Servlet的学习之Response响应对象(3)
本篇来说明响应对象HttpServletResponse对象的最后一点内容。
首先来看响应对象控制浏览器定时刷新,在我的web应用【myservlet】中创建Servlet,在该Servlet中设置响应头,定时刷新的代码很简单:
response.setHeader("refresh", "3 "); //3秒刷新一次
就可告知浏览器3秒刷新一次网页。当然“Refresh”响应头还是可以定时跳转到指定页面,如下代码:
response.setHeader("refresh", "3;url='/myservlet/index.jsp'");
将会在访问我这个Servlet的3秒后访问我的【myservlet】web应用下的index.jsp资源。
之前说过,使用<meta>标签可以模拟响应头,同样在这里可以使用Servlet向客户端写数据时将<meta>标签写入响应数据实体,由浏览器解析后再来控制:
1 String data = "银魂"; 2 response.setContentType("text/html;charset=UTF-8"); 3 response.getWriter().write("<meta http-equiv='refresh' content='3;url=/myservlet/index.jsp' >"); 4 response.getWriter().write(data);
这里请注意:在向响应对象写入任何数据之前,请先设置好使用的编码表,如果在写入数据之后再设置编码表则无效,例如下面代码:
1 String data = "银魂"; 2 response.getWriter().write(data); 3 response.setContentType("text/html;charset=UTF-8");
通过查看HttpWathch可以知道,编码表并没有设置成功:
把设置编码表的代码放置在向响应对象写入数据也是不行的,如下:
1 String data = "银魂"; 2 response.getWriter().write("<meta http-equiv='refresh' content='3;url=/myservlet/index.jsp' >"); 3 response.setContentType("text/html;charset=UTF-8"); 4 response.getWriter().write(data);
这样也会设置编码表无效,造成中文乱码问题,所以在向响应对象写入任何数据之前请确保先将编码表设置好。
请求重定向:之前在http协议中学习了响应码302和“Location”响应头可以设置请求重定向。
一个简单的代码示例(web工程名为【myservlet】):
1 response.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY); //302状态码 2 response.setHeader("location", "/myservlet/index.jsp");
对于不太熟悉HTTP协议的编程人员来说,当然还有更快捷的方式:
1 response.sendRedirect("/myservlet/index.jsp");
验证:在浏览器中的地址栏中键入该Servlet的地址,浏览器则是会跳转至该web目录下的index.jsp,这个可以从浏览器地址栏上看出。
关于请求重定向中的细节:
一次请求重定向会向服务器发送两次请求。也就是说会产生两次response响应对象和request请求对象;同时浏览器的地址栏是会发生变化的,URL将跳转到重定向后的页面地址。这点和转发不同(在《Servlet的学习(五)》中说过)。
最后再回到response响应对象的getOutputStream方法和getWriter方法,这两个方法在《Servlet的学习(七)》中已经详细介绍了解决中文乱码问题,那么现在我们还需要注意的是:getOutputStream方法和getWriter方法这两个方法相互排斥,不能同时使用。否则会出现如下问题:
也许大家会瞧不起这个问题,认为不就是在一个Servlet中不要同时使用字节流和字符流嘛,注意下就好了。
问题当然不会这么简单,比如在转发中使用不同的IO流还是会出现这种问题的:
假设我的【myservlet】这个web工程中有两个Servlet:ServletResponse1和ServletResponse2。
在ServletResponse1中的代码为:
1 response.getWriter(); 2 RequestDispatcher dispatcher = this.getServletContext().getRequestDispatcher("/WEB-INF/classes/ServletResponse2"); 3 dispatcher.forward(request, response);
在ServletResponse2中的代码为:
1 response.getOutputStream();
那么结果是直接部署出错:
在ServletResponse1中将Response对象传递给ServletResponse2中,本身Response就已经调用了获取Writer对象的方法,因此不能再在ServletResponse2中获取OutputStream对象,所以在做转发时要特别注意获得IO流对象。
而将Servlet调用getOutputStream()方法后再转发给JSP文件也是会出错的
比如在ServletResponse1中代码为:
1 OutputStream out = response.getOutputStream(); 2 RequestDispatcher dispatcher = this.getServletContext().getRequestDispatcher("/index.jsp"); 3 dispatcher.forward(request, response);
而访问这个Servlet会看到:
这是因为在Servlet向JSP中写入数据时默认使用了getWriter()方法获取字符流,然后向JSP中写入数据,这时如果我们在转发JSP之前的Servlet再使用getOutputStream必然会产生冲突。如果想向JSP中传入的必须是使用字节流才能传输的数据,请查验相关解决方案。