servlet的生命周期

本文详细解析了Servlet的工作原理,包括其生命周期中的初始化、响应请求及终止阶段,并探讨了Servlet与JSP的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

自定义servlet是继承的HttpServlet,HttpServlet继承自GenericServlet,GenericServlet实现的javax.servlet. 这里要注意的是,GenericServlet是一个通用的,不特定于任何协议的Servlet,它实现了Servlet接口。而HttpServlet继承于GenericServlet,因此HttpServlet也实现了Servlet接口。所以我们定义Servlet的时候只需要继承HttpServlet即可。而HttpServlet是特定于HTTP协议的类,所以HttpServlet中实现了service()方法,并将请求ServletRequest、ServletResponse 强转为HttpRequest 和 HttpResponse。

Servlet接口,此接口的主要定义方法如下:

void init(ServletConfig var1) throws ServletException;

ServletConfig getServletConfig();

void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;

String getServletInfo();

void destroy();

在代码中,Servlet生命周期由接口javax.servlet.Servlet定义。所有的Java Servlet 必须直接或间接地实现javax.servlet.Servlet接口,这样才能在Servlet Engine上运行。javax.servlet.Servlet接口定义了一些方法,在Servlet 的生命周期中,这些方法会在特定时间按照一定的顺序被调用。

下面是主要方法的的说明

  1. init()方法

    在Servlet的生命周期中,仅执行一次init()方法,它是在服务器装入Servlet时执行的,可以配置服务器,以在启动服务器或客户机首次访问Servlet时装入Servlet。无论有多少客户机访问Servlet,都不会重复执行init();

  2. service()方法

    它是Servlet的核心,每当一个客户请求一个HttpServlet对象,该对象的Service()方法就要调用,而且传递给这个方法一个“请求”(ServletRequest)对象和一个“响应”(ServletResponse)对象作为参数。在HttpServlet中已存在Service()方法。默认的服务功能是调用与HTTP请求的方法相应的do功能。

  3. destroy()方法

    仅执行一次,在服务器端停止且卸载Servlet时执行该方法,有点类似于C++的delete方法。一个Servlet在运行service()方法时可能会产生其他的线程,因此需要确认在调用destroy()方法时,这些线程已经终止或完成。

所以servlet生命周期分为三个阶段:

  1. 初始化阶段 调用init()方法
  2. 响应客户请求阶段  调用service()方法
  3. 终止阶段  调用destroy()方法

当启动Servlet容器时,容器首先查找一个配置文件web.xml,这个文件中记录了可以提供服务的Servlet。每个Servlet被指定一个Servlet名,也就是这个Servlet实际对应的Java的完整class文件名。Servlet容器会为每个自动装入选项的Servlet创建一个实例。所以,每个Servlet类必须有一个公共的无参数的构造器 servlet在servlet Engine上的运行加载顺序:

不存在的servlet实例————>容器装载servlet ————>创建servlet实例————>初始化servlet:调用servlet的init()方法————>处理业务:调用serlvet实例的service()方法————>结束servlet:调用实例的destroy()方法

初始化阶段: 当servlet实例化时,servlet容器将调用每个servlet的init()方法来实例化每个实例,执行完每个init()方法后,servlet处于“已初始化”状态。 对于servlet对象创建的时机: 根据网上资料所说有三种:

1、Servlet容器启动时:读取web.xml配置文件中的信息,构造指定的Servlet对象,创建ServletConfig对象,同时将ServletConfig对象作为参数来调用Servlet对象的init方法。

2、在Servlet容器启动后:客户首次向Servlet发出请求,Servlet容器会判断内存中是否存在指定的Servlet对象,如果没有则创建它,然后根据客户的请求创建HttpRequest、 HttpResponse对象,从而调用Servlet 对象的service方法。

3、Servlet的类文件被更新后,重新创建Servlet Servlet容器在启动时自动创建Servlet,这是由在web.xml文件中为Servlet设置的<load-on-startup>属性决定

对于第一种开始并不了解,经查看源码知道,是在GenericServlet的init()方法里实现的,源码如下:

public void init(ServletConfig config) throws ServletException {
    this.config = config;
    this.init();
}

config的加载配置信息源码:

public String getInitParameter(String name) {
            ServletConfig sc = this.getServletConfig();
        if(sc == null) {
            throw new IllegalStateException(lStrings.getString("err.servlet_config_not_initialized"));
        } else {
            return sc.getInitParameter(name);
        }
    }

    public Enumeration getInitParameterNames() {
        ServletConfig sc = this.getServletConfig();
        if(sc == null) {
            throw new IllegalStateException(lStrings.getString("err.servlet_config_not_initialized"));
        } else {
            return sc.getInitParameterNames();
        }
    }

    public ServletConfig getServletConfig() {
        return this.config;
    }

    public ServletContext getServletContext() {
        ServletConfig sc = this.getServletConfig();
        if(sc == null) {
            throw new IllegalStateException(lStrings.getString("err.servlet_config_not_initialized"));
        } else {
            return sc.getServletContext();
        }
    }

第三种关于<load-on-statup> ...... </load-on-statup>要注意一点是:参数小于0即负数时,web容器启动时不做实例化处理,servlet首次被 调用时才做实例化,这种情况和没有设置<load-on-statup>时是一样的;参数大于0时,web容器启动时做实例化处理,顺序是从小到大,正整数小的先被实例化;参数等于0时,web容器启动时做实例处理,相当于是最大整数,因此web容器启动时,最后被实例化; 注意:在web.xml文件中配置<load-on-statup>的servlet,很可能没有配置<servlet-mapping>,这样我们无法通过url的方式访问这个servlet,这种servlet通常是需要在servlet容器启动自动加载,完成一些全局性的初始化工作

响应客户请求阶段: servlet被初始化以后,就处于能响应请求的就绪状态,每个对servlet的请求由一个Servlet Request对象代表,servlet给客户端的响应由一个servlet Response对象代表。对于用户的到达请求,服务器都会创建特定于请求的Servlet Request和servlet Response对象,然而调用被请求servlet的service()方法。service()方法从ServletRequest对象获取客户请求信息,并通过ServletResponse对象向客户返回响应信息。

ServletRequest和ServletResponse对象在HttpServlet里被强转为HttpServletRequest和HttpServletResponse,源码:

public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
    HttpServletRequest request;
    HttpServletResponse response;
    try {
        request = (HttpServletRequest)req;
        response = (HttpServletResponse)res;
    } catch (ClassCastException var6) {
        throw new ServletException("non-HTTP request or response");
    }

    this.service(request, response);
}

对于Service()方法,同一个Service()方法可能被多个用户同时访问,这样也会出现并发问题,所以在对同一文件的读写操作时最好加线程同步,但这样的话会降低项目的整体性能 ,具体需求具体分析

终止阶段: 当WEB应用被终止,或Servlet容器终止运行,或Servlet容器重新装载Servlet新实例时,Servlet容器会先调用Servlet的destroy()方法,在destroy()方法中可以释放掉Servlet所占用的资源。

最后说点Servlet与JSP的比较: jsp在被web容器加载后生成的class反编译后是类servlet,可以看成是servlet,jsp是直观的网页模式,servlet虽然可以生成网页,但逻辑复杂,也不直观,servlet一般用于处理业务

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值