解决Tomcat下IntelliJ IDEA报错java.lang.NoClassDefFoundError: javax/servlet/ServletContextListener
解決Tomcat下IntelliJ IDEA報(bào)錯(cuò)java.lang.NoClassDefFoundError: javax/servlet/ServletContextListener
??筆者在做代碼重構(gòu)的時(shí)候,以前記得運(yùn)行正常的代碼,如今一直報(bào)錯(cuò),百思不得其解。然后發(fā)現(xiàn)居然運(yùn)行一個(gè)簡(jiǎn)單的程序也發(fā)生了同樣的報(bào)錯(cuò)信息。當(dāng)時(shí)筆者的運(yùn)行環(huán)境如下:
筆者報(bào)錯(cuò)時(shí)的運(yùn)行環(huán)境:
-
JDK 13.0.2
-
Spring 5.2.9.RELEASE
-
Maven 3.6.3
-
Tomcat 10.0.0(Servlet 5.0,JSP 3.0)
-
IntelliJ IDEA 2020.1.2 (Ultimate Edition)
??這個(gè)報(bào)錯(cuò)的信息如下:
xx-xxx-202X xx:xx:xx.xx 嚴(yán)重 [RMI TCP Connection(3)-127.0.0.1] org.apache.catalina.core.StandardContext.listenerStart 配置應(yīng)用程序監(jiān)聽器[org.springframework.web.context.ContextLoaderListener]錯(cuò)誤java.lang.NoClassDefFoundError: javax/servlet/ServletContextListenerat 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.ServletContextListenerat org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1364)at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1187)... 56 more??然后筆者針對(duì)一個(gè)簡(jiǎn)單的程序不斷排錯(cuò)之后才發(fā)現(xiàn),原來(lái)是 Servlet、JSP 與 Spring 的版本之間的匹配出了問題。眾所周知,2018 年,Java EE 改名為 Jakarta EE。這導(dǎo)致一些 JAR 包的包名也在之后的版本中進(jìn)行了更改。這對(duì)本項(xiàng)目的影響是,Spring 本身是不含 Servlet、JSP 的 JAR 包的,但其依賴這些 JAR 包。如果在 Tomcat 服務(wù)器中部署的項(xiàng)目使用了 Spring,則這部分的 JAR 包將由 Tomcat 服務(wù)器來(lái)提供。而問題在于,Spring 5.2.9.RELEASE 期望的 JAR 包前綴是 javax,而Tomcat 10.0.0 提供的 JAR 包前綴是 jakarta。因此,Spring 報(bào)了一個(gè)認(rèn)為沒有 Servlet、JSP 的 JAR 包的錯(cuò)。
(查看 Tomcat 的各版本對(duì)應(yīng)的 Servlet 等的版本的網(wǎng)址是:http://tomcat.apache.org/whichversion.html)
??由于 Tomcat 與 Servlet、JSP 的 JAR 包關(guān)系密切,因此無(wú)法通過替換 Tomcat 下的文件夾 lib 中 Servlet、JSP 的 JAR 包來(lái)解決。而且這也無(wú)法通過在 Maven 中添加正確的 Servlet、JSP 依賴來(lái)解決,實(shí)際上,如果該工程的純 Java 代碼的部分沒有使用到 Servlet、JSP 的 JAR 包,其實(shí)這里在 Maven 添加的 Servlet、JSP 依賴都可以刪掉。(更專業(yè)的說法是,在基于 Maven 的 Web 應(yīng)用中,對(duì) Servlet、JSP 的依賴范圍為 provided。)
??幸運(yùn)的是,Tomcat 9.0.41 使用的 JAR 包前綴是 javax 。因此,這里只需要再安裝一個(gè)Tomcat 9.0.41 即可解決(不需要卸載已有的 Tomcat,因?yàn)椴煌姹镜?Tomcat 的安裝路徑可以不同,只是安裝時(shí)需要先關(guān)閉已有的 Tomcat 服務(wù)器,避免占用同一個(gè)端口號(hào))。
筆者成功運(yùn)行時(shí)的運(yùn)行環(huán)境:
-
JDK 13.0.2
-
Spring 5.2.9.RELEASE
-
Maven 3.6.3
-
Tomcat 9.0.41(Servlet 4.0,JSP 2.3)
-
IntelliJ IDEA 2020.1.2 (Ultimate Edition)
總結(jié)
以上是生活随笔為你收集整理的解决Tomcat下IntelliJ IDEA报错java.lang.NoClassDefFoundError: javax/servlet/ServletContextListener的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: VMware Workstation P
- 下一篇: 解决 Tomcat 下 getInitP