前 言
人总是要有梦想的,也许哪天就实现了呢!
如果有不正确之处,还望指正,毕竟我还是一个菜鸟!
一、HTTP 协议
在之前的一篇文章中,提到了HTTP 协议的请求部分,这次我们讲解HTTP 的响应部分。
-
响应行:
-
组成:协议/版本 响应状态码 状态码描述
-
响应状态码:服务器告诉客户端浏览器本次请求和响应的一个状态,状态码都是3位数字组成。状态码分类如下:
1xx:服务器接收客户端消息,但是接收没有完成,等待了一段时间后,向客户端发送1xx状态码 2xx:成功。代表的是200 3xx:重定向。代表:302(重定向),304(访问缓存) 4xx:客户端错误。代表:404(请求路径没有对应的资源),405(请求方式没有对应的doXxx方法) 5xx:服务器错误。代表:500(服务器内部出现异常)
-
-
响应头:
-
格式:
头名称:值
-
常见的响应头:
Content-Type:服务器告诉客户端本次响应体数据格式以及编码格式 Content-disposition:服务器告诉客户端以什么格式打开响应体数据
-
-
响应空行:
-
响应体:传输的数据
响应信息
二、Response 对象
1、设置响应消息
当客户从浏览器发起请求时,在访问成功的情况下,服务器就需要作出响应,所以我们就需要设置响应消息,来传给客户端浏览器。
-
设置响应行:
- 格式:
HTTP/1.1 200 ok
- 设置状态码:
setStatus(int sc)
- 格式:
-
设置响应头:
setHeader(String name, String value)
-
设置响应体:具体步骤如下:
-
获取输出流:
1. PrintWriter getWriter() - 字符输出流 2. ServletOutputStream getOutputStream() - 字节输出流
-
使用输出流,将数据输出到客户端浏览器
-
2、重定向(Redirect)
- 概述:重定向就是不对本次请求进行业务处理,而是跳转到指定的URL进行处理业务,在这期间,浏览器发起了两次请求。举例:这就相当于你去1号窗口办理事务,但是1号窗口不能办理并且告诉你3号窗口能够办理你的业务,这时候你就自己去了3号窗口,找3号窗口的业务员替你办理业务。在这个过程中,你去了两个窗口,向不同的业务员发起请求。这里的业务员就相当于URL。
- 特点:
- 重定向是两次请求,地址栏发生改变。并且不能使用request对象来共享数据。
- 重定向可以访问其他站点的资源,即可以跳转到网络资源中。
- 重定向的路径需要加入虚拟目录。
- 方法:
sendRedirect(String URL)
- 路径写法:
- 相对路径:通过相对路径的方式,不能够确定唯一资源,如:
../index.html
- 绝对路径:通过绝对路径可以确定唯一资源,如:
http://localhost/servlet/responseDemo
- 相对路径:通过相对路径的方式,不能够确定唯一资源,如:
3、Redirect 与 Forward 区别
- 重定向是两次请求,都是从浏览器出发;请求转发是一次请求,转发在服务器内部进行。
- 重定向浏览器地址栏发生改变;请求转发浏览器地址栏不发生改变;
- 重定向可以访问网络资源;请求转发只能访问本服务器中的资源;
- 重定向的路径中需要加虚拟目录;请求转发的路径不需要加入虚拟目录,只需要资源路径即可。
4、响应乱码问题
-
为什么会出现响应乱码?
服务器给浏览器发送响应信息,需要借助输出流,如果不对流的字符编码进行设置,就会出现乱码。其中,字节流如果不指定编码默认就是平台编码,即编辑器的默认的编码,如果浏览器与之字符编码不同就会出现乱码情况,而字符流如果不指定编码默认是ISO8859-1,该编码集不包括中文,所以如果使用中文一定会出现乱码情况。
-
解决:在服务器做出响应之前,设置响应编码
/** * setContentType() */ @WebServlet(value = "/forward.do") public class ServletDemo9 extends HttpServlet { @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 防止请求乱码 req.setCharacterEncoding("utf-8"); String username = req.getParameter("username"); // 设置响应编码,防止中文乱码 resp.setContentType("text/html;charset=utf-8"); resp.getWriter().write(username + ",欢迎你!"); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doPost(req, resp); } }
三、ServletContext 对象
-
概述:ServletContext对象称为Servlet上下文对象,服务器会为每个web程序创建一个上下文对象,上下文对象在项目中只有一个。该对象代表整个web应用程序,它可以和web容器(Tomcat)进行通信。该对象包含所有用户请求的数据, 一般用来获取MIME类型的文件数据、共享数据以及获取服务器中的文件资源。
-
获取对象的两种方式:
/** * 1. 通过HttpServletRequest对象来获取 * 2. 通过HttpServlet对象来获取 */ @WebServlet(value = "/servletContextDemo1") public class ServletContextDemo1 extends HttpServlet { @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 1. 通过request对象来获取 ServletContext context1 = req.getServletContext(); // 2. 通过HttpServlet对象来获取 ServletContext context2 = this.getServletContext(); System.out.println(context1 == context2); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doPost(req, resp); } } 运行结果:true
ServletContext 功能
-
获取MIME类型:
- MIME类型:在互联网通信过程中的一种文件数据类型,用来标志是什么类型的文件,我们之前setContentType方法中的text/html,就是MIME类型的一种,用来指明是html文件类型。
- 获取方式:
String getMimeType(String file)
-
域对象,共享数据:
-
概述:这里的域对象,与Request域对象不是一种,request域对象不能在不同的用户请求*享数据,而ServletContext域对象可以做到在所有的servlet*享数据,它的域范围是最大的。
-
方法介绍:
1. void setAttribute(String name,Object obj) - 存储数据 2. Object getAttitude(String name) - 通过键获取值 3. void removeAttribute(String name) - 通过键移除键值对
-
-
获取文件的真实路径:服务器中的路径
- 概述:通过文件的相对路径来获取文件的绝对路径,这里的相对路径,相对的是项目发布在tomcat中的资源路径
- 方法:
String getRealPath(String path)
-
代码示例:
@WebServlet(value = "/servletContextDemo2") public class ServletContextDemo2 extends HttpServlet { @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 获取域对象 ServletContext context = req.getServletContext(); // 创建文件对象 File file = new File("a.txt"); // 获取file的MIME类型 String mimeType = context.getMimeType(String.valueOf(file)); // 设置域对象 context.setAttribute("msg", "这里是ServletContext域对象"); // 获取默认的绝对路径 System.out.println(context.getRealPath("/")); // 获取web目录下的文件路径 System.out.println(context.getRealPath("/index.html")); // 获取WEB-INF目录下的文件路径 System.out.println(context.getRealPath("/WEB-INF/web.xml")); // 获取src目录下文件的路径 System.out.println(context.getRealPath("/WEB-INF/classes/a.txt")); System.out.println(ServletContextDemo2.class.getClassLoader().getResource("a.txt").getPath()); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doPost(req, resp); } } @WebServlet(value = "/servletContextDemo3") public class ServletContextDemo3 extends HttpServlet { @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletContext context = req.getServletContext(); // 获取域对象 System.out.println(context.getAttribute("msg")); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doPost(req, resp); } } 运行结果: F:\JetBrains\javacode\javaweb2\out\artifacts\servlet_war_exploded\ F:\JetBrains\javacode\javaweb2\out\artifacts\servlet_war_exploded\index.html F:\JetBrains\javacode\javaweb2\out\artifacts\servlet_war_exploded\WEB-INF\web.xml F:\JetBrains\javacode\javaweb2\out\artifacts\servlet_war_exploded\WEB-INF\classes\a.txt /F:/JetBrains/javacode/javaweb2/out/artifacts/servlet_war_exploded/WEB-INF/classes/a.txt 这里是ServletContext域对象