ITEEDU

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()方法。