servlet的四种响应

标签: servlet | 发表时间:2015-04-26 01:41 | 作者:magi1201
出处:http://blog.csdn.net


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


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

作者:magi1201 发表于2015/4/25 17:41:19 原文链接
阅读:44 评论:0 查看评论

相关 [servlet] 推荐:

Servlet Filter 学习

- - CSDN博客架构设计推荐文章
最近在研究CAS , CAS 中的Servlet Filter 不太熟悉, 所以花了点时间学下了下这部分的知识, 分成以下几部分 学习. Servlet Filter  的功能和用法. Servlet Filter 顺序的注意事项. A filter is an object that performs filtering tasks on either the request to a resource (a servlet or static content), or on the response from a resource, or both.

Servlet、Filter和Listener

- - Web前端 - ITeye博客
Java Servlet是与平台无关的服务器端组件,运行于Servlet容器中(如Tomcat),Servlet容器负责Servlet和客户端的通信以及调用Servlet的方法,Servlet和客户端的通信采用“请求/响应”的模式. Servlet可完成以下功能:. 1、创建并返回基于客户请求的动态HTML页面.

Servlet – 会话跟踪

- - ImportNew
HTTP本身是 “无状态”协议,它不保存连接交互信息,一次响应完成之后即连接断开,下一次请求需要重新建立连接,服务器不记录上次连接的内容.因此如果判断两次连接是否是同一用户, 就需要使用 会话跟踪技术来解决.常见的会话跟踪技术有如下几种:. URL重写: 在URL结尾附加. 会话ID标识,服务器通过会话ID识别不同用户..

servlet的四种响应

- - CSDN博客推荐文章
        在一个servlet的请求中,响应的方式的通常有四式,response.getWriter(),response.getOutputStream(),. request.getRequestDispatcher("ajax.jsp").forward(request, response) 和 response.sendRedirect("ajax.jsp").

Servlet是否线程安全

- - 研发管理 - ITeye博客
Servlet是线程安全吗. 要解决这个问题,首先要知道什么是线程安全:.   如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码. 如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的. 或者说:一个类或者程序所提供的接口对于线程来说是原子操作或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题.

Servlet 3.0的檔案上傳寫法

- - 簡睿隨筆
Servlet 3.0已經大幅簡化網頁檔案上傳的程式寫法,以下是撰寫的幾個重點.
的enctype要是"multipart/form-data". 是主要使用的檔案瀏覽元素. 後端接收的Servlet寫在action屬性裡. 以@MultipartConfig(location = “c:/www/xxx/data/")指定寫檔路徑.

jsp+servlet实现验证码功能

- - CSDN博客推荐文章
验证码的功能大多数人可能不都理解,但几乎每个安全网站都会有. 验证码是用来防止非人为因素操作的行为,例如一个黑客要黑一个网站,怎么弄呢. 最简单的思路当然是造成其网路拥堵直至系统瘫痪掉. 如果没有验证码,那么我就可以在注册页面,写一个程序,只有注册表单,不断更换主键或不可重复的内容,不停的提交. 那这样每秒可以注册几万次都有可能,这样服务器就大量负载,很容易就瘫痪并死掉.

基于uploadify上传和 servlet 的下载

- - CSDN博客推荐文章
由于工作需要 暂时快速的选定了uploadify作为文件上传插件. 至于下载就匆忙的用servlet来实现. 首先到uploadify官网下载需要的Js文件. 然后需要自己手写一个Js 来调用 uploadify.js 重点只说上传 其他辅助功能方法不细说.                         'buttonText' : '添加附件',.

【转】Servlet 和filter 执行顺序

- - 企业架构 - ITeye博客
一,servlet容器对url的匹配过程:. 当一个请求发送到servlet容器的时候,容器 先会将请求的url减去当前应用上下文的路径作为servlet的映射url,比如我访问的是http://localhost/test /aaa.html,我的应用上下文是test,容器会将http://localhost/test去掉,剩下的/aaa.html部分拿来做 servlet的映射匹配.

Servlet实现图形验证码

- - CSDN博客推荐文章
|-- 配置开发图形验证码Servlet. // 设置响应头 Content-type类型. // 以下三句是用于设置页面不缓存. // 建立指定宽、高和BufferedImage对象. Graphics g = image.getGraphics(); // 该画笔画在image上. Color c = g.getColor(); // 保存当前画笔的颜色,用完画笔后要回复现场.