Servlet生命周期实现方式
- 实例和初始化时机
- 就绪/调用/服务阶段
- 销毁时机
案例实操
Servlet 的生命周期
Servlet 没有 main() 方法,不能独立运行,它的运行完全由 Servlet 引擎来控制和调度。所谓生命周期,指的是 servlet 容器何时创建 servlet 实例、何时调用其方法进行请求的处理、并何时销毁其实例的整个过程。(此处讨论默认的生命周期)
- 实例和初始化时机
当请求到达容器时,容器查找该 servlet 对象是否存在,如果不存在,则会创建实例并进行初始化。
- 就绪/调用/服务阶段
有请求到达容器,容器调用 servlet 对象的 service() 方法,处理请求的方法在整个生命周期中可以被多次调用;
HttpServlet 的 service() 方法,会依据请求方式来调用 doGet() 或者 doPost() 方法。但是,这两个 do 方法默认情况下,会抛出异常,需要子类去 override。
- 销毁时机
当容器关闭时(应用程序停止时),会将程序中的 Servlet 实例进行销毁。
上述的生命周期可以通过 Servlet 中的生命周期方法来观察。在 Servlet 中有三个生命周期方法,不由用户手动调用,而是在特定的时机由容器自动调用,观察这三个生命周期方法即可观察到 Servlet 的生命周期。
init 方法,在 Servlet 实例创建之后执行(证明该 Servlet 有实例创建了)
public void init(ServletConfig config) throws ServletException {
System.out.println("有实例创建了");
}
service 方法,每次有请求到达某个 Servlet 方法时执行,用来处理请求(证明该 Servlet 进行服务了)
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("服务调用了");
}
destroy 方法,Servlet 实例销毁时执行(证明该 Servlet 的实例被销毁了)
public void destroy() {
System.out.println("有实例被销毁了");
}
Servlet 的生命周期,简单的概括就分为四步:servlet 类加载→实例化→服务→销毁。下面我们描述一下 Tomcat 与 Servlet 是如何工作的,看看下面的时序图:
1、Web Client 向 Servlet 容器(Tomcat)发出 Http 请求
2、Servlet 容器接收 Web Client 的请求
3、Servlet 容器创建一个 HttpRequest 对象,将 Web Client 请求的信息封装到这个对象中
4、Servlet 容器创建一个 HttpResponse 对象
5、Servlet 容器调用 HttpServlet 对象的 service 方法,把 HttpRequest 对象与 HttpResponse 对象作为参数,传给 HttpServlet 对象
6、HttpServlet 调用 HttpRequest 对象的有关方法,获取 Http 请求信息
7、HttpServlet 调用 HttpResponse 对象的有关方法,生成响应数据
8、Servlet 容器把 HttpServlet 的响应结果传给 Web Client
扩展
Servlet 的配置
Servlet 除了配置基本的访问信息,还可以配置初始化参数,自启动等,并且一个 Servlet 可以配置多个访问路径,还可以使用通配符“*”。
基本配置
<servlet>
<servlet-name>helloweb</servlet-name><!-- 给服务器看的 -->
<servlet-class>com.xxx.web.HelloWeb</servlet-class><!-- servlet对应的资源路径 -->
</servlet>
<servlet-mapping>
<servlet-name>helloweb</servlet-name><!-- 给服务器看的 -->
<url-pattern>/helloweb</url-pattern><!-- 给浏览器看的,对外访问路径 -->
<url-pattern>/*</url-pattern>
</servlet-mapping>
初始化参数
<servlet>
<servlet-name>helloweb</servlet-name><!-- 给服务器看的 -->
<servlet-class>com.xxx.web.HelloWeb</servlet-class><!-- servlet对应的资源路径 -->
<!-- 初始化参数 -->
<init-param>
<param-name>param1</param-name>
<param-value>1</param-value>
</init-param>
<init-param>
<param-name>param2</param-name>
<param-value>2</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>helloweb</servlet-name><!-- 给服务器看的 -->
<url-pattern>/helloweb</url-pattern><!-- 给浏览器看的,对外访问路径 -->
<url-pattern>/*</url-pattern>
</servlet-mapping>
自启动
<servlet>
<servlet-name>helloweb</servlet-name><!-- 给服务器看的 -->
<servlet-class>com.xxx.web.HelloWeb</servlet-class><!-- servlet对应的资源路径 -->
<!-- 初始化参数 -->
<init-param>
<param-name>param1</param-name>
<param-value>1</param-value>
</init-param>
<init-param>
<param-name>param2</param-name>
<param-value>2</param-value>
</init-param>
<!-- 自启动 -->
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>helloweb</servlet-name><!-- 给服务器看的 -->
<url-pattern>/helloweb</url-pattern><!-- 给浏览器看的,对外访问路径 -->
<url-pattern>/*</url-pattern>
</servlet-mapping>
servlet-name:Servlet 对象的名称
servlet-class:创建 Servlet 对象所要调用的类
param-name:参数名称
param-value:参数值
load-on-startup:Servlet 容器启动时加载 Servlet 对象的顺序
servlet-mapping/servlet-name:要与 servlet 中的 servlet-name 配置的内容对应
url-pattern:客户访问的 Servlet 的相对 URL 路径
说明:url-pattern 可以配多个(一个 servlet 可以通过多个 url-pattern 访问)当多个 servlet 配置成了同一个 url-pattern,报错 java.lang.reflect.InvocationTargetExceptionion;通配符“*”只能放在最前面或最后面,不能放中间且不能单独存在(以/分割的,不能和单词组成整体)。越精确越优先。常规配置即可。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。