Servlet 2.x 规范

Servlet 2.x 规范

sun 公司制订的一种用来扩展 web 服务器功能的组件规范。

Servlet 2.x 组件关系

  1. Servlet 接口:init(ServletConfig config)、service(ServletRequest req, ServletResponse res)、destroy()
  2. GenericServlet 抽象类:实现了 Servlet 接口中的 init, destroy 方法
  3. HttpServlet 抽象类:继承了 GenericServlet 抽象类,实现了 service()
  4. ServletConfig 接口:String getInitParameter(String paraName)
  5. ServletRequest 接口:HttpServletRequest 的父接口
  6. ServletResponse 接口:HttpServletResponse 的父接口

一、Servlet

1.1 Servlet 的生命周期

Servlet 的生命周期指 Servlet 容器如何去创建 Servlet 对象、如何给 Servlet 对象分配资源、如何调用 Servlet 对象的方法来处理请求、以及如何销毁 Servlet 对象的整个过程。

Servlet 生命周期的四个阶段:

(1) 实例化:容器调用 Servlet 的构造器,创建 Servlet 对象。

情况1:容器收到请求后才创建 Servlet 对象。默认,容器只会为 Servlet 创建唯一一个实例。

情况2: 容器启动时交某些 Servlet 对象创建好(需要配置 load-on-startup)。load-on-startup 参数值必须是 >=0 的整数,越小优先级(即先实例化)越高。

(2) 初始化:容器在创建好 Servlet 对象后,立即调用 init() 方法。

init() 只执行一次

GenericServlet 已经实现了 init(),该方法会将容器创建好的 ServletConfig 对象作为参数传给 init()。

ServletConfig 对象提供一个 getInitParameter() 来访问 Servlet 的初始化参数。

如果 GenericServlet 的 init() 提供的初始化操作不满足需要,可以重写 init() 无参方法,不重写 init(ServletConfig config)

(3) 就绪

Servlet 对象可以调用了,容器收到请求后,会调用 Servlet 对象的 service() ,该方法会依据请求类型(get/post)分别调用 doGet(), doPost()

(4) 销毁:Servlet 容器在销毁 Servlet 对象之前,会调用 destroy() 方法。

1.2 Servlet 如何处理请求资源路径

  1. Servlet 容器会先假设访问的是一个 Servlet ,会依据应用名(appname)找到应用所在的文件夹,然后找到 web.xml 文件。

  2. 匹配

    • 精确匹配(完全匹配)
    • 通配符匹配:使用 * 匹配任意长度的字符串。eg:
    • 后缀匹配:使用 . 开头,后面可以接任意字符。eg: .do
  3. 如果都不匹配,则容器认为访问的是一个静态资源文件(html/css/js),如果找到则返回,否则返回404。

1.3 Servlet 是如何运行的?

  1. 浏览器依据 ip, port 建立与 Servlet 容器之间的连接。
  2. 浏览器将请求数据打包(即按照 http 协议的要求,将相关数据封闭成一个数据包,即请求数据包)并发送给 Servlet 容器。
  3. Servlet 容器解析请求数据包,并将解析后的数据放到 request 对象上。同时创建一个 response 对象。
  4. Servlet 容器依据请求资源路径找到 Servlet 的配置,然后创建 Servlet 对象。
  5. Servlet 调用 service 方法,并且会将事先创建好的 request 对象和 response 对象作为 service 方法的参数传递给 Servlet 对象。
  6. Servlet 通过 request 对象获得请求参数,进行相应的处理,然后将处理结果写到 response 对象上。
  7. Servlet 读取 response 对象上的数据,然后将处理结果打包(响应数据包)并发送给浏览器。
  8. 浏览器解析响应数据包,将返回的数据展现给用户。

1.4 实例

public class HelloWorldServlet extends HttpServlet {
    public void service(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {
        //1、读请求参数值
        String qtyStr = req.getParameter("qty");
        int qty = Integer.parseInt(qtyStr);
        //2、处理请求
        String rs = "";
        for (int i = 0; i < qty; i++) {
            rs += "<h1>Hello World</h1>";
        }
        //3、设置一个消息头content-type,告诉浏览器返回的数据类型是一个html文档及编码格式
        //告诉服务器使用out输出时使用指定的编码格式进行编码
        res.setContentType("text/html;charset=utf-8");
        //4、获得一个输出流
        PrintWriter out = res.getWriter();
        //5、调用流的方法进行输出,其实质是将处理结果写到了res对象上
        out.println(rs);
        out.close();
    }
}

配置 WEB-INF/web.xml 配制文件

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
    <servlet>
        <servlet-name>helloWord</servlet-name>
        <!--类名要完整(包名,类名都要全)-->
        <servlet-class>com.herolei.HelloWorldServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>helloWord</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
</web-app>

启动程序,访问 http://localhost:8080/hello?qty=30

补充:web 打包后的目录如下

appname(应用名)
  └──WEB-INF
      ├──classes    .class文件
      ├──lib        .jar文件,lib文件夹可选
      └──web.xml    部署描述文件

二、Listener

Servlet 规范当中定义的一种特殊的组件,用来监听容器产生的事件并进行处理。

容器会产生两大类事件:

  1. 生命周期相关的事件:容器在创建或者销毁 request, servletContext(Servlet 上下文)时产生的事件。对应的接口有 ServletRequestListener、ServletContextListener。
  2. 绑定相关的事件:容器调用了 request, servletContext 的 setAttribute, removeAttribute 时产生的事件。。对应的接口有 ServletContextAttributeListener、ServletRequestAttributeListener。
public interface ServletContextListener extends EventListener {
    // 容器初始化
    void contextInitialized(ServletContextEvent ctx);
    // 容器销毁
    void contextDestroyed(ServletContextEvent ctx);
}

public interface ServletContextAttributeListener extends EventListener {
    void attributeAdded(ServletContextAttributeEvent event);
    void attributeRemoved(ServletContextAttributeEvent event);
    void attributeReplaced(ServletContextAttributeEvent event);
}

三、Filter

public interface Filter {
    // 初始化 Filter
    void init(FilterConfig filterConfig) throws ServletException;

    // 调用,如果要继续调用下一个 Filter,需要调用 chain.doFilter(request, response)
    void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException;

    // 销毁
    public void destroy();
}

public interface FilterChain {
    void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException;
}

参考:

  1. 《Servlet 规范》:https://www.runoob.com/servlet/servlet-life-cycle.html

每天用心记录一点点。内容也许不重要,但习惯很重要!

猜你喜欢

转载自www.cnblogs.com/binarylei/p/10205884.html