Servlet 规范与 Tomcat 版本对照表 + JDK 兼容性

维护老 SSM/SSH 项目常遇到——web.xmlversion="2.5",跑起来应该配哪个 Tomcat?JDK 8 能跑吗?先给对照表:

Servlet 与 Tomcat 版本对照

Servlet 版本Tomcat 版本官方支持 JDK
Servlet 2.4Tomcat 5.0/5.5Java 1.4 / 5
Servlet 2.5Tomcat 6.xJava 5 / 6
Servlet 3.0Tomcat 7.xJava 6 / 7
Servlet 3.1Tomcat 8.0Java 7 / 8
Servlet 3.1Tomcat 8.5Java 7 / 8
Servlet 4.0Tomcat 9.xJava 8+
Jakarta Servlet 5Tomcat 10.xJava 8+
Jakarta Servlet 6Tomcat 11.xJava 17+

Tomcat 10 是分水岭——包名从 javax.servlet.* 改到 jakarta.servlet.*。老代码原封不动放 Tomcat 10 直接编译不过。

判断项目该用哪个

打开 web.xml,看头部:

<web-app version="2.5"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
        http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
</web-app>

version="2.5" 就是 Servlet 2.5,对应 Tomcat 6+。

JDK 8 能跑 Servlet 2.5 项目吗

能。稳定组合

推荐
Servlet 规范2.5(保持 web.xml 不变)
Tomcat7.0.109(最后一个 7.x)
JDK1.8
Spring3.x / 4.x
MyBatis3.x

理由:

  • Tomcat 7 向下兼容 Servlet 2.5(Tomcat 是超集)
  • Tomcat 7 完整支持 JDK 8,无 PermGen 问题
  • Tomcat 6 对 JDK 8 支持不完整,从 6.0.53 才勉强能跑,还是别用了

迁移 Tomcat 6 到 Tomcat 7 要改什么

九成情况什么都不用改。真要改的坑:

1. web.xml schema 版本:可以不动。Tomcat 7 依然接受 web-app version="2.5"

2. JSP 的 EL 表达式:Tomcat 7 默认 EL 2.2、Tomcat 6 是 EL 2.1。有些字符串比较写法(比如 ${x eq null})在两版本略有差异,一般不影响。

3. 端口 / 编码server.xml 里 Connector 改:

<Connector port="8080" protocol="HTTP/1.1"
           connectionTimeout="20000"
           URIEncoding="UTF-8"
           redirectPort="8443" />

URIEncoding="UTF-8" 治所有 GET 参数中文乱码。

4. session:Tomcat 7 默认关闭了 sessionId URL 追加(;jsessionid=xxx)。老 JSP 依赖 <c:url> 处理会不同,一般不影响。

Maven 里跑 Tomcat:tomcat7-maven-plugin

不装 Tomcat 也能跑,用 Maven 插件:

<build>
  <plugins>
    <plugin>
      <groupId>org.apache.tomcat.maven</groupId>
      <artifactId>tomcat7-maven-plugin</artifactId>
      <version>2.2</version>
      <configuration>
        <port>8080</port>
        <path>/</path>
        <uriEncoding>UTF-8</uriEncoding>
      </configuration>
    </plugin>
  </plugins>
</build>

跑:

mvn tomcat7:run

这个插件已经没维护 10 多年了,但对 Servlet 2.5 老项目照样能跑。生产别用,本地开发够。

Tomcat 8/9 呢

Servlet 2.5 项目理论上放 Tomcat 8/9 也能跑(javax.servlet 包名不变)。但会遇到:

  • 老 Spring 3.x 和 Tomcat 8 的 WebSocket 冲突
  • 一些 EL 2.2 / 3.0 的表达式行为差异
  • JSP 编译器更严格

迁移建议:如果项目还在开发新功能,直接升到 Tomcat 9 + JDK 8 + Servlet 3.x(web.xml 头改一下);只是维护,稳留 Tomcat 7 + JDK 8。

Tomcat 10+ 的 jakarta 大坑

老代码:

import javax.servlet.http.HttpServletRequest;

Tomcat 10 只认:

import jakarta.servlet.http.HttpServletRequest;

想迁移,用官方工具批量替换:

# Eclipse Transformer
java -jar org.eclipse.transformer.cli-*.jar \
    --input old.war --output new.war

或者手工找替换:

find . -name "*.java" -exec sed -i 's/javax\.servlet/jakarta.servlet/g' {} +

改完还要处理 Spring 版本——Spring 5.x 只支持 javax.servlet,要 jakarta 得升到 Spring 6.x(同时 JDK 17+)。这是个大工程,不是小改

一句话总结

老 Servlet 2.5 项目最稳的组合是 Tomcat 7.0.109 + JDK 8。Tomcat 10 起改包名 jakarta,迁移是大工程。开发用 tomcat7-maven-plugin 快。