Tomcat将servlet转换为javax.servlet.Servlet而不是jakarta.servlet.http.HttpServlet [英] Tomcat casting servlets to javax.servlet.Servlet instead of jakarta.servlet.http.HttpServlet

查看:354
本文介绍了Tomcat将servlet转换为javax.servlet.Servlet而不是jakarta.servlet.http.HttpServlet的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

与先前的javax.servlet实现相反,我一直在徒劳地尝试实现tomcat 9的jakarta servlet(据我所知,jakarta软件包是前进的方向).问题是,当我将浏览器指向servlet的URL时,出现以下错误...

I have been trying in vain to implement tomcat 9's jakarta servlet as opposed to the previous javax.servlet implementation (as its my understanding that the jakarta package is the way forward). The issue is that when I point the browser at my servlet's url I get the following error(s)...

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实际上正在实现什么类.

The problem is obvious enough. Tomcat is trying to cast my jakarta.servlet.http.HttpServlet to a javax.servlet.Servlet which clearly won't work. What I can't figure is how to tell it what class the servlet is actually implementing.

该类本身被声明为...

The class itself is declared as ...

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文件如下...

My web.xml file is as follows ...

<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模式会导致使用正确的句柄,但显然不会.战争似乎包含适当的罐子...

I had hoped that using the proper jakartaee xml schema in the deployment descriptor would cause the correct clases to be used but apparently not. The WAR seems to contain the proper jars ...

jakarta.jakartaee-api-9.0.0.jar
tomcat-el-api-10.0.0.jar
tomcat-servlet-api-10.0.0.jarjakarta.servlet-api-5.0.0.jar
tomcat-jsp-api-10.0.0.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被指定为...

The pom is specified as ...

<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进行构建会产生相同的结果.

It's been days of searching the web for answers to this question and I can't seem to find any other instances of this exact scenario. I should mention that this is an eclipse generated probject that I have manually modified. Building with both maven and eclipse generates the same results when I deploy the war file.

推荐答案

基本上,您实际上是在WAR中包括特定于Tomcat 10.x的库,然后将WAR部署到Tomcat9.x.这根本不是正确的方法.而且,Tomcat 10.x是第一个被Jakart化的版本,而不是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.

对于Tomcat 9.x,您应该使用 javax.* 导入,并且整个 < dependencies> 部分应如下:

For Tomcat 9.x, 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>

对于Tomcat 10.x,您应使用 jakarta.* 导入,并且整个 < dependencies> 部分应如下:

For Tomcat 10.x, 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>

请注意,< scope> 已为他们明确设置为提供,这意味着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的 javax:javaee-api jakarta.platform:jakartaTomcat 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.

但是,如果您在为Tomcat开发代码时非常清楚这一限制(例如,请确保您没有意外地使用JSTL,CDI,BV,JPA等,而无需首先在Tomcat中实际安装它们),并且只想最小化 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>

另请参见:

  • Tomcat版本
  • Java EE到底是什么?
  • 这篇关于Tomcat将servlet转换为javax.servlet.Servlet而不是jakarta.servlet.http.HttpServlet的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆