解决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)
-
IntelliJ 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/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??然后筆者針對一個簡單的程序不斷排錯之后才發現,原來是 Servlet、JSP 與 Spring 的版本之間的匹配出了問題。眾所周知,2018 年,Java EE 改名為 Jakarta EE。這導致一些 JAR 包的包名也在之后的版本中進行了更改。這對本項目的影響是,Spring 本身是不含 Servlet、JSP 的 JAR 包的,但其依賴這些 JAR 包。如果在 Tomcat 服務器中部署的項目使用了 Spring,則這部分的 JAR 包將由 Tomcat 服務器來提供。而問題在于,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 依賴都可以刪掉。(更專業的說法是,在基于 Maven 的 Web 應用中,對 Servlet、JSP 的依賴范圍為 provided。)
??幸運的是,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)
-
IntelliJ IDEA 2020.1.2 (Ultimate Edition)
總結
以上是生活随笔為你收集整理的解决Tomcat下IntelliJ IDEA报错java.lang.NoClassDefFoundError: javax/servlet/ServletContextListener的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: VMware Workstation P
- 下一篇: 解决 Tomcat 下 getInitP