Servlet:访问流程、核心接口与生命周期

深入理解 Servlet:访问流程、核心接口与生命周期

在 Java Web 开发中,Servlet 是基石般的存在。无论是传统的 JSP 还是现代的 Spring MVC,底层都离不开 Servlet 的支持。本文将围绕 Servlet 的访问流程、体系结构、生命周期以及两个重要的配置对象(ServletConfig 和 ServletContext)展开,结合流程图与类图,帮助大家彻底掌握 Servlet 的核心原理。


一、Servlet 访问流程

浏览器向 Web 服务器发起请求,服务器根据 URL 映射找到对应的 Servlet,然后执行一系列操作。整个过程可以用下面的流程图表示:
自定义Servlet Servlet容器 Web服务器 浏览器 自定义Servlet Servlet容器 Web服务器 浏览器 发起HTTP请求 解析请求,定位Servlet 创建HttpServletRequest/HttpServletResponse对象 调用service()方法 处理请求并返回响应 封装响应对象 返回HTTP响应

关键点

  • 在调用 service() 方法之前,容器会自动创建 HttpServletRequestHttpServletResponse 对象。
  • service() 方法会根据请求类型(GET、POST 等)分发给对应的 doGet()doPost() 方法。
  • 响应结束后,容器负责将响应数据发送回浏览器。

二、Servlet 体系结构(UML 类图)

Servlet 规范中,我们通常继承 HttpServlet 来编写自己的业务逻辑。下图展示了 Servlet 核心接口与类的继承关系:
实现
继承
继承
<<interface>>
Servlet
+init(ServletConfig config)
+service(ServletRequest req, ServletResponse res)
+destroy()
+getServletConfig()
+getServletInfo()
<<abstract>>
GenericServlet
-config: ServletConfig
+init(ServletConfig config)
+init()
+getServletConfig()
+getServletContext()
+log(String msg)
+abstract service(ServletRequest req, ServletResponse res)
<<abstract>>
HttpServlet
+service(ServletRequest req, ServletResponse res)
+service(HttpServletRequest req, HttpServletResponse resp)
+doGet(HttpServletRequest req, HttpServletResponse resp)
+doPost(HttpServletRequest req, HttpServletResponse resp)
+doPut(...)
+doDelete(...)
MyServlet
+doGet(HttpServletRequest req, HttpServletResponse resp)
+doPost(HttpServletRequest req, HttpServletResponse resp)

说明

  • Servlet 接口定义了所有 Servlet 必须实现的生命周期方法。
  • GenericServlet 抽象类提供了 Servlet 接口的基本实现,并增加了日志、初始化参数等辅助方法,但依然保留了 service() 方法为抽象。
  • HttpServlet 进一步针对 HTTP 协议,将 service() 方法实现为请求类型分发器,并提供了 doGet()doPost() 等钩子方法。
  • 我们自定义的 Servlet 只需继承 HttpServlet,重写需要的 doXxx() 方法即可。

三、Servlet 生命周期

Servlet 由 Web 容器(如 Tomcat)管理,其生命周期分为四个阶段:加载实例化 → 初始化 → 服务 → 销毁。下面用流程图展示:
容器启动或首次请求
加载Servlet类并实例化
调用init方法初始化
等待请求
收到请求,调用service方法
容器关闭或应用卸载
调用destroy方法,释放资源

各阶段详解

阶段 时机 次数 说明
加载与实例化 首次访问 Servlet 时,或容器启动时(若配置了 <load-on-startup> 1次 通过反射调用无参构造器创建实例
初始化 实例化之后立即执行 1次 调用 init(ServletConfig config),可用于加载资源、获取配置
服务 每次收到请求 多次 调用 service() 方法,根据请求类型分发到 doGet/doPost
销毁 容器正常关闭或应用被卸载时 1次 调用 destroy() 方法,释放数据库连接等资源

注意

  • 默认情况下,Servlet 在第一次被访问时 才加载实例化。若希望在容器启动时就完成加载,可以在 web.xml 中配置 <load-on-startup> 正数(数值越小优先级越高)。
  • init() 只执行一次,且是线程安全的(容器保证单例)。

四、ServletConfig 与 ServletContext

这两个接口是 Servlet 编程中获取配置和共享数据的关键。

1. ServletConfig

作用范围每个 Servlet 私有 ,由容器在 init() 方法中传入。

主要功能

  • 获取当前 Servlet 在 web.xml 中配置的初始化参数(<init-param>)。
  • 获取当前 Servlet 的名称(<servlet-name>)。
  • 获取全局的 ServletContext 对象。

配置示例web.xml):

xml 复制代码
<servlet>
    <servlet-name>DemoServlet</servlet-name>
    <servlet-class>com.example.DemoServlet</servlet-class>
    <init-param>
        <param-name>encoding</param-name>
        <param-value>UTF-8</param-value>
    </init-param>
</servlet>

代码使用

java 复制代码
String encoding = getServletConfig().getInitParameter("encoding");
String servletName = getServletConfig().getServletName();
ServletContext context = getServletConfig().getServletContext();

2. ServletContext

作用范围整个 Web 应用共享 ,一个应用只有一个 ServletContext 对象。

主要功能

  • 获取全局初始化参数 :在 <context-param> 中配置的参数,所有 Servlet 均可读取。
  • 获取 Web 资源的绝对路径 :通过 getRealPath("/")getResourceAsStream() 读取配置文件、图片等。
  • 作为域对象 :在多个 Servlet 之间共享数据(setAttribute / getAttribute)。

配置示例web.xml):

xml 复制代码
<context-param>
    <param-name>globalConfig</param-name>
    <param-value>production</param-value>
</context-param>

代码使用

java 复制代码
// 获取全局参数
String config = getServletContext().getInitParameter("globalConfig");
// 获取文件真实路径
String realPath = getServletContext().getRealPath("/WEB-INF/config.properties");
// 存储共享数据
getServletContext().setAttribute("userCount", 100);
Integer count = (Integer) getServletContext().getAttribute("userCount");

五、总结

概念 核心要点
访问流程 浏览器 → Web服务器 → 容器创建 req/res → 调用 service → 返回响应
体系结构 Servlet(接口) → GenericServlet(抽象类) → HttpServlet(抽象类) → 自定义Servlet
生命周期 实例化(1次) → init(1次) → service(多次) → destroy(1次)
ServletConfig 每个 Servlet 私有,用于获取自身初始化参数及 ServletContext
ServletContext 整个应用共享,用于获取全局参数、资源路径、存储域数据
相关推荐
鱼鳞_2 小时前
Java学习笔记_Day27(Stream流)
java·笔记·学习
indexsunny2 小时前
互联网大厂Java面试实战:从Spring Boot到微服务架构的深度探讨
java·数据库·spring boot·安全·微服务·监控·面试实战
夕除2 小时前
javaweb--03
java
m0_677904842 小时前
K8s学习
java·学习·kubernetes
Fate_I_C2 小时前
Kotlin 内部类和嵌套类
java·开发语言·kotlin
宸津-代码粉碎机3 小时前
Spring Boot 4.0 实战技巧全解析
java·大数据·spring boot·后端·python
Makoto_Kimur3 小时前
Java Scanner 的 ACM 常用输入模板
java·数据结构·算法
0xDevNull3 小时前
Spring 核心教程:@Component vs @Bean 深度解析
java·后端
小碗羊肉3 小时前
【从零开始学Java | 第三十二篇】方法引用(Method Reference)
java·开发语言