在一個servlet的請求中,響應的方式的通常有四式,response.getWriter(),response.getOutputStream(),
request.getRequestDispatcher("ajax.jsp").forward(request, response) 和 response.sendRedirect("ajax.jsp") 。
其中
- response.getWriter() 輸出頁面
- response.getOutputStream() 輸出二進制流檔案
- request.getRequestDispatcher("ajax.jsp").forward(request, response) 頁面跳轉
- response.sendRedirect("ajax.jsp") 重定向
這四種方式單獨使用,大家應該都很熟悉,如果一個servlet裡面寫了兩種響應,會出現什麼情況呢,今天看一下寫兩個響應的現象分析。
servlet的四種響應
getWriter
getWriter 傳回可将字元文本發送到用戶端的
PrintWriter
對象。
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 單獨這一塊,輸出Welcome to Servlet
PrintWriter out = response.getWriter();
out.println("<body><h1>");
out.println("Welcome to Servlet");
out.println("</h1></body>");
}
輸出
getOutputStream
zh_cn |
getOutputStream 傳回适用于在響應中編寫二進制資料的
ServletOutputStream
。
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
OutputStream os = response.getOutputStream();
InputStream is = new FileInputStream(new File("D:\\pic\\P41004-154736.jpg"));
byte[] buf = new byte[1024];
while (is.read(buf) > 0) {
os.write(buf);
}
os.flush();
is.close();
os.close();
}
輸出
getRequestDispatcher("ajax.jsp").forward(request, response)
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getRequestDispatcher("ajax.jsp").forward(request, response);
}
跳轉到 ajax.jsp頁面
sendRedirect("ajax.jsp")
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.sendRedirect("ajax.jsp");
}
重定向到ajax.jsp頁面
上面采用forward跳轉的時候,位址欄顯示的是res請求,使用redirect重定向之後,等于重新發送了一個ajax.jsp的請求,URL位址欄變為了ajax.jsp
兩個響應情況
一個servlet請求會有一個request請求和一個response響應,那如果一個response想響應兩次呢?一般都是會出錯的。代碼中避免使用多個響應的情況。
getWriter和getOutputStream
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter out = response.getWriter();
out.println("<body><h1>");
out.println("Welcome to Servlet");
out.println("</h1></body>");
OutputStream os = response.getOutputStream();
InputStream is = new FileInputStream(new File("D:\\pic\\P41004-154736.jpg"));
byte[] buf = new byte[1024];
while (is.read(buf) > 0) {
os.write(buf);
}
os.flush();
is.close();
os.close();
}
輸出
抛出 getWriter() has already been called for this response 異常資訊
上面介紹了單獨使用getWriter和 getOutputStream的情況,分别傳回響應頁面和二進制流檔案。
這兩個方法都有幾個共同的異常資訊,IOException 和 IllegalStateException。
getWriter的IllegalStateException異常描述:if the
getOutputStream
method has already been called for this response object
getOutputStream的IllegalStateException異常描述:if the
getWriter
method has been called on this response
這個IllegalStateException資訊說明,這兩個響應不可以同時使用,否則會出現IllegalStateException。
getWriter和forward
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 單獨這一塊,輸出Welcome to Servlet
PrintWriter out = response.getWriter();
out.println("<body><h1>");
out.println("Welcome to Servlet");
out.println("</h1></body>");
request.getRequestDispatcher("ajax.jsp").forward(request, response);
}
輸出
沒有輸出Welcome to Servlet ,直接跳轉到了ajax.jsp頁面
getWriter和redirect
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 單獨這一塊,輸出Welcome to Servlet
PrintWriter out = response.getWriter();
out.println("<body><h1>");
out.println("Welcome to Servlet");
out.println("</h1></body>");
// 帶上response.sendRedirect 時,直接跳轉到ajax.jsp
response.sendRedirect("ajax.jsp");
}
輸出
通過上面的getWriter和forward的例子和這裡的getWriter和redirect的例子可以看出,getWriter隻向頁面輸出内容,但并沒有送出(commit)該響應。後續有可以送出響應的響應代碼時,會覆寫掉getWriter的響應輸出。
将上面的代碼做一點修改,添加一行代碼out.flush();
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 單獨這一塊,輸出Welcome to Servlet
PrintWriter out = response.getWriter();
out.println("<body><h1>");
out.println("Welcome to Servlet");
out.println("</h1></body>");
out.flush();
request.getRequestDispatcher("ajax.jsp").forward(request, response);
}
out.flush() 方法會送出掉該response響應,此時頁面響應為
同時,背景會出現異常
java.lang.IllegalStateException: Cannot forward after response has been committed
at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:348)
at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:338)
getOutputStream和forward
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
OutputStream os = response.getOutputStream();
InputStream is = new FileInputStream(new File("D:\\pic\\P41004-154736.jpg"));
byte[] buf = new byte[1024];
while (is.read(buf) > 0) {
os.write(buf);
}
os.flush();
is.close();
os.close();
request.getRequestDispatcher("ajax.jsp").forward(request, response);
}
前台頁面依然出現
同時背景會出現
嚴重: Servlet.service() for servlet [com.test.ResTest] in context with path [/servletDemo] threw exception
java.lang.IllegalStateException: Cannot forward after response has been committed
at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:348)
at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:338)
at com.test.ResTest.doPost(ResTest.java:52)
at com.test.ResTest.doGet(ResTest.java:34)
RequestDispatcher 類的forward方法有個
IllegalStateException
異常
異常資訊這樣描述:if the response was already committed ,如果響應已經被送出。
這裡例子說明getOutputStream,對前台進行了響應,并且送出了該響應。
getOutputStream和redirect
出現與getOutputStream和forward中同樣的結果,前台展現,背景出錯
forward和redirect
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getRequestDispatcher("ajax.jsp").forward(request, response);
response.sendRedirect("ajax.jsp");
}
輸出
這個異常資訊與前面的相同,就不再做分析了。
經過上面的幾個同時兩個響應的例子,可以看出,一個servlet請求隻能有一個響應,任何多個響應的代碼都是錯誤的,都會出現
IllegalStateException
。也就是說,多個響應的場景是非法的,一個servlet一個響應就可以了,是它的标配。
上面的内容純屬個人總結,若有描述不詳盡的地方或錯誤地方,煩請提出,謝謝。