Servlet笔记——(3.1)关于HTTPServletResponse详解

服务器处理请求的流程:

(1) 服务器每次收到请求时,都会为这个请求开辟一个新的线程;

(2) 服务器会把客户端的请求数据封装到request对象中,request就是请求数据的载体;

(3) 服务器还会创建response对象,这个对象与客户端连接在一起,它可以用来向客户端发送响应。


3.1.1 HttpServletResponse概述

ServletResponse:与协议无关的类型;HttpServletResponse:与http协议相关的类型。

response是Servlet#service(ServletRequest, ServletResponse) 方法的一个参数,类型为javax.servlet.ServletResponse;

在客户端发出每个请求时,服务器都会创建一个response对象,并传入给Servlet#service(ServletRequest, ServletResponse)方法;

response对象是用来对客户端进行响应的,这说明在service(ServletRequest, ServletResponse) 方法中使用response对象可以完成对客户端的响应工作;

接口ServletResponse的定义可参考“JSP内置对象之response对象”,“response”对象的原型即实现了此接口。

3.1.2 HTTP响应协议

响应首行;响应头(头名-头值);空行;响应体。

响应内容是由服务器发送给浏览器的内容,浏览器会根据响应内容来显示。


Status-Line) HTTP/1.1 200 OK

Server Apache-Coyote/1.1

Content-Type text/html;charset=UTF-8

Content-Length 740

Date Mon, 12 Jan 2015 12:46:23 GMT


3.1.3 状态码

l 200:请求成功,浏览器会把响应体内容(通常是html)显示在浏览器中;

l 404:请求的资源没有找到,说明客户端错误请求了不存在的资源;

l 500:请求资源找到了,但服务器内部出现了错误;

l 302:重定向,当响应码为302时,表示服务器要求浏览器重新再发一个请求,服务器会发送一个响应头Location,它指定了新请求URL地址。

示例代码:

public class BServlet extends HttpServlet {
	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
		throws ServletException, IOException {
		response.setStatus(200);
		response.sendError(404, "您要访问的资源不存在");
		response.sendError(404);
	}
}

3.1.4 响应头

使用response对象的setHeader()方法来设置响应头(头就是键值对,可能存在一个头:一个名称一个值;也可能存在多个头:一个名称多个值),使用该方法设置的响应头最终会发送给客户端浏览器。比如:content-Type、Refresh、Location等。

测试代码:

public class BServlet extends HttpServlet {	
	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
		throws ServletException, IOException {		
		response.setHeader("a", "AA");	// 单值		
		response.addHeader("b", "BB");	// 多值
		response.addHeader("b", "BBB");		
		response.setIntHeader("c", 100);			
		response.setDateHeader("d", System.currentTimeMillis());
	}
}

3.1.4.1 302

重定向是服务器通知浏览器去访问另一个地址,即再发出另外一个请求。操作步骤如下:

    1. 响应码为302表示重定向,所以完成重定向的第一步就是设置响应码为302;

2. 重定向是通知浏览器发送第二个请求,即服务器需要告知浏览器第二个URL请求的地址,所以完成重定向的第二步是设置Location头,用以指定第二次请求的URL地址。


示例代码

public class AServlet extends HttpServlet {	
	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {		
		// 重定向路径中的"/":表示客户端的根"http://locahost:8080/"		  			  					response.setStatus(302);
		response.setHeader("Location", "/servlet/BServlet");	// 访问BServlet  【URI】		  	
		response.getWriter().print(this);
	}		
}

上述代码的作用是:当访问完AServlet后,会通知浏览器重定向到BServlet。客户端浏览器解析到响应码位302后,就知道服务器让它重定向,所以它会马上获取响应头Location,然后发出第二个请求。



3.1.4.2 Refresh

设置Refresh头,可以理解为“定时重定向(刷新)”。

response.setContentType("text/html;charset=utf-8");
response.getWriter().println("欢迎回来,5秒钟后跳转到百度主页");
response.setHeader("Refresh", "5;url=http://www.baidu.com");	    // url=/servlet/BServlet

3.1.4.3 禁用浏览器缓存

Cache-Control、pragma、expires

response.setHeader("Cache-control", "no-cache");
response.setHeader("pragma", "no-cache");
response.setDateHeader("expires", -1);

注意:meta标签可以代替相应头:





3.1.4.4 响应类型(字符集)

设置响应类型/字符集。

(1) JSP页面定义:

(2) 等价于Servlet中定义响应头:

response.setContentType("text/html");    // MIME类型,参考%CATALINA%/conf/web.xml设置信息
response.setCharacterEncoding("utf-8")

(3) 等价于Sevlet中定义响应头:

response.setContentType("text/html;charset=utf-8");

(4) 等价于Servlet中定义响应头:

response.setHeader("content-type", "text/html;charset=utf-8")

设置content-type响应头,作用是告诉浏览器响应内容类型为html类型,同时设置response的字节流编码为utf-8。

在HTML页面中可以使用来指定响应头,例如在index.html页面中给出,表示浏览器只会显示index.html页面3  

秒,然后自动跳转到http://www.baidu.com。  response.setHeader(“Refresh”, “3;url=http://www.baidu.com”)


3.1.5 响应体

响应体(响应正文)通常是html,也可以是图片等。

response是响应对象,向客户端输出响应正文(响应体)可以使用response的响应流,response提供了两个响应流对象:

(1) PrintWriter out = response.getWriter():获取字符流,用来向客户端发送字符数据,需要设置编码;

(2) ServletOutputStream out = response.getOutputStream():获取字节流,用来向客户端发送字节数据。

注意在一个请求中,不能同时使用这两个流!也就是说,要么使用response.getWriter(),要么使用response.getOutputStream(),但不能同时使用这两个流,否则会抛出IllegalStateException异常。

示例代码:使用ServletOutputStream发送字节数据(图片)

public class AServlet extends HttpServlet {	
	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		ServletContext application = this.getServletContext();		
		// 在WebRoot/images/555.jpg
		InputStream is = application.getResourceAsStream("/images/555.jpg");		
		// 导入commons-io.jar(拷贝到MyEclipse – WebRoot – WEB-INF - lib)
		response.getOutputStream().write(IOUtils.toByteArray(is));  // InputStream --> byte[]
	}		
}



字符(流)编码

在使用response.getWriter()时需要注意默认字符编码是ISO-8859-1,如果希望设置字符流的编码为UTF-8,可以使用response.setCharacterEncoding(“utf-8”)来设置,这样可以保证输出给客户端的字符都是使用UTF-8编码的。

但客户端浏览器并不知道响应数据是什么编码的。如果希望通知客户端使用UTF-8来解读响应数据,那么还是使用response.setContentType(“text/html;charset=utf-8”)方法比较好,因为这个方法不仅调用response.setCharacterEncoding(“UTF-8”),还会设置content-type响应头,客户端浏览器会使用content-type头来解读响应数据。

字符流缓冲区

response.getWriter()是PrintWriter类型,所以它有缓冲区,缓冲区的默认大小是8KB。也就是说在响应数据没有输出8KB之前,数据都是存放在缓冲区中,而不是立刻发送到客户端。当Servlet执行结束后,服务器才会去刷新流,使缓冲区中的数据发送到客户端。

如果希望响应数据马上发送给客户端:(1)向流中写入大于8KB的数据;(2)调用response.flushBuffer()方法来手动刷新缓冲区。

3.1.6 重定向

客户端重定向response.sendRedirect(String URL)方法会设置响应头为302,同时设置Location响应头。服务器实际上已经向客户端产生了(302)响应,客户端(即浏览器)根据响应的HTTP Header中包含的Redirect地址,向服务器重新发起一个(GET方式)请求。需要注意的是,重定向发出的GET请求与最开始的那个请求不是同一个请求,这也意味着,在前一个请求中调用setAttribute()放进去的数据已经丢失!

public class AServlet extends HttpServlet {
	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.sendRedirect(request.getContextPath() + "/hello/BServlet");  // 重定向的URL地址为:http://localhost/hello/BServlet
	}
}

【重定向小结】

(1) 重定向是两次请求;

(2) 重定向的URL可以是其他应用,不局限于当前应用;

(3) 重定向的响应头是302,并且必须要有Location的响应头;

(4) 重定向就不要在使用response.getWriter()或response.getOutputStream()输出数据,不然可能会出现异常。




你可能感兴趣的:(Servlet笔记)