天天看点

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一个响应就可以了,是它的标配。

上面的内容纯属个人总结,若有描述不详尽的地方或错误地方,烦请提出,谢谢。

继续阅读