HttpServletResponse
第一章 HTTP响应详解
前面的文章我们学习了HTTP请求协议及HttpServletRequest对象,今天我们来学习HTTP协议中的另一部分:HTTP响应协议及HttpServletResponse对象。
1、HTTP响应报文
HTTP是基于请求和响应的协议,一次请求对应一次响应。请求和响应的数据格式都遵从HTTP的超文本传输协议。与HTTP的请求一样,HTTP响应的数据也分为3部分:响应行 ,响应头 ,响应体 这3部分组成。请求是通过浏览器将数据传送到服务器,而响应是将服务器处理的结果回送到浏览器。
2、使用抓包工具查看响应数据
创建一个web项目,在web项目的web文件夹下创建一个hello.html页面。将下面的代码复制到hello.html页面中,启动项目,通过:
url:http://localhost:8080/hello.html访问这个页面。使用chrome工具抓包。
【示例】hello.html静态页面
xml复制代码<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <h2>get请求</h2> <form action="/getServlet" method="get"> 用户名:<input type="text" name="username" value="suoge" /> <br/> 密码:<input type="text" name="password" value="1234" /> <br/> <input type="submit" value="get提交" /> </form> <h2>post请求</h2> <form action="/postServlet" method="post"> 用户名:<input type="text" name="username" value="suoge" /> <br/> 密码:<input type="text" name="password" value="1234" /> <br/> <input type="submit" value="post提交" /> </form> </body> </html>
分别创建GetServlet和PostServlet,代码如下:
GetServlet的代码如下:
scala复制代码@WebServlet("/getServlet") public class GetServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //给浏览器响应数据 response.getWriter().print("hello response"); } }
PostServlet的代码如下:
scala复制代码@WebServlet("/postServlet") public class PostServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //给浏览器响应数据 response.getWriter().print("hello response"); } }
抓取的响应报文如下图所示:
说明:
1)由于浏览器的原因,浏览器会把请求行和响应行信息放在了一起;
2)get和post请求的响应没有区别;
【响应行】
响应行格式:协议/版本 状态码
如:HTTP/1.1 200 ;
常见状态码:
状态码 |
状态码描述 |
说明 |
200 |
OK |
请求已成功,请求所希望的响应头或数据体将随此响应返回。出现此状态码是表示正常状态。 |
302 |
Move temporarily |
重定向,请求的资源临时从不同的 地址响应请求。 |
304 |
Not Modified |
从浏览器缓存中读取数据,不从服务器重新获取数据。例如,用户第一次从浏览器访问服务器端图片资源,以后在访问该图片资源的时候就不会再从服务器上加载而直接到浏览器缓存中加载,这样效率更高。 |
404 |
Not Found |
请求资源不存在。通常是用户路径编写错误,也可能是服务器资源已删除。 |
403 |
Forbidden |
服务器已经理解请求,但是拒绝执行它 |
405 |
Method Not Allowed |
请求行中指定的请求方法不能被用于请求相应的资源 |
500 |
Internal Server Error |
服务器内部错误。通常程序抛异常 |
【响应头】
响应头也是用的键值对key:value,服务器基于响应头通知浏览器的行为。
常见的响应头 :
响应头Key |
响应头value |
location |
指定响应的路径,需要与状态码302配合使用,完成重定向 |
content-Type |
响应正文的类型(MIME类型,属于服务器里面的一种类型,例如文件在window系统有自己的类型,.txt .doc .jpg。文件在服务器中也有自己的类型),同时还可以解决乱码问题。例如:text/html;charset=UTF-8 |
content-disposition |
通过浏览器以附件形式解析正文,例如:attachment;filename=xx.zip |
refresh |
页面刷新,例如:3;url=www.itcast.cn //三秒刷新页面到www.itcast.cn |
说明:
MimeType:标识数据类型
bash复制代码最早的HTTP协议中,并没有附加的数据类型信息,所有传送的数据都被客户程序解释为超文本标记语言HTML 文档,而为了支持多媒体数据类型,HTTP协议中就使用了附加在文档之前的MIME数据类型信息来标识数据类型。 MIME意为多功能Internet邮件扩展,它设计的最初目的是为了在发送电子邮件时附加多媒体数据,让邮件客户程序能根据其类型进行处理。然而当它被HTTP协议支持之后,它的意义就更为显著了。它使得HTTP传输的不仅是普通的文本,而变得丰富多彩。 每个MIME类型由两部分组成,前面是数据的大类别,例如声音audio、图象image等,后面定义具体的种类。 常见的MIME类型(通用型): windows tomcat 超文本标记语言文本 .html text/html *** xml文档 .xml text/xml XHTML文档 .xhtml application/xhtml+xml 普通文本 .txt text/plain *** PDF文档 .pdf application/pdf Microsoft Word文件 .word application/msword PNG图像 .png image/png *** GIF图形 .gif image/gif JPEG图形 .jpeg,.jpg image/jpeg ......
【响应体】
响应体,就是服务器发送给浏览器的数据。当前浏览器向服务器请求的资源是hello.html,所以服务器给浏览器响应的数据是一个html页面。
请求资源路径:
响应结果:
如果请求是servlet,那么浏览器的响应体接收到的是servlet响应的数据:
总结:
响应行:协议版本号 状态码 200(一切正常) 404(找不到资源路径) 500(服务器报异常) 302(和location一起使用,实现重定向) 304(从浏览器缓存中读取数据) 405(服务器的servlet没有重写doGet和doPost方法)
响应头:
location 指定响应的路径
content-type:告诉浏览器文件格式,告诉浏览器不要解析html文件,解决中文乱码问题
refresh 定时刷新
content-disposition 以附件形式展示图片等资源
响应体:
服务器处理的结果响应到浏览器中
第二章 HttpServletResponse对象
遇到问题 : 服务器接受客户端的请求之后,处理请求之后,服务器如何将对应的数据响应给客户端呢?
解决方案 : 一切皆对象,Servlet程序接受客户端请求之后,通过HttpServletResponse对象来完成向客户端的响应。
通过该对象,将数据返回给客户端。
1、HttpServletResponse对象作用
HttpServletResponse对象代表服务器响应,tomcat创建HttpServletResponse对象,并将该对象作为参数传递给servlet的service方法。
这个对象的作用:
设置响应行、头、体
下面,就这几方面对HttpServletResponse对象的常用API进行详细讲解。
2、HttpServletResponse对象常用API
2.1【响应行】
响应行:协议/版本 如:HTTP/1.1 200 。这里边的信息,我们通常只会用到状态码,操作状态码的方法setStatus(int code);
方法 |
说明 |
setStatus(int code) |
向浏览器发送状态码 |
【常用状态码】
对应的状态码响应状态码常量 |
说明 |
200 |
响应成功 |
404 |
资源路径错误或资源被删除 |
500 |
服务器内部错误 |
302 |
重定向 |
2.2 【响应头】
方法 |
说明 |
setHeader(String name,String value) |
设置响应头信息 |
【常见响应头】
响应头Key |
响应头value |
refresh |
页面刷新,例如:3;url=www.itcast.cn //三秒刷新页面到www.itcast.cn |
content-type |
设置响应数据的类型(MIME类型) 和编码格式 例如:text/html;charset=UTF-8 |
location |
指定响应的路径,需要与状态码302配合使用,完成重定向。 |
content-disposition |
通过浏览器以附件形式解析正文,例如:attachment;filename=xx.zip。 |
2.2.1.常见响应头
【练习】响应头---定时刷新
需求:1. 访问到Servlet类3秒后跳转到百度;
scala复制代码@WebServlet("/refreshServlet") public class RefreshServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //实现refresh关键字跳转功能 响应头API //方法具有2个参数 关键字 跳转地址 response.setHeader("refresh","3;url=http://www.baidu.com"); } }
浏览器输入地址:
http://localhost:8080/refreshServlet
注意:3秒以后自动跳转到百度主页,前提你要联网啊。
【练习】content-type 设置响应数据的类型。告诉浏览器不要解析html格式数据。
scala复制代码@WebServlet("/contentServlet") public class ContentServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //告诉浏览器不要解析html格式数据 //每次写这些方法,代码太多,而且API还经常使用 setContentType(text/plain) // response.setHeader("content-type","text/plain"); response.setContentType("text/plain"); response.getWriter().print("<html><body><h1>itcast</h1></body></html>"); } }
说明:text/plain的意思是将文件设置为纯文本的形式,浏览器在获取到这种文件时并不会对其进行处理。
抓包查看浏览器信息:
效果图:
2.2.2.处理响应乱码
2.2.2.1乱码产生的原因
服务器如果需要响应给浏览器中文数据,tomcat使用getWriter()输出字符时,对于中文需要进行编码处理,而tomcat8 默认编码是ISO-8859-1,该码表是不支持中文编码的。所以响应给浏览器,出现乱码。
代码如下:
css复制代码 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.getWriter().print("<html><body><h1>程序员</h1></body></html>"); }
2.2.2.2响应乱码解决方案
因为HttpServletResponse实现类是由tomcat服务器提供的。所以服务器在向浏览器输出数据之前,对于中文要采用支持中文的编码进行编码,通过response.setContentType("text/html;charset=utf-8"); :
- 设置响应的数据类型(text/html);
- 设置响应的数据编码(utf-8);
2.2.2.3处理响应乱码的API
方法 |
说明 |
response.setHeader("content-type","text/html;charset=utf-8"); |
设置响应头 |
response.setContentType("text/html;charset=utf-8"); |
简写方式 |
【注意事项】
- 开发中通常使用response.setContentType("text/html;charset=utf-8");来处理响应乱码;
- 处理响应乱码必须书写在响应数据之前才起作用;
【练习】content-type 设置响应数据的类型和编码
scala复制代码@WebServlet("/encodeServlet") public class EncodeServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //设置响应头:content-type //乱码产生的原因:编解码不一致 //tomcat的编码是:ISO-8859-1 //通过设置响应头 //1.设置响应的数据格式; //2.设置响应数据的编码格式; // response.setHeader("content-type","text/html;charset=utf-8"); //简化API response.setContentType("text/html;charset=utf-8"); response.getWriter().print("程序员"); } }
效果图:如果没有进行响应乱码的处理,则浏览器显示的是乱码.处理之后的效果如下所示:
2.2.3.重定向(掌握)
【重定向原理分析】
【重定向API】: 重定向可以去一个servlet,也可以去一个html静态资源.
方法 |
说明 |
response.setStatus(302); response.setHeader("location", "/otherServlet"); |
通过设置响应状态码和响应头实现重定向 |
response.sendRedirect("/otherServlet"); |
重定向的简写方式 |
【注意事项】
- 开发中通常使用response.sendRedirect("/otherServlet");来实现重定向。
【练习】通过设置响应头location和响应行的状态码302完成重定向。
方法:
arduino复制代码 //方式一: //location+302 共同完成重定向 response.setHeader("location", "url"); //响应行 response.setStatus(302); //方式二: //简化的API response.sendRedirect("url");
班长的servlet,【MonitorServlet.java】:
scala复制代码@WebServlet("/monitorServlet") public class MonitorServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //使用重定向 // response.setHeader("location","/suogeServlet"); // response.setStatus(302); response.sendRedirect("/suogeServlet"); } }
【SuogeServlet.java】
scala复制代码@WebServlet("/suogeServlet") public class SuogeServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //处理响应乱码 response.setContentType("text/html;charset=utf-8"); response.getWriter().print("一起学习Java"); } }
浏览器地址栏输入访问网站效果:
http://localhost:8080/monitorServlet
回车之后,浏览器地址栏变为:
2.3、转发和重定向的区别
完成重定向操作之后,同学们心里有一个疑问:之前学习的转发和现在的重定向都可以完成跳转,都可以跳转到一个servlet,也可以跳转到一个html静态资源,功能相同。那么他们之间有什么区别呢?
【转发和重定向区别】
转发和重定向的另一种解释:
2.3.1、转发和重定向的区别
区别点 |
转发 |
重定向 |
实现原理 |
服务器内部 |
浏览器执行 |
请求次数 |
一次 |
两次 |
浏览器地址栏地址 |
不变化 |
变为第二次请求的地址 |
能否共享request域 |
能够共享 |
不能共享 |
作用 |
共享request域对象 |
完成跳转 |
2.3.2、转发和重定向怎么选择
- 如果需要共享request域,必须使用转发;
- 如果需要将浏览器地址栏地址变为第二次请求的地址,必须使用重定向;
作者:also_lucky