我一直在徒劳地尝试实现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
jakarta.服务程序-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生成的probject,我已经手动修改过了。当我部署war文件时,使用maven和eclipse生成的结果是一样的。
1条答案
按热度按时间8fsztsew1#
您基本上是在WAR中物理地包含Tomcat 10.x特定的库,然后将WAR部署到Tomcat 9.x。这根本不是正确的方法。此外,Tomcat 10.x是第一个被Jakartified化的版本,而不是Tomcat 9.x。
Tomcat 9.x版本
对于基于Servlet 4.0、JSP 2.3、EL 3.0、WS 1.1和JASIC 1.0的Tomcat 9.x,您应该使用
javax.*
导入,并且整个<dependencies>
部分 * 至少 * 应该如下所示:Tomcat 10.0.x版本
对于基于Servlet 5.0、JSP 3.0、EL 4.0、WS 2.0和JASIC 2.0的Tomcat 10.0.x,您应该使用
jakarta.*
导入,并且整个<dependencies>
部分 * 至少 * 应该如下所示:Tomcat 10.1.x版本
对于基于Servlet 6.0、JSP 3.1、EL 5.0、WS 2.1和JASIC 3.0的Tomcat 10.1.x,您应该使用
jakarta.*
导入,并且整个<dependencies>
部分 * 至少 * 应该如下所示:无论如何
请注意,
<scope>
被显式地设置为provided
,这意味着Maven不将物理JAR文件包含在生成的WAR文件的/WEB-INF/lib
中(因为它已经由Tomcat本身提供了!)。否则,您只会在运行时类路径中的重复类引起的运行时冲突中结束。另外请注意Tomcat不是JEE服务器,因此根据定义导入
javax:javaee-api
for Tomcat 9.x或jakarta.platform:jakarta.jakartaee-api
for 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无法解析,JSF需要按照如何通过Maven?正确安装和配置JSF库中的说明单独安装,CDI需要按照如何在Tomcat上安装和使用CDI?中的说明单独安装
然而,如果您在开发Tomcat代码时非常清楚这个限制(即,确保您不会意外地使用JSTL、CDI、BV、JPA等,而没有首先在Tomcat中实际安装它们),并且只想最小化
pom.xml
样板文件,那么您也可以使用Tomcat 9.x的这种最小依赖关系配置:对于Tomcat 10.0.x,请执行以下操作:
对于Tomcat 10.1.x,请执行以下操作:
另请参阅: