前 言

人总是要有梦想的,也许哪天就实现了呢!

如果有不正确之处,还望指正,毕竟我还是一个菜鸟!



一、HTTP 协议

在之前的一篇文章中,提到了HTTP 协议的请求部分,这次我们讲解HTTP 的响应部分。

  1. 响应行:
  1. 组成:协议/版本 响应状态码 状态码描述
  2. 响应状态码:服务器告诉客户端浏览器本次请求和响应的一个状态,状态码都是3位数字组成。状态码分类如下:
1xx:服务器接收客户端消息,但是接收没有完成,等待了一段时间后,向客户端发送1xx状态码
2xx:成功。代表的是200
3xx:重定向。代表:302(重定向),304(访问缓存)
4xx:客户端错误。代表:404(请求路径没有对应的资源),405(请求方式没有对应的doXxx方法)
5xx:服务器错误。代表:500(服务器内部出现异常)
  1. 响应头:
  1. 格式:头名称:值
  2. 常见的响应头:
Content-Type:服务器告诉客户端本次响应体数据格式以及编码格式
Content-disposition:服务器告诉客户端以什么格式打开响应体数据
  1. 响应空行:
  2. 响应体:传输的数据


响应信息

下载文件的response的头部_java

二、Response 对象

1、设置响应消息

当客户从浏览器发起请求时,在访问成功的情况下,服务器就需要作出响应,所以我们就需要设置响应消息,来传给客户端浏览器。

  1. 设置响应行:
  1. 格式:HTTP/1.1 200 ok
  2. 设置状态码:setStatus(int sc)
  1. 设置响应头:setHeader(String name, String value)
  2. 设置响应体:具体步骤如下:
  1. 获取输出流:
1. PrintWriter getWriter() - 字符输出流
2. ServletOutputStream getOutputStream() - 字节输出流
  1. 使用输出流,将数据输出到客户端浏览器


2、重定向(Redirect)

  1. 概述:重定向就是不对本次请求进行业务处理,而是跳转到指定的URL进行处理业务,在这期间,浏览器发起了两次请求。举例:这就相当于你去1号窗口办理事务,但是1号窗口不能办理并且告诉你3号窗口能够办理你的业务,这时候你就自己去了3号窗口,找3号窗口的业务员替你办理业务。在这个过程中,你去了两个窗口,向不同的业务员发起请求。这里的业务员就相当于URL。
  2. 特点:
  1. 重定向是两次请求,地址栏发生改变。并且不能使用request对象来共享数据。
  2. 重定向可以访问其他站点的资源,即可以跳转到网络资源中。
  3. 重定向的路径需要加入虚拟目录。
  1. 方法:sendRedirect(String URL)
  2. 路径写法:
  1. 相对路径:通过相对路径的方式,不能够确定唯一资源,如:../index.html
  2. 绝对路径:通过绝对路径可以确定唯一资源,如:http://localhost/servlet/responseDemo


3、Redirect 与 Forward 区别

  1. 重定向是两次请求,都是从浏览器出发;请求转发是一次请求,转发在服务器内部进行。
  2. 重定向浏览器地址栏发生改变;请求转发浏览器地址栏不发生改变;
  3. 重定向可以访问网络资源;请求转发只能访问本服务器中的资源;
  4. 重定向的路径中需要加虚拟目录;请求转发的路径不需要加入虚拟目录,只需要资源路径即可。


4、响应乱码问题

  1. 为什么会出现响应乱码?
    服务器给浏览器发送响应信息,需要借助输出流,如果不对流的字符编码进行设置,就会出现乱码。其中,字节流如果不指定编码默认就是平台编码,即编辑器的默认的编码,如果浏览器与之字符编码不同就会出现乱码情况,而字符流如果不指定编码默认是ISO8859-1,该编码集不包括中文,所以如果使用中文一定会出现乱码情况。
  2. 解决:在服务器做出响应之前,设置响应编码
/**
*	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 对象

  1. 概述:ServletContext对象称为Servlet上下文对象,服务器会为每个web程序创建一个上下文对象,上下文对象在项目中只有一个。该对象代表整个web应用程序,它可以和web容器(Tomcat)进行通信。该对象包含所有用户请求的数据, 一般用来获取MIME类型的文件数据、共享数据以及获取服务器中的文件资源。
  2. 获取对象的两种方式:
/**
*	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 功能

  1. 获取MIME类型:
  1. MIME类型:在互联网通信过程中的一种文件数据类型,用来标志是什么类型的文件,我们之前setContentType方法中的text/html,就是MIME类型的一种,用来指明是html文件类型。
  2. 获取方式:String getMimeType(String file)
  1. 域对象,共享数据:
  1. 概述:这里的域对象,与Request域对象不是一种,request域对象不能在不同的用户请求中共享数据,而ServletContext域对象可以做到在所有的servlet中共享数据,它的域范围是最大的。
  2. 方法介绍:
1. void setAttribute(String name,Object obj) - 存储数据
2. Object getAttitude(String name) - 通过键获取值
3. void removeAttribute(String name) - 通过键移除键值对
  1. 获取文件的真实路径:服务器中的路径
  1. 概述:通过文件的相对路径来获取文件的绝对路径,这里的相对路径,相对的是项目发布在tomcat中的资源路径
  2. 方法:String getRealPath(String path)
  1. 代码示例:
@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域对象