Servlet 与 Tomcat

最后更新: 2025-07-31 23:33:22 +0800 +0800
tags: Java | Servlet | Tomcat
原文以英文撰写。您正在阅读AI翻译版本。

Jakarta Servlet API 定义服务器端请求和响应模型。Apache Tomcat 实现该 API, 并提供 Catalina servlet 容器、HTTP 和 AJP 连接器、会话管理、部署和运维工具。 Tomcat 11 实现 Jakarta Servlet 6.1 并需要 Java 17;导入 javax.servlet.* 的旧应用 需要迁移到 jakarta.servlet.* 命名空间,或使用较旧的兼容容器。

Web 应用布局 #

可部署的 Web 应用可以是展开目录或 WAR 归档:

text
orders.war
|-- index.html
`-- WEB-INF
    |-- web.xml
    |-- classes/com/example/OrdersServlet.class
    `-- lib/orders-domain.jar

WEB-INF/ 下的资源不能由客户端直接寻址。WEB-INF/classes/ 包含应用类和资源, WEB-INF/lib/ 包含依赖 JAR。WEB-INF/web.xml 是部署描述符。 Servlet 3.0 及更高版本还支持基于注解的注册,以及通过 ServletContainerInitializer 进行程序化注册, 因此除非部署需要描述符元数据或排序,否则可以省略 web.xml。

映射和请求分派 #

Servlet 映射根据 URL 模式选择 servlet。精确映射优先于最长路径映射, 随后是扩展名映射和默认 / 映射。过滤器可以在目标之前或之后包装请求和响应, 监听器则观察上下文、会话和请求生命周期事件。

分派具有不同的 DispatcherType 值:

  • REQUEST 表示原始容器分派。
  • FORWARD 在不经过客户端往返的情况下转移处理。
  • INCLUDE 插入另一个资源的输出。
  • ERROR 调用配置的错误处理。
  • ASYNC 继续处理异步请求。
java
request.getRequestDispatcher("/WEB-INF/views/order.jsp")
       .forward(request, response);

重定向则发送 3xx 响应,之后客户端开始新请求。在正常分派期间,连接器解析请求, Catalina 选择虚拟主机和 Web 上下文,过滤器链运行,一个 servlet 实例处理调用。 容器会并发调用 servlet,因此可变实例字段需要同步,或者最好完全消除。

会话通过 Cookie 或 URL 重写标识。并发请求可能访问会话属性,不能将它们视为线程私有。 异步处理会释放请求线程,但应用必须完成 AsyncContext,并保留所需的安全或日志上下文。

Tomcat 的容器模型 #

org.apache.catalina.startup.Bootstrap 启动独立安装。 catalina.home 指向共享的 Tomcat 二进制文件,而 catalina.base 指向实例的配置、日志、 临时文件、工作目录和已部署应用。因此多个实例可以共享一个安装。

Catalina 组合以下元素:

  1. Server 拥有 Tomcat 实例。
  2. Service 将一个或多个 Connector 与一个 Engine 关联。
  3. Engine 将请求路由到 Host。
  4. Host 包含一个或多个 Web 应用 Context。
  5. Wrapper 表示单个 servlet。

连接器负责协议处理和工作线程。阻塞式 servlet 工作会占用这些线程, 因此连接器限制、下游超时和应用执行器限制必须形成一个统一的容量计划。

类加载器和关闭 #

Tomcat 分离引导、系统、公共和每个 Web 应用的类加载器。 Web 应用可以看到自己的 WEB-INF/classes 和 WEB-INF/lib,但看不到其他应用的类。 Tomcat 的 Web 加载器对应用类使用本地优先查找,但对 Java、Jakarta Servlet 和容器实现 API 必须委派。WEB-INF/lib 中重复的 API JAR 不会覆盖容器 API,并可能导致链接失败。

为实现优雅关闭,停止接受新流量,在截止时间内允许进行中的工作完成,然后停止 Server。 Servlet 上下文监听器和受管资源会收到关闭回调,但应用创建的执行器和线程仍需要显式终止。 会话持久化取决于配置的管理器,不得假设重启后仍然存在。

主要参考资料 #

评论

在 GitHub 上阅读或评论(发表评论需要登录)