天天看點

servlet的四種響應servlet的四種響應兩個響應情況

        在一個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>");
		
	}
           

輸出

servlet的四種響應servlet的四種響應兩個響應情況

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();
		
	}
           

輸出

servlet的四種響應servlet的四種響應兩個響應情況

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頁面

servlet的四種響應servlet的四種響應兩個響應情況

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頁面

servlet的四種響應servlet的四種響應兩個響應情況

       上面采用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();
		
	}
           

輸出

servlet的四種響應servlet的四種響應兩個響應情況

抛出 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);
		

	}
           

輸出

servlet的四種響應servlet的四種響應兩個響應情況

沒有輸出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");
	}
           

輸出

servlet的四種響應servlet的四種響應兩個響應情況

    通過上面的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響應,此時頁面響應為

servlet的四種響應servlet的四種響應兩個響應情況

同時,背景會出現異常

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的四種響應servlet的四種響應兩個響應情況

同時背景會出現

嚴重: 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的四種響應servlet的四種響應兩個響應情況

這個異常資訊與前面的相同,就不再做分析了。

    經過上面的幾個同時兩個響應的例子,可以看出,一個servlet請求隻能有一個響應,任何多個響應的代碼都是錯誤的,都會出現

IllegalStateException

。也就是說,多個響應的場景是非法的,一個servlet一個響應就可以了,是它的标配。

上面的内容純屬個人總結,若有描述不詳盡的地方或錯誤地方,煩請提出,謝謝。

繼續閱讀