Skip to content

Servlet生命周期

Servlet 对象是 Servlet 容器帮我们创建的,因此生命周期的方法都是由容器(Tomcat)来管理和调用的。

生命周期

Servlet 对象的生命周期:

生命周期对应方法执行时机执行次数
构造对象构造器第一次请求或容器启动后1 次
初始化init()第一次请求或容器启动后1 次
处理服务service()每次请求多次
销毁destory()容器关闭时1 次
java
@WebServlet("/servletLifeCycle")
public class ServletLifeCycle extends HttpServlet {
  public ServletLifeCycle() {
    // 执行一次
    System.out.println("constructor");
  }

  @Override
  public void init() throws ServletException {
    // 执行一次
    System.out.println("init");
  }

  @Override
  protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    // 执行多次
    System.out.println("service");
  }

  @Override
  public void destroy() {
    // 执行一次
    System.out.println("destroy");
  }
}

注意

由上面的案例中,可以看出 Servlet 在 Tomcat 中是单例的!

因此,在 Servlet 实现类中定义的成员变量是全局的,在多个线程之间共享同一份数据,所以强烈不建议在其内部定义可以被修改的成员变量,因为在并发请求时,会引发线程安全问题!

java
@WebServlet("/servletLifeCycle")
public class ServletLifeCycle extends HttpServlet {
  private int count = 0;

  @Override
  protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// ❌ 强烈不建议
    count++;
    System.out.println("service");
  }
}

立即初始化

上面的案例中,可以看到 构造器和 init() 方法是在第一次请求的时候被触发的。那么能不能在容器启动的时候就触发呢?

可以,此时需要设置注解的 loadOnStartup 属性。

loadOnStartup 值作用
-1默认值,Tomcat 启动时不会初始化该 Servlet
>= 1Tomcat 启动时,实例化该 Servlet 的顺序,值越小越优先执行
java
// Tomcat内部已经预定义用到5了,所以我们从6开始,以免重复
@WebServlet(value = "/servletLifeCycle", loadOnStartup = 6)
public class ServletLifeCycle extends HttpServlet {
  // ...

  @Override
  protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    System.out.println("service");
  }
}

DefaultServlet

DefaultServlet 是 Tomcat 内置的一个 Servlet,专门用于处理 当客户端请求静态资源的路径和任何 Servlet 都不匹配时,就需要用它来获取静态资源。

它默认随服务启动,并且启动的 loadOnStartup 为 1。

在 Tomcat 的 conf/web.xml 中,有一段下面的配置:

xml
<servlet>
  <servlet-name>default</servlet-name>
  <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
  <init-param>
    <param-name>debug</param-name>
    <param-value>0</param-value>
  </init-param>
  <init-param>
    <param-name>listings</param-name>
    <param-value>false</param-value>
  </init-param>
  <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
  <servlet-name>default</servlet-name>
  <url-pattern>/</url-pattern>
</servlet-mapping>

提示

后续在学习 SpringMVC 的时候,SpringMVC 也会提供一个 DefaultServlet,它会把 Tomcat 的 DefaultServlet 覆盖掉,这时请求静态资源时会报 404,造成的原因就在这里,这时候需要我们手动配置修改这个问题。

Released under the MIT License.