Servlet-生命周期

Servlet-生命周期

步骤使用方法执行时间
实例化构造器第一次请求/随服务器启动
初始化init构造完毕
接受请求,处理请求,服务service每次请求
销毁destory关闭服务

在Servlet被访问时,经历了 实例化对象 -> init初始化对象 -> 执行service方法

一直到服务器关闭,则会销毁此Servlet对象

@WebServlet("/servletLifeCycle")
public class ServletLifeCycle extends HttpServlet {
    public ServletLifeCycle() {
        System.out.println("构造器");
    }

    @Override
    public void init(ServletConfig config) throws ServletException {
        System.out.println("初始化");
    }

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

    @Override
    public void destroy() {
        System.out.println("销毁");
    }
}

由此次实验,我们可以知道以下结论

  • Servlet在Tomcat中是单例的:既一个Servlet只会实例化一个对象
  • Servlet不会只被一个客户端访问,每一个客户端都是一个线程,而Servlet的成员变量在多个线程栈之中时共享的,所以强烈建议不要在service方法中修改成员变量,避免线程安全问题
Servlet的对象

Servlet的对象是在其第一次被访问时实例化和初始化

我们可以通过调整web.xml的load-on-startup标签,让其与Tomcat启动时就实例化和初始化对象

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"
         version="6.0">
    <servlet>
        <servlet-name>servletLifeCycle</servlet-name>
        <servlet-class>com.xiaobai.servlet.ServletLifeCycle</servlet-class>
<!--        默认值是-1,含义是 tomcat启动时不会实例化该servlet
        其他正整数,含义是在tomcat在启动时,同时也是实例化该servlet的顺序
		如果序号冲突,则tomcat会自动协调启动顺序-->
        <load-on-startup>6</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>servletLifeCycle</servlet-name>
        <url-pattern>/servletLifeCycle</url-pattern>
    </servlet-mapping>
</web-app>

注:Tomcat的配置文件中web.xml里已经占用了很多启动的序号,这里推荐用户自定义的序号是从6开始

那么我们也可以调整注解的参数

int loadOnStartup() default -1;

@WebServlet(value = "/servletLifeCycle",loadOnStartup = 6)


default-servlet

在Tomcat的web.xml中,配置了这样的一个Sevlet映射

<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>

当客户端访问静态资源时,Tomcat仍然会将请求按照Servlet的寻找方式来寻找

当客户端没查到精确匹配的Servlet时,就会将请求交给DefaultServlet来处理

这个DefaultServlet配置了模糊匹配全部(除了.jsp文件外)

DefaultServlet会寻找其对应的具体文件,再使用IO流读取此文件,并将此文件放到response对象的响应体中

并根据文件的拓展名选择合适的MIME(媒体类型),使用response设置Content-Type响应头

再读取文件大小,使用response设置Content-Length响应头

最后将response对象转换成响应报文发送回客户端

SpringMVC

在SpringMVC中,会默认使default-servlet失效,如果不单独进行额外的配置,会导致无法访问其网站内的所有静态资源

我们可以通过在其中重新配置default-servlet映射来解决这个问题