大可制作:QQ群:31564239(asp|jsp|php|mysql)

JSP/Servlet: Servlet 生命周期

Servlet的生命周期主要有四个阶段:载入、初始化、执行、清除。

Servlet的载入指的是容器将Servlet类载入JVM并实例化,这个时候Servlet对象还不算具备Servlet该有的功能,只能说是一个纯綷的Java对象,载入Servlet的时机有三种可能:
  • 服务器启动时
  • 浏览器第一次接收请求时
  • 管理者要求时

若要求在服务器启动时载入Servlet,可以在web.xml的<servlet>定义时,加入<load-on- startup>标签,例如:

  • web.xml
... 
<servlet>
<servlet-name>Servletname1</servlet-name>
<servlet-class>demo.servlet.SomeServlet1</servlet-class>
<load-on-startup>10</load-on-startup>
</servlet>
<servlet>
<servlet-name>Servletname2</servlet-name>
<servlet-class>demo.servlet.SomeServlet2</servlet-class>
<load-on-startup>20</load-on-startup>
</servlet>
<servlet>
<servlet-name>Servletname3</servlet-name>
<servlet-class>demo.servlet.SomeServlet3</servlet-class>
<load-on-startup>30</load-on-startup>
</servlet>
<servlet>
<servlet-name>Servletname4</servlet-name>
<servlet-class>demo.servlet.SomeServlet4</servlet-class>
<load-on-startup/>
</servlet>
...

<load-on-startup>标签设定的是载入时的顺序值,数值越小就越先载入。

在Servlet类被容器载入并实例化之后,会进行初始化的动作,此时init()方法会被调用执行,init()方法传入一个 ServletConfig类型的对象,表示与Servlet相关的环境对象,web.xml中的一些设定信息也包括在这个对象当中,在初始化之后, Servlet对象才称的上具备Servlet功能:
public void init(ServletConfig config)
             throws ServletException
 
ServletConfig的使用您并不陌生,在JSP的隐含对象 config 就是对应于ServletConfig,您可以用它来取得设定于web.xml中的初始参数(即使用config.getInitParameter ()):
  • web.xml
... 
 <servlet>
    ...
    <init-param>
        <param-name>parameter</param-name>
        <param-value>value</param-value>
    </init-param>
    ...
 </servlet>
...

您也可以使用无参数的init()方法,在Servlet 2.1之后,容器会调用有参数的init()方法,在执行完毕后再调用无参数的init()方法:
public void init() throws ServletException
 

通常在覆盖init()方法时,会这么撰写:
public void init(ServletConfig config)
    throws ServletException {
    super.init(config);
    // .....
}
 

这是了兼具Servlet 2.0之前的相容,确保父类GenericServlet会调用无参数的init()方法:
public class GenericServlet
        implements Servlet, ServletConfig {
    ServletConfig _config = null;
 
    public void init(ServletConfig) throws ServletException {
        _config = config;
        log("init classed");
        init();
    }
    ....
}
 

Servlet的初始化可以用于一些资源的预先载入,例如开启数据库连线,避免在使用者第一次请求网页时才开启数据库连线,以免使用者必须花费时间等待连线的完成。

Servlet在载入之后会一直存在于服务器的内存中,直到服务器关闭或是要求清除Servlet时,这可以避免对象生成时所需的时间与资源负担,并可 实现一些信息的持续性(persistence),每一个使用者请求Servlet时,容器会产生一个执行线来存取Servlet,也因而在设计 Servlet时必须注意到线程的安全问题。

在Servlet 2.4中,单绪执行模型(SingleThreadModel)接口已经被取消,这个接口本来是为了一个Servlet名称产生一组Servlet Pool,以共同分担请求并避免多线程存取同一个Servlet所造成的线程安全问题,然而如果使用单绪执行模型,可能会产生过多的对象或过多的资源 耗费(例如数据库连线)。

当Servlet被清除之时,会调用destroy()方法,通常也建议调用super.destroy(),这会调用父类 GenericServlet的destroy(),以在log档中记录Servlet被清除的讯息,例如:
public void destroy() {
    super.destroy();
    //....
}
 

浏览器发出请求至Servlet的执行顺序是:

浏览器 -> Web 服务器 -> Servlet 容器 -> service()

如果是HttpServlet则会依请求的方法,在service()之后调用对应的doXXX()方法。