解决Tomcat下IntelliJ IDEA报错java.lang.NoClassDefFoundError: javax/servlet/ServletContextListener

解决Tomcat下IntelliJ IDEA报错java.lang.NoClassDefFoundError: javax/servlet/ServletContextListener

  笔者在做代码重构的时候,以前记得运行正常的代码,如今一直报错,百思不得其解。然后发现居然运行一个简单的程序也发生了同样的报错信息。当时笔者的运行环境如下:

笔者报错时的运行环境:
JDK 13.0.2
Spring 5.2.9.RELEASE
Maven 3.6.3
Tomcat 10.0.0(Servlet 5.0,JSP 3.0)
Intelli] IDEA 2020.1.2 (Ultimate Edition)

  这个报错的信息如下:

xx-xxx-202X xx:xx:xx.xx 严重 [RMI TCP Connection(3)-127.0.0.1] org.apache.catalina.core.StandardContext.listenerStart 配置应用程序监听器[org.springframework.web.context.ContextLoaderListener]错误
	java.lang.NoClassDefFoundError: javax/servlet/ServletContextListener
		at java.base/java.lang.ClassLoader.defineClass1(Native Method)
		at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1016)
		at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:151)
		at org.apache.catalina.loader.WebappClassLoaderBase.findClassInternal(WebappClassLoaderBase.java:2431)
		at org.apache.catalina.loader.WebappClassLoaderBase.findClass(WebappClassLoaderBase.java:864)
		at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1333)
		at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1187)
		at org.apache.catalina.core.DefaultInstanceManager.loadClass(DefaultInstanceManager.java:540)
		at org.apache.catalina.core.DefaultInstanceManager.loadClassMaybePrivileged(DefaultInstanceManager.java:521)
		at org.apache.catalina.core.DefaultInstanceManager.newInstance(DefaultInstanceManager.java:151)
		at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4589)
		at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5126)
		at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
		at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:717)
		at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:690)
		at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:706)
		at org.apache.catalina.startup.HostConfig.manageApp(HostConfig.java:1727)
		at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
		at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
		at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
		at java.base/java.lang.reflect.Method.invoke(Method.java:567)
		at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:288)
		at java.management/com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:809)
		at java.management/com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
		at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:427)
		at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:376)
		at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
		at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
		at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
		at java.base/java.lang.reflect.Method.invoke(Method.java:567)
		at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:288)
		at java.management/com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:809)
		at java.management/com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
		at java.management/com.sun.jmx.remote.security.MBeanServerAccessController.invoke(MBeanServerAccessController.java:468)
		at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl.doOperation(RMIConnectionImpl.java:1466)
		at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl$PrivilegedOperation.run(RMIConnectionImpl.java:1307)
		at java.base/java.security.AccessController.doPrivileged(AccessController.java:691)
		at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(RMIConnectionImpl.java:1406)
		at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl.invoke(RMIConnectionImpl.java:827)
		at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
		at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
		at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
		at java.base/java.lang.reflect.Method.invoke(Method.java:567)
		at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:359)
		at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200)
		at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197)
		at java.base/java.security.AccessController.doPrivileged(AccessController.java:691)
		at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196)
		at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:562)
		at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:796)
		at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:677)
		at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
		at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:676)
		at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
		at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
		at java.base/java.lang.Thread.run(Thread.java:830)
	Caused by: java.lang.ClassNotFoundException: javax.servlet.ServletContextListener
		at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1364)
		at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1187)
		... 56 more

  然后笔者针对一个简单的程序不断排错之后才发现,原来是Servlet、JSP与Spring的版本之间的匹配出了问题。众所周知,2018年,Java EE改名为Jakarta EE。这导致一些JAR包的包名也在之后的版本中进行了更改。这对本项目的影响是,Spring本身是不含Servlet、JSP的JAR包的,但Tomcat服务器将使用Spring,且Tomcat服务器提供Servlet、JSP的JAR包。而这里,Spring 5.2.9.RELEASE期望的JAR包前缀是javax,而Tomcat 10.0.0提供的JAR包前缀是jakarta。因此,Spring报了一个认为没有Servlet、JSP的JAR包的错。

(查看Tomcat的各版本对应的Servlet等的版本的网址是:http://tomcat.apache.org/whichversion.html

  由于Tomcat与Servlet、JSP的JAR包关系密切,因此无法通过替换Tomcat下的文件夹lib中Servlet、JSP的JAR包来解决。而且这也无法通过在Maven中添加正确的Servlet、JSP依赖来解决,实际上,如果该工程的纯Java代码的部分没有使用到Servlet、JSP的JAR,其实这里在Maven添加的Servlet、JSP依赖都可以删掉。

  幸运的是,Tomcat 9.0.41使用的JAR包前缀是javax。因此,这里只需要再安装一个Tomcat 9.0.41即可解决(不需要卸载已有的Tomcat,因为不同版本的Tomcat的安装路径不同,只是安装时需要先关闭已有的Tomcat服务器)。

笔者成功运行时的运行环境:
JDK 13.0.2
Spring 5.2.9.RELEASE
Maven 3.6.3
Tomcat 9.0.41(Servlet 4.0,JSP 2.3)
Intelli] IDEA 2020.1.2 (Ultimate Edition)

猜你喜欢

转载自blog.csdn.net/wangpaiblog/article/details/112424058
今日推荐