Java Servlet - Servlet 生命周期

Servlet 生命周期

The lifecycle of a servlet is controlled by the container in which the servlet has been deployed. When a request is mapped to a servlet, the container performs the following steps.

servlet 的生命周期由部署 servlet 的容器控制。当将请求映射到 servlet 时,容器执行以下步骤。

  1. If an instance of the servlet does not exist, the web container:

    如果一个 servlet 实例不存在,web 容器:

  2. Loads the servlet class

    加载 servlet 类

  3. Creates an instance of the servlet class

    创建 sevlet 类的一个实例

  4. Initializes the servlet instance by calling the init method (initialization is covered in Creating and Initializing a Servlet)

    通过调用 init 方法初始化 servlet 实例

  5. The container invokes the service method, passing request and response objects. Service methods are discussed in Writing Service Methods.

    容器调用 service 方法,传入请求和响应对象。服务方法在 Writing Service Methods 中讨论。

If it needs to remove the servlet, the container finalizes the servlet by calling the servlet’s destroy method. For more information, see Finalizing a Servlet.

如果它需要移除 servlet,容器通过调用 servlet 的 destroy 方法来结束 servlet。详情参见 Finalizing a Servlet

实践

环境

操作系统:

Windows 10 x64

集成开发环境:

Eclipse IDE for Enterprise Java and Web Developers (includes Incubating components)

Version: 2021-09 (4.21.0)

Build id: 20210910-1417

服务器:

apache-tomcat-9.0.55

新建项目

选择主菜单 File > New > Dynamic Web Project,新建项目:

在这里插入图片描述

New Dynamic Web Project 向导中:

  • 填写项目名称(Project name)
  • 选择目标运行时环境(Target runtime,即服务器,或称容器)
  • 其他可以根据需要修改,或者保持不变,然后点击 Next > 按钮

在这里插入图片描述

接着点击 Next > 按钮:

在这里插入图片描述

最后点击 Finish 按钮:

在这里插入图片描述

项目新建完成之后,其结构如下:

在这里插入图片描述

运行 cmd.exe,进入该项目所在的文件夹中,使用 tree 命令查看项目结构:

D:\F\eclipse-workspace\servlet-lifecycle>tree /a /f
文件夹 PATH 列表
卷序列号为 8C71-860C
D:.
|   .classpath
|   .project
|
+---.settings
|       .jsdtscope
|       org.eclipse.jdt.core.prefs
|       org.eclipse.wst.common.component
|       org.eclipse.wst.common.project.facet.core.xml
|       org.eclipse.wst.jsdt.ui.superType.container
|       org.eclipse.wst.jsdt.ui.superType.name
|
+---build
|   \---classes
\---src
    \---main
        +---java
        \---webapp
            +---META-INF
            |       MANIFEST.MF
            |
            \---WEB-INF
                \---lib

编写 Servlet

src/main/java 目录中,新建一个 Servlet,名为 LifecycleServlet,如下:

在这里插入图片描述

LifecycleServlet.java 文件中:

  • LifecycleServlet 类上使用 @WebServlet 注解,使用 urlPatterns 属性为该 Servlet 指定请求映射的 URL
  • 为该 Servlet 提供一个无参构造方法
  • 重写两个 init 方法,以及 destroy 方法
  • 重写 doGetdoPost 方法
package com.mk.servlet;

import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(urlPatterns = "/lifecycle")
public class LifecycleServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;

    private DateFormat dateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss.SSS ");
    
    
    public LifecycleServlet() {
        System.out.println(dateFormat.format(new Date()) + "LifecycleServlet.LifecycleServlet()");
    }
    
    @Override
    public void init() throws ServletException {
        super.init();
        System.out.println(dateFormat.format(new Date()) + "LifecycleServlet.init()");
    }
    
    @Override
    public void init(ServletConfig config) throws ServletException {
        super.init(config);
        System.out.println(dateFormat.format(new Date()) + "LifecycleServlet.init(ServletConfig config)");
    }
    
    @Override
    public void destroy() {
        super.destroy();
        System.out.println(dateFormat.format(new Date()) + "LifecycleServlet.destroy()");
    }
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String dateTime = dateFormat.format(new Date());
        
        System.out.println(dateTime + "LifecycleServlet.doGet()");

        System.out.println(dateTime + "Request Method: " + request.getMethod());
        System.out.println(dateTime + "Request URI: " + request.getRequestURI());
        System.out.println(dateTime + "Request URL: " + request.getRequestURL().toString());
        
        response.getWriter().append("Served at: ").append(request.getContextPath());
    }
    
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println(dateFormat.format(new Date()) + "LifecycleServlet.doPost()");
        
        doGet(request, response);
//        // TODO Auto-generated method stub
//        super.doPost(req, resp);
    }
}

启动服务器

完成以上操作之后,右击项目,选择 Run As > Run on Server

在这里插入图片描述

Run On Server 向导中,选择服务器,然后点击 Next > 按钮:

在这里插入图片描述

确保你要部署的项目出现在 Configured 列表中,然后点击 Finish 按钮启动服务器:

在这里插入图片描述

在服务器启动过程中,会输出一些日志,从这里我们可以得到一些信息:

12月 19, 2021 5:01:48 下午 org.apache.catalina.startup.VersionLoggerListener log
信息: Server.服务器版本: Apache Tomcat/9.0.55
12月 19, 2021 5:01:48 下午 org.apache.catalina.startup.VersionLoggerListener log
信息: 服务器构建:        Nov 10 2021 08:26:45 UTC
12月 19, 2021 5:01:48 下午 org.apache.catalina.startup.VersionLoggerListener log
信息: 服务器版本号:      9.0.55.0
12月 19, 2021 5:01:48 下午 org.apache.catalina.startup.VersionLoggerListener log
信息: 操作系统名称:      Windows 10
12月 19, 2021 5:01:48 下午 org.apache.catalina.startup.VersionLoggerListener log
信息: OS.版本:           10.0
12月 19, 2021 5:01:48 下午 org.apache.catalina.startup.VersionLoggerListener log
信息: 架构:              amd64
12月 19, 2021 5:01:48 下午 org.apache.catalina.startup.VersionLoggerListener log
信息: Java 环境变量:     D:\F\Eclipse\eclipse\plugins\org.eclipse.justj.openjdk.hotspot.jre.full.win32.x86_64_16.0.2.v20210721-1149\jre
12月 19, 2021 5:01:48 下午 org.apache.catalina.startup.VersionLoggerListener log
信息: Java虚拟机版本:    16.0.2+7-67
12月 19, 2021 5:01:48 下午 org.apache.catalina.startup.VersionLoggerListener log
信息: JVM.供应商:        Oracle Corporation
12月 19, 2021 5:01:48 下午 org.apache.catalina.startup.VersionLoggerListener log
信息: CATALINA_BASE:     D:\F\eclipse-workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0
12月 19, 2021 5:01:48 下午 org.apache.catalina.startup.VersionLoggerListener log
信息: CATALINA_HOME:     D:\F\Apache\Apache Tomcat\apache-tomcat-9.0.55
12月 19, 2021 5:01:49 下午 org.apache.catalina.startup.VersionLoggerListener log
信息: 命令行参数:       -Dcatalina.base=D:\F\eclipse-workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0
12月 19, 2021 5:01:49 下午 org.apache.catalina.startup.VersionLoggerListener log
信息: 命令行参数:       -Dcatalina.home=D:\F\Apache\Apache Tomcat\apache-tomcat-9.0.55
12月 19, 2021 5:01:49 下午 org.apache.catalina.startup.VersionLoggerListener log
信息: 命令行参数:       -Dwtp.deploy=D:\F\eclipse-workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps
12月 19, 2021 5:01:49 下午 org.apache.catalina.startup.VersionLoggerListener log
信息: 命令行参数:       --add-opens=java.base/java.lang=ALL-UNNAMED
12月 19, 2021 5:01:49 下午 org.apache.catalina.startup.VersionLoggerListener log
信息: 命令行参数:       --add-opens=java.base/java.io=ALL-UNNAMED
12月 19, 2021 5:01:49 下午 org.apache.catalina.startup.VersionLoggerListener log
信息: 命令行参数:       --add-opens=java.base/java.util=ALL-UNNAMED
12月 19, 2021 5:01:49 下午 org.apache.catalina.startup.VersionLoggerListener log
信息: 命令行参数:       --add-opens=java.base/java.util.concurrent=ALL-UNNAMED
12月 19, 2021 5:01:49 下午 org.apache.catalina.startup.VersionLoggerListener log
信息: 命令行参数:       --add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED
12月 19, 2021 5:01:49 下午 org.apache.catalina.startup.VersionLoggerListener log
信息: 命令行参数:       -Dfile.encoding=GBK
12月 19, 2021 5:01:49 下午 org.apache.catalina.startup.VersionLoggerListener log
信息: 命令行参数:       -XX:+ShowCodeDetailsInExceptionMessages
12月 19, 2021 5:01:49 下午 org.apache.catalina.core.AprLifecycleListener lifecycleEvent
信息: 使用APR版本[1.7.0]加载了基于APR的Apache Tomcat本机库[1.2.31]。
12月 19, 2021 5:01:49 下午 org.apache.catalina.core.AprLifecycleListener lifecycleEvent
信息: APR功能:IPv6[true]、sendfile[true]、accept filters[false]、random[true]、UDS [true]。
12月 19, 2021 5:01:49 下午 org.apache.catalina.core.AprLifecycleListener lifecycleEvent
信息: APR/OpenSSL配置:useAprConnector[false],useOpenSSL[true]
12月 19, 2021 5:01:49 下午 org.apache.catalina.core.AprLifecycleListener initializeSSL
信息: OpenSSL成功初始化 [OpenSSL 1.1.1l  24 Aug 2021]
12月 19, 2021 5:01:49 下午 org.apache.coyote.AbstractProtocol init
信息: 初始化协议处理器 ["http-nio-8080"]
12月 19, 2021 5:01:49 下午 org.apache.catalina.startup.Catalina load
信息: 服务器在[562]毫秒内初始化
12月 19, 2021 5:01:49 下午 org.apache.catalina.core.StandardService startInternal
信息: 正在启动服务[Catalina]
12月 19, 2021 5:01:49 下午 org.apache.catalina.core.StandardEngine startInternal
信息: 正在启动 Servlet 引擎:[Apache Tomcat/9.0.55]
12月 19, 2021 5:01:49 下午 org.apache.coyote.AbstractProtocol start
信息: 开始协议处理句柄["http-nio-8080"]
12月 19, 2021 5:01:49 下午 org.apache.catalina.startup.Catalina start
信息: [478]毫秒后服务器启动

服务器启动完成之后,Eclipse IDE 会打开一个默认的浏览器,不过其没有访问 LifecycleServlet 的映射 URL,所以服务器返回 404,表示请求失败,请求所希望得到的资源未被在服务器上发现。如下:

提示:关于 404 响应代码的解释,参考 Web 开发技术 > HTTP > HTTP 响应代码 > 404 Not Found

在这里插入图片描述

测试

接下来,让我们访问 http://localhost:8080/servlet-lifecycle/lifecycle,注意观察控制台输出:

在这里插入图片描述

从控制台输出的信息的顺序可知,其与之前描述的 Servlet 生命周期是一致的:

提示:在 init 方法中,我们可以读取一些初始化配置参数、建立数据库连接,等等。

2021.12.19 18:20:10.728 LifecycleServlet.LifecycleServlet()
2021.12.19 18:20:10.728 LifecycleServlet.init()
2021.12.19 18:20:10.728 LifecycleServlet.init(ServletConfig config)
2021.12.19 18:20:10.728 LifecycleServlet.doGet()
2021.12.19 18:20:10.728 Request Method: GET
2021.12.19 18:20:10.728 Request URI: /servlet-lifecycle/lifecycle
2021.12.19 18:20:10.728 Request URL: http://localhost:8080/servlet-lifecycle/lifecycle

当我们选择停止服务器:

在这里插入图片描述

服务器会在停止之前,调用 Servlet 的 destroy 方法:

提示:在 destroy 方法中,我们可以释放占用的资源,比如关闭数据库连接,等等。

在这里插入图片描述

参考

Java Servlet Technology - Servlet Lifecycle

Creating and Initializing a Servlet

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值