且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

Tomcat 将 servlet 转换为 javax.servlet.Servlet 而不是 jakarta.servlet.http.HttpServlet

更新时间:2023-11-16 17:06:40

您基本上是在 WAR 中实际包含 Tomcat 10.x 特定库,然后将 WAR 部署到 Tomcat 9.x.这根本不是正确的方法.此外,Tomcat 10.x 是第一个被 Jakartified 的版本,而不是 Tomcat 9.x.

You're basically physically including Tomcat 10.x specific libraries in WAR and then deploying the WAR to Tomcat 9.x. This is not the correct approach at all. Moreover, Tomcat 10.x was the first version to be Jakartified, not Tomcat 9.x.

对于基于 Servlet 4.0、JSP 2.3、EL 3.0、WS 1.1 和 JASIC 1.0 的 Tomcat 9.x,您应该使用 javax.* 导入和 整个strong> 部分应该最少看起来像:

For Tomcat 9.x, which is based on Servlet 4.0, JSP 2.3, EL 3.0, WS 1.1 and JASIC 1.0, you should use javax.* imports and the entire <dependencies> section should minimally look like:

<dependencies>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>4.0.0</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>javax.servlet.jsp-api</artifactId>
        <version>2.3.0</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>javax.el</groupId>
        <artifactId>javax.el-api</artifactId>
        <version>3.0.0</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>javax.websocket</groupId>
        <artifactId>javax.websocket-api</artifactId>
        <version>1.1</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>javax.security.enterprise</groupId>
        <artifactId>javax.security.enterprise-api</artifactId>
        <version>1.0</version>
        <scope>provided</scope>
    </dependency>
</dependencies>

对于基于 Servlet 5.0、JSP 3.0、EL 4.0、WS 2.0 和 JASIC 2.0 的 Tomcat 10.x,您应该使用 jakarta.* 导入和 整个strong> 部分应该最少看起来像:

For Tomcat 10.x, which is based on Servlet 5.0, JSP 3.0, EL 4.0, WS 2.0 and JASIC 2.0, you should use jakarta.* imports and the entire <dependencies> section should minimally look like:

<dependencies>
    <dependency>
        <groupId>jakarta.servlet</groupId>
        <artifactId>jakarta.servlet-api</artifactId>
        <version>5.0.0</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>jakarta.servlet.jsp</groupId>
        <artifactId>jakarta.servlet.jsp-api</artifactId>
        <version>3.0.0</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>jakarta.el</groupId>
        <artifactId>jakarta.el-api</artifactId>
        <version>4.0.0</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>jakarta.websocket</groupId>
        <artifactId>jakarta.websocket-api</artifactId>
        <version>2.0.0</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>jakarta.security.enterprise</groupId>
        <artifactId>jakarta.security.enterprise-api</artifactId>
        <version>2.0.0</version>
        <scope>provided</scope>
    </dependency>
</dependencies>

请注意, 为它们显式设置为 provided,这意味着 Maven 应该包含物理 JAR生成的 WAR 文件的 /WEB-INF/lib 中的文件(因为它已经由 Tomcat 本身提供了!).否则,您只会因运行时类路径中的重复类而导致运行时冲突.

Please note that the <scope> is explicitly set to provided for them, which means that Maven should not include the physical JAR files in /WEB-INF/lib of the generated WAR file (because it's already provided by Tomcat itself!). Otherwise you only end up in runtime conflicts caused by duplicate classes in the runtime classpath.

另请注意,Tomcat 不是 JEE 服务器,因此为 Tomcat 9.x 或 jakarta.platform:jakarta 导入 javax:javaee-apiTomcat 10.x 的 .jakartaee-api 是每个定义错误的.因为它允许您针对其他 JEE 组件(例如 JSF、JSTL、CDI、BV、EJB、JPA、JAX-RS、JSONB 等)编译您的代码,而 Tomcat 实际上并没有直接提供它们.Tomcat 仅提供开箱即用的 Servlet、JSP、EL、WS 和 JASIC,因此您只需声明它们在 pom.xml 中.

Please also note that Tomcat is not a JEE server and thus importing either javax:javaee-api for Tomcat 9.x or jakarta.platform:jakarta.jakartaee-api for Tomcat 10.x is per definition wrong. Because it will allow you to compile your code against other JEE components such as JSF, JSTL, CDI, BV, EJB, JPA, JAX-RS, JSONB, etc etc while Tomcat actually doesn't offer them out the box. Tomcat only offers Servlet, JSP, EL, WS and JASIC out the box, so you should only declare them in pom.xml.

例如JSTL需要按照如何安装JSTL?绝对uri:http://java.sun.com/jstl/core无法解析,需要按照如何通过Maven正确安装和配置JSF库?和CDI需要按照说明单独安装在如何在Tomcat上安装和使用CDI?一个>

For example, JSTL needs to be installed separately as instructed in How to install JSTL? The absolute uri: http://java.sun.com/jstl/core cannot be resolved and JSF needs to be installed separately as instructed in How to properly install and configure JSF libraries via Maven? and CDI needs to be installed separately as instructed in How to install and use CDI on Tomcat?

如果您在为 Tomcat 开发代码的过程中非常清楚这个限制(即确保自己不会在没有先在 Tomcat 中实际安装它们的情况下意外使用例如 JSTL、CDI、BV、JPA 等),并且只想最小化 pom.xml 样板文件,那么您也可以使用 Tomcat 9.x 的这种最小化依赖项配置:

If you're however very well aware of this limitation during developing code for Tomcat (i.e. make sure yourself that you don't accidentally use e.g. JSTL, CDI, BV, JPA, etc without actually installing them in Tomcat first), and merely want to minimize pom.xml boilerplate, then you can also get away with this minimalist dependencies configuration for Tomcat 9.x:

<dependencies>
    <dependency>
        <groupId>javax</groupId>
        <artifactId>javaee-web-api</artifactId>
        <version>8.0</version>
        <scope>provided</scope>
    </dependency>
</dependencies>

或者对于 Tomcat 10.x:

Or this for Tomcat 10.x:

<dependencies>
    <dependency>
        <groupId>jakarta.platform</groupId>
        <artifactId>jakarta.jakartaee-web-api</artifactId>
        <version>9.0.0</version>
        <scope>provided</scope>
    </dependency>
</dependencies>

另见: