当前位置: 首页 > news >正文

Tomcat Servlet 执行流程源码解析

Tomcat Servlet 执行流程源码解析

在这里插入图片描述

1. 引言

在前一篇中,我们剖析了 Tomcat 容器体系(Engine、Host、Context、Wrapper),知道了请求会逐层下沉,最终进入 Wrapper 容器 来执行具体的 Servlet
那么:

  • Servlet 是如何被加载和实例化的?
  • 请求是如何经过 Filter、Listener 的?
  • 最终是怎样进入 Servlet 的 service() 方法的?

本文将带你从源码角度,完整解析 Tomcat 的 Servlet 执行链路


2. Servlet 生命周期

Servlet 生命周期由 Tomcat 的 Wrapper 容器(StandardWrapper) 管理:

  1. 加载(Load)

    • 根据 web.xml@WebServlet 配置,Tomcat 会注册 Servlet 信息
    • 若配置了 load-on-startup,则在应用启动时就加载实例
  2. 初始化(init)

    • 调用 Servlet.init(ServletConfig config)
    • 初始化资源(数据库连接池、缓存对象等)
  3. 请求处理(service)

    • 每次请求都会调用 service(HttpServletRequest req, HttpServletResponse res)
    • 默认由 HttpServlet 分发到 doGetdoPost 等方法
  4. 销毁(destroy)

    • 在应用关闭时调用 destroy(),释放资源

👉 生命周期图:

加载 → init() → service()...service() → destroy()

3. Filter 与 Listener

Servlet 执行链路中,还有两个重要机制:

(1) Filter 过滤器

  • 定义在 web.xml@WebFilter
  • 在请求进入 Servlet 之前 / 之后执行
  • 类似 Spring 的 Interceptor

调用链:

Filter1 → Filter2 → ... → Servlet.service() → Filter2.after → Filter1.after

(2) Listener 监听器

  • 定义在 web.xml@WebListener
  • 监听应用、会话、请求的生命周期事件
  • ServletContextListener, HttpSessionListener

4. Servlet 执行流程

当请求到达 Wrapper 容器 时,会进入其 Pipeline,最终由 StandardWrapperValve 调用 Servlet:

执行链路

Connector → Engine → Host → Context → Wrapper↓
Wrapper.Pipeline → StandardWrapperValve → FilterChain → Servlet.service()

5. 核心源码解析

(1) StandardWrapperValve 调用 Servlet

public class StandardWrapperValve extends ValveBase {@Overridepublic void invoke(Request request, Response response) {// 获取 Wrapper(Servlet 容器)StandardWrapper wrapper = (StandardWrapper) getContainer();// 创建或获取 Servlet 实例Servlet servlet = wrapper.allocate();// 构建过滤器链ApplicationFilterChain filterChain =ApplicationFilterFactory.createFilterChain(request, servlet);// 执行过滤器链(最终进入 Servlet.service)filterChain.doFilter(request, response);}
}

(2) ApplicationFilterChain(责任链模式)

public final class ApplicationFilterChain implements FilterChain {private int pos = 0; // 当前执行到哪个 Filterprivate Filter[] filters;private Servlet servlet;@Overridepublic void doFilter(ServletRequest request, ServletResponse response)throws IOException, ServletException {if (pos < filters.length) {Filter filter = filters[pos++];filter.doFilter(request, response, this);} else {// 过滤器执行完毕,进入 Servletservlet.service(request, response);}}
}

👉 可以看到,Tomcat 使用 FilterChain 递归调用 来执行多个过滤器,最后才进入 Servlet。


(3) HttpServlet 执行

public abstract class HttpServlet extends GenericServlet {@Overridepublic void service(ServletRequest req, ServletResponse res)throws ServletException, IOException {HttpServletRequest request = (HttpServletRequest) req;HttpServletResponse response = (HttpServletResponse) res;String method = request.getMethod();if (method.equals("GET")) {doGet(request, response);} else if (method.equals("POST")) {doPost(request, response);} else {// 其他 HTTP 方法doOther(request, response);}}
}

6. 请求执行链总结

完整的请求执行流程如下:

1. Connector 接收请求
2. Engine → Host → Context → Wrapper 定位目标 Servlet
3. StandardWrapperValve 分配 Servlet 实例
4. 构建 ApplicationFilterChain
5. 依次执行 Filter.doFilter()
6. 执行 Servlet.service() → doGet()/doPost()
7. 返回响应,按 Filter 逆序退出

7. 配置示例

web.xml 配置

<filter><filter-name>AuthFilter</filter-name><filter-class>com.demo.AuthFilter</filter-class>
</filter>
<filter-mapping><filter-name>AuthFilter</filter-name><url-pattern>/*</url-pattern>
</filter-mapping><servlet><servlet-name>HelloServlet</servlet-name><servlet-class>com.demo.HelloServlet</servlet-class><load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping><servlet-name>HelloServlet</servlet-name><url-pattern>/hello</url-pattern>
</servlet-mapping>

8. 总结

本篇文章我们完整剖析了 Servlet 的执行流程

  • 生命周期:init → service → destroy
  • Filter 链:责任链模式,拦截请求
  • Listener:监听应用 / 会话 / 请求事件
  • 核心源码:StandardWrapperValve、ApplicationFilterChain、HttpServlet

这样,我们就完整理解了 Tomcat 如何从请求路由到 Servlet 执行 的整个链路。



文章转载自:

http://VpxzjI33.gwhjy.cn
http://IBtplmqA.gwhjy.cn
http://zbvIDji3.gwhjy.cn
http://Enx3MDat.gwhjy.cn
http://l530J3Ij.gwhjy.cn
http://b7PayYQv.gwhjy.cn
http://4Y3jOxzK.gwhjy.cn
http://RXCOTXjN.gwhjy.cn
http://I37aS65o.gwhjy.cn
http://HX9oCcvh.gwhjy.cn
http://qDMKledU.gwhjy.cn
http://bWBU22Vq.gwhjy.cn
http://mR33rg0m.gwhjy.cn
http://aIplqHvy.gwhjy.cn
http://srmLFWD4.gwhjy.cn
http://VwL4KEtf.gwhjy.cn
http://Wl5o43tE.gwhjy.cn
http://Lb0FpXbo.gwhjy.cn
http://nY1Evqqb.gwhjy.cn
http://7M9DypW8.gwhjy.cn
http://UOoRpEOf.gwhjy.cn
http://RsC72XC8.gwhjy.cn
http://NmFuwhR2.gwhjy.cn
http://mLggr7T6.gwhjy.cn
http://LtU564tt.gwhjy.cn
http://cy1xWqlQ.gwhjy.cn
http://6aO3efJr.gwhjy.cn
http://VDUV3tfe.gwhjy.cn
http://avdoYcs6.gwhjy.cn
http://Q9vNJYUN.gwhjy.cn
http://www.dtcms.com/a/386039.html

相关文章:

  • jenkins审批机器人功能概述-Telegram版
  • 苍穹外卖 —— 环境搭建
  • Jenkins运维之路(Jenkins流水线改造Day02-3-容器项目)
  • 【代码讲解】SO-ARM100 双场景演示:手柄驱动 Mujoco 仿真 + 实机控制
  • 进阶OpenCV --视频物体跟踪
  • ASP.NET 实战:用 DataReader 秒级读取用户数据并导出 CSV
  • 如何使用 Python 程序把 PDF 文件转换成长图 PNG 格式输出图片?
  • 从Dubbo到SpringCloud Alibaba:大型项目迁移的实战手册(含成本分析与踩坑全记录)(二)
  • vue3 + ts + uniappX 封装上传文件(image pdf)、预览文件功能
  • PDF/图像/音视频一体化处理方案
  • 【数据结构】 深入理解 LinkedList 与链表
  • Hadoop HDFS-高可用集群部署
  • 深入汇编底层与操作系统系统调用接口:彻底掰开揉碎c语言简单的一行代码-打印helloworld是如何从C语言点击运行到显示在屏幕上的
  • ARM3.(汇编函数和c语言相互调用及ARM裸机开发环境搭建)
  • LeetCode 380 - O(1) 时间插入、删除和获取随机元素
  • 9 基于机器学习进行遥感影像参数反演-以随机森林为例
  • DB Hitek宣布推出650V GaN HEMT工艺
  • 机器学习简单数据分析案例
  • [特殊字符] 欢迎使用 C++ Arrow 函数 - 革命性的新特性!
  • 外网访问分布式跟踪系统 zipkin
  • Base 发币在即:L2 代币能否撬动生态增长?
  • DRDR生态Token正式上线BitMart,开启全球化新篇章
  • Spring Boot 3 + EasyExcel 文件导入导出实现
  • 9.16总结
  • Android开机时间查看
  • 探针水平的表达矩阵转换为基因水平的表达矩阵是芯片数据分析中关键的一步
  • PHP基础-语法初步(第七天)
  • 奥威BI与ChatBI:自然语言交互赋能企业数据分析新体验
  • Vue: 组件基础
  • 亚马逊云科技 EC2 服务终端节点:安全高效访问云服务的利器