gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-03 20:23:50 34 4
gpt4 key购买 nike

我一直在徒劳地尝试实现 tomcat 9 的 jakarta servlet,而不是以前的 javax.servlet 实现(因为我的理解是 jakarta 包是前进的方向)。问题是,当我将浏览器指向我的 servlet 的 url 时,我收到以下错误...

java.lang.ClassCastException: class cti.nm.web.Index cannot be cast to class javax.servlet.Servlet (cti.nm.web.Index is in unnamed module of loader org.apache.catalina.loader.ParallelWebappClassLoader @48c76607; javax.servlet.Servlet is in unnamed module of loader java.net.URLClassLoader @621be5d1)
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:690)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
org.apache.coyote.ajp.AjpProcessor.service(AjpProcessor.java:432)
org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:888)
org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1597)
org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
java.base/java.lang.Thread.run(Thread.java:832)
问题已经很明显了。 Tomcat 正在尝试将我的 jakarta.servlet.http.HttpServlet 转换为 javax.servlet.Servlet,这显然不起作用。我无法想象的是如何告诉它 servlet 实际实现的类。
类本身被声明为...
package cti.nm.web;
import jakarta.servlet.http.HttpServlet;
import java.io.IOException;
import java.io.PrintWriter;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

public class Index extends HttpServlet {

public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {

response.setContentType("text/html");
//print a bunch of stuff
}
}

我的 web.xml 文件如下...
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
version="5.0">

<display-name>NMWeb</display-name>
<description>
NMWeb Description
</description>

<servlet>
<servlet-name>Index</servlet-name>
<servlet-class>cti.nm.web.Index</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>Index</servlet-name>
<url-pattern>/NMWeb</url-pattern>
</servlet-mapping>

</web-app>
我曾希望在部署描述符中使用正确的 jakartaee xml 模式会导致使用正确的类,但显然不是。 war 似乎包含适当的 jar ......
jakarta.jakartaee-api-9.0.0.jar
tomcat-el-api-10.0.0.jar
tomcat-servlet-api-10.0.0.jar
jakarta.servlet-api-5.0.0.jar
tomcat-jsp-api-10.0.0.jar
pom 被指定为 ...
<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>cti.nm.NMWeb</groupId>
<artifactId>NMWeb</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>

<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.3</version>
<configuration>
<warSourceDirectory>WebContent</warSourceDirectory>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>jakarta.platform</groupId>
<artifactId>jakarta.jakartaee-api</artifactId>
<version>[9.0.0,)</version>

</dependency>
<!-- https://mvnrepository.com/artifact/jakarta.servlet/jakarta.servlet-api -->
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>[5.0.0,)</version>

</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.tomcat/tomcat-jsp-api -->
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jsp-api</artifactId>
<version>[10.0.0,)</version>

</dependency>
</dependencies>
</project>
在网上搜索这个问题的答案已经有几天了,我似乎找不到这种确切情况的任何其他实例。我应该提到这是我手动修改的 Eclipse 生成的对象。当我部署 war 文件时,使用 maven 和 eclipse 构建会生成相同的结果。

最佳答案

您基本上是在 WAR 中实际包含 Tomcat 10.x 特定库,然后将 WAR 部署到 Tomcat 9.x。这根本不是正确的方法。此外,Tomcat 10.x 是第一个被 Jakartified 的版本,而不是 Tomcat 9.x。
对于基于 Servlet 4.0、JSP 2.3、EL 3.0、WS 1.1 和 JASIC 1.0 的 Tomcat 9.x,您应该使用 javax.*进口和整个 <dependencies>部分应该至少看起来像:

<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.*进口和 整个 <dependencies>部分应该至少看起来像:
<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>
请注意 <scope>明确设置为 provided对他们来说,这意味着 Maven 应该 不是 /WEB-INF/lib 中包含物理 JAR 文件生成的 WAR 文件(因为它已经由 Tomcat 本身提供了!)。否则,您只会因运行时类路径中的重复类而导致运行时冲突。
另请注意,Tomcat 是 不是 一个 JEE 服务器,从而导入 javax:javaee-api对于 Tomcat 9.x 或 jakarta.platform:jakarta.jakartaee-api Tomcat 10.x 的定义是错误的。因为它允许您针对其他 JEE 组件(例如 JSF、JSTL、CDI、BV、EJB、JPA、JAX-RS、JSONB 等)编译代码,而 Tomcat 实际上并没有提供它们。 Tomcat only offers Servlet, JSP, EL, WS and JASIC out the box ,所以你应该只在 pom.xml 中声明它们.
例如JSTL需要按照 How to install JSTL? The absolute uri: http://java.sun.com/jstl/core cannot be resolved中的说明单独安装。和 JSF 需要按照 How to properly install and configure JSF libraries via Maven? 中的说明单独安装和 CDI 需要按照 How to install and use CDI on Tomcat? 中的说明单独安装
但是,如果您在为 Tomcat 开发代码期间非常清楚这个限制(即确保您自己不会意外使用例如 JSTL、CDI、BV、JPA 等,而没有先在 Tomcat 中实际安装它们),并且只是想要最小化 pom.xml样板文件,那么您也可以使用 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:
<dependencies>
<dependency>
<groupId>jakarta.platform</groupId>
<artifactId>jakarta.jakartaee-web-api</artifactId>
<version>9.0.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
也可以看看:
  • Tomcat versions
  • What exactly is Java EE?
  • 关于maven - Tomcat 将 servlet 转换为 javax.servlet.Servlet 而不是 jakarta.servlet.http.HttpServlet,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65703840/

    34 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com