1. HttpServletRequest

1.1. HttpServletRequest简介

  在Servlet Api中,定义了一个HttpServletRequest接口,它继承自ServletRequest,专门用于封装Http的请求。由于Http请求包含请求行、请求头和请求体三部分,因此在HttpServletRequest中分别定义了接受请求头、请求行和请求体的相关方法。

1.2. 请求行

1.2.1. 获取请求行相关信息的相关方法

  (1)getMethod():返回请求方法,请求方法可能是GET或者POST,也有可能是HEAD、PUT或者DELETE。
  (2)getRequestURI():返回URI(URI是URL从主机和端口之后到表单数据之前的那一部分)。如http://localhost:8080/my/test1?name=%E5%A4%87%E4%BB%BD%E5%A4%A7V&passWord=2342的URI为“/my/test1”。
  (3)getRemoteAddr():用于获取客户端的IP地址。如:0:0:0:0:0:0:0:1
  (4)getLocalAddr():用于获取服务器当前接受请求的IP地址。如:0:0:0:0:0:0:0:1
  (5)getRemotePort():用于获取客户端的端口号。如:8080
  (6)getContextPath():用于获取RUL中的属于web应用程序的路径。
  (7)getProtocol():用于获取请行中的协议名和版本。如:HTTP/1.1

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("MyServlet收到GET请求");
        System.out.println("请求方式:" + request.getMethod());
        System.out.println("URI:" + request.getRequestURI());
        System.out.println("发出请求客户端IP地址:" + request.getRemoteAddr());
        System.out.println("服务点接收请求的IP地址:" + request.getLocalAddr());
        System.out.println("访问客户端的端口号:" + request.getRemotePort());
        System.out.println("web应用路径:" + request.getContextPath());
        System.out.println("http协议和版本:" + request.getProtocol());
    }

JavaWeb开发(四)HttpServletRequest-LMLPHP

1.3. 请求头

  获取请求头的相关方法
  (1)getHeader (String name):用于获取一个指定头字段的值,如果请求头不包含此字段则返回null,如果包含多个该字段的值则返回第一个值。
  (2)getIntHeader ():用于获取指定头字段的值,并且将其转化为int类型,如果不存在该字段则返回-1,如果获取的值不能转化成int类型则会发生NumberFormatException异常。
  (3)getDataHeaderNames():用于获取指定头字段的值,并且将按照GMT时间格式转化成一个代表日期/时间的长整数。
  (4)getHeaderNames():用于获取所有包含请求头字段的Enumerating。

        //获取请求头
        //accept:text/html, application/xhtml+xml, image/jxr, */*
        //accept-language:zh-Hans-CN,zh-Hans;q=0.5
        //user-agent:Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko
        //accept-encoding:gzip, deflate
        //host:localhost:8080
        //connection:Keep-Alive
        //cookie:JSESSIONID=73B0F51907B51DCCEc8b-855f-ad93239cf1f0
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String element = headerNames.nextElement();
            System.out.println(element + ":" + request.getHeader(element));
        }

1.4. 请求体

  获取请求参数:
  (1)getParameter(String name):用于获取某个指定名称的参数值,如果请求中没有包含指定名称的参数值,则返回空串“”,如果包含多个该参数的值则返回第一个出现的参数值。
  (2)getParameterNames():用于返回一个包含请求消息中的所有参数名的Enumerating。
  (3) getParameterMap():用于将请求中的所有参数和值装入一个map对象然后返回。

1.5. 发送响应行

  sendError(int sc, String msg):使用指定的状态码发送一个错误响应至客户端。服务器默认会创建一个HTML格式的服务错误页面作为响应结果,其中包含参数msg指定的文本信息,这个HTML页面的内容类型为“text/html”,保留cookies和其他未修改的响应头信息。如果一个对应于传入的错误码的错误页面已经在web.xml中声明,那么这个声明的错误页面将会优先于建议的msg参数服务于客户端。(ps:相比较上面的方法,我更倾向于前者。使用上面的方法,可以通过定制不同状态的响应结果显示于客户端,我们应该不想让客户端看到服务器创建出的简单粗暴的页面吧?)
  setStatus(int sc):设置响应的状态码。这个方法被用于当响应结果正常时(例如,状态码为SC_OK或SC_MOVED_TEMPORARTLY)设置响应状态码。如果发生错误,而且来访者希望调用在web应用中定义的错误页面作为显示,那么应该使用sendError方法代替之。使用setStatus方法之后,容器会清空缓冲并设置Location响应头,保留cookies和其他响应头信息。

1.6. Servlet 生命周期

  Servlet 生命周期可被定义为从创建直到毁灭的整个过程。以下是 Servlet 遵循的过程:
  • Servlet 初始化后调用 init () 方法。
  • Servlet 调用 service() 方法来处理客户端的请求。
  • Servlet 销毁前调用 destroy() 方法。
  • 最后,Servlet 是由 JVM 的垃圾回收器进行垃圾回收的。
  现在让我们详细讨论生命周期的方法。

1.6.1. init() 方法

  init 方法被设计成只调用一次。它在第一次创建 Servlet 时被调用,在后续每次用户请求时不再调用。因此,它是用于一次性初始化,就像 Applet 的 init 方法一样。
Servlet 创建于用户第一次调用对应于该 Servlet 的 URL 时,但是您也可以指定 Servlet 在服务器第一次启动时被加载。
  当用户调用一个 Servlet 时,就会创建一个 Servlet 实例,每一个用户请求都会产生一个新的线程,适当的时候移交给 doGet 或 doPost 方法。init() 方法简单地创建或加载一些数据,这些数据将被用于 Servlet 的整个生命周期。
  init 方法的定义如下:

public void init() throws ServletException {
  // 初始化代码...
}

1.6.2. service() 方法

  service() 方法是执行实际任务的主要方法。Servlet 容器(即 Web 服务器)调用 service() 方法来处理来自客户端(浏览器)的请求,并把格式化的响应写回给客户端。
每次服务器接收到一个 Servlet 请求时,服务器会产生一个新的线程并调用服务。service() 方法检查 HTTP 请求类型(GET、POST、PUT、DELETE 等),并在适当的时候调用 doGet、doPost、doPut,doDelete 等方法。
  下面是该方法的特征:

public void service(ServletRequest request, 
                    ServletResponse response) 
      throws ServletException, IOException{
}

  service() 方法由容器调用,service 方法在适当的时候调用 doGet、doPost、doPut、doDelete 等方法。所以,您不用对 service() 方法做任何动作,您只需要根据来自客户端的请求类型来重写 doGet() 或 doPost() 即可。
  doGet() 和 doPost() 方法是每次服务请求中最常用的方法。下面是这两种方法的特征。

1.6.3. doGet() 方法

  GET 请求来自于一个 URL 的正常请求,或者来自于一个未指定 METHOD 的 HTML 表单,它由 doGet() 方法处理。

public void doGet(HttpServletRequest request,
                  HttpServletResponse response)
    throws ServletException, IOException {
    // Servlet 代码
}

1.6.4. doPost() 方法

  POST 请求来自于一个特别指定了 METHOD 为 POST 的 HTML 表单,它由 doPost() 方法处理。

public void doPost(HttpServletRequest request,
                   HttpServletResponse response)
    throws ServletException, IOException {
    // Servlet 代码

1.6.5. destroy() 方法

  destroy() 方法只会被调用一次,在 Servlet 生命周期结束时被调用。destroy() 方法可以让您的 Servlet 关闭数据库连接、停止后台线程、把 Cookie 列表或点击计数器写入到磁盘,并执行其他类似的清理活动。
  在调用 destroy() 方法之后,servlet 对象被标记为垃圾回收。destroy 方法定义如下所示:

  public void destroy() {
    // 终止化代码...
  }

1.6.6. 架构图

  下图显示了一个典型的 Servlet 生命周期方案。
  • 第一个到达服务器的 HTTP 请求被委派到 Servlet 容器。
  • Servlet 容器在调用 service() 方法之前加载 Servlet。
  • 然后 Servlet 容器处理由多个线程产生的多个请求,每个线程执行一个单一的 Servlet 实例的 service() 方法。
JavaWeb开发(四)HttpServletRequest-LMLPHP

01-02 13:37