Apache Tomcat 11.0.24 已发布,这个版本继续面向 Jakarta EE 11 平台实现部分规范。对正在运行 Tomcat 10 或更高版本的团队来说,真正需要盯紧的不是小版本号本身,而是 Java EE 迁移到 Eclipse 基金会后带来的包名变化:已实现 API 的主包已经从 javax.* 变为 jakarta.*。这不是配置开关能解决的问题,绝大多数旧应用都需要改代码、改依赖、重新测试。
版本号背后的实际影响
Tomcat 11 属于 Jakarta EE 时代的容器。公告里强调“实现 Jakarta EE 11 平台的部分规范”,这意味着它不是 Java EE 8 时代应用的原地运行环境,也不是旧 javax.servlet.* 代码的透明兼容层。
最常见的断点会出现在这些地方:
- Servlet、Filter、Listener 的 import:
javax.servlet.*需要改成jakarta.servlet.* - JSP、EL、WebSocket 等相关 API 的依赖坐标可能需要同步升级
- 编译期依赖和运行期容器版本必须对齐,不能代码用
javax、容器用jakarta - 第三方库如果还停留在旧 Java EE API,也可能拖住整个升级
这类升级最好按“编译先过、启动再过、请求路径再过”的顺序推进。不要一上来把 JDK、Spring、Tomcat、数据库驱动一起升级,否则排错面会被拉得很大。
最小代码改造:Servlet 从 javax 迁到 jakarta
可以这样实践:先拿一个最小 Servlet 验证你的构建链路和 Tomcat 11 是否匹配。下面示例使用 Maven 和 Jakarta Servlet API。运行前请确认本机已安装 JDK 17 或更高版本,并把项目部署到 Tomcat 11。
pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>demo</groupId>
<artifactId>tomcat11-jakarta-demo</artifactId>
<version>1.0.0</version>
<packaging>war</packaging>
<properties>
<maven.compiler.release>17</maven.compiler.release>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>6.1.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
src/main/java/demo/HelloServlet.java:
package demo;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/plain;charset=UTF-8");
response.getWriter().println("Hello from Tomcat 11 and Jakarta Servlet");
}
}
构建 WAR:
mvn clean package
把生成的 target/tomcat11-jakarta-demo-1.0.0.war 放到 Tomcat 11 的 webapps/ 目录后访问:
curl http://localhost:8080/tomcat11-jakarta-demo-1.0.0/hello
如果你把 import 写成旧的 javax.servlet.http.HttpServlet,在 Tomcat 11 方向的项目里通常会先在编译阶段暴露问题;如果通过某些旧依赖侥幸编译,运行时也可能因为 API 不匹配失败。
用命令先扫出高风险代码
正式迁移前,可以先粗略扫描项目里还残留多少 javax 引用。下面命令不会修改文件,只用于盘点。
rg "import javax\.|javax\.servlet|javax\.websocket|javax\.annotation" src pom.xml build.gradle settings.gradle
如果你想看每类引用数量,可以这样做:
rg -o "javax\.[A-Za-z0-9_.]+" src pom.xml build.gradle 2>/dev/null | sort | uniq -c | sort -nr
这个结果可以帮助你拆迁移任务:Servlet API 通常优先处理;JPA、Validation、Mail、XML Binding 等包如果也出现,需要结合应用框架版本一起评估,不能只做文本替换。
容器验证:用独立 Tomcat 做冒烟测试
可以这样实践:用官方 Tomcat 11 镜像跑一个干净容器,把 WAR 挂进去,避免本机旧容器、旧环境变量干扰判断。
mvn clean package
mkdir -p /tmp/tomcat11-webapps
cp target/tomcat11-jakarta-demo-1.0.0.war /tmp/tomcat11-webapps/demo.war
docker run --rm \
-p 8080:8080 \
-v /tmp/tomcat11-webapps:/usr/local/tomcat/webapps \
tomcat:11-jdk17
另开一个终端请求:
curl http://localhost:8080/demo/hello
这里需要根据你的实际镜像策略调整标签,例如 JDK 版本、基础镜像来源和漏洞扫描要求。示例重点是隔离验证:确认 WAR 在 Tomcat 11 上能部署、能启动、能响应。
升级建议:别把包名迁移当成搜索替换
Tomcat 11.0.24 的发布提醒再次说明,Jakarta 迁移已经是 Tomcat 10 之后的基本前提。实际落地时建议按下面清单推进:
- 先确认应用框架是否支持 Jakarta EE 版本,例如 Spring、Jersey、CXF、JSF 等
- 把
javax.*import、Maven/Gradle 依赖、测试代码一起纳入迁移范围 - 为关键请求路径补上集成测试,尤其是登录、文件上传、Filter 链、Session、WebSocket
- 用独立 Tomcat 11 环境做部署验证,不要只依赖 IDE 内置服务器
- 检查第三方库是否仍依赖旧 Java EE API,必要时升级或替换
边界也要讲清楚:如果你的应用还深度绑定旧框架,短期内直接跳到 Tomcat 11 可能成本很高。更稳的路线是先完成 javax 到 jakarta 的依赖梳理,再升级框架主版本,最后切换运行容器。Tomcat 小版本可以快速跟进,但 Jakarta 迁移必须按工程变更处理。