IDEA啟動tomcat報錯:java.lang.NoClassDefFoundError: org/springframework/context/ApplicationContext、ContainerBase.addChild: start: org.apache.catalina.LifecycleException: Failed to start component


  先看錯誤日志:

27-May-2019 17:07:29.838 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log Server version:        Apache Tomcat/9.0.0.M26
27-May-2019 17:07:29.844 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log Server built:          Aug 2 2017 20:29:05 UTC
27-May-2019 17:07:29.845 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log Server number:         9.0.0.0
27-May-2019 17:07:29.845 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log OS Name:               Windows 10
27-May-2019 17:07:29.845 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log OS Version:            10.0
27-May-2019 17:07:29.845 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log Architecture:          amd64
27-May-2019 17:07:29.845 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log Java Home:             D:\Dev\Java\jdk1.8.0_102\jre
27-May-2019 17:07:29.845 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log JVM Version:           1.8.0_102-b14
27-May-2019 17:07:29.845 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log JVM Vendor:            Oracle Corporation
27-May-2019 17:07:29.845 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_BASE:         C:\Users\wulf\.IntelliJIdea2018.3\system\tomcat\Unnamed_manage_system_home_2
27-May-2019 17:07:29.845 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_HOME:         D:\Dev\apache-tomcat-9.0.0.M26
27-May-2019 17:07:29.846 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.util.logging.config.file=C:\Users\wulf\.IntelliJIdea2018.3\system\tomcat\Unnamed_manage_system_home_2\conf\logging.properties
27-May-2019 17:07:29.847 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
27-May-2019 17:07:29.848 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:51337,suspend=y,server=n
Caused by: java.lang.NoClassDefFoundError: org/springframework/context/ApplicationContext
    at java.lang.Class.getDeclaredFields0(Native Method)
    at java.lang.Class.privateGetDeclaredFields(Class.java:2583)
    at java.lang.Class.getDeclaredFields(Class.java:1916)
    at org.apache.catalina.util.Introspection.getDeclaredFields(Introspection.java:110)
    at org.apache.catalina.startup.WebAnnotationSet.loadFieldsAnnotation(WebAnnotationSet.java:262)
    at org.apache.catalina.startup.WebAnnotationSet.loadApplicationListenerAnnotations(WebAnnotationSet.java:88)
    at org.apache.catalina.startup.WebAnnotationSet.loadApplicationAnnotations(WebAnnotationSet.java:64)
    at org.apache.catalina.startup.ContextConfig.applicationAnnotationsConfig(ContextConfig.java:328)
    at org.apache.catalina.startup.ContextConfig.configureStart(ContextConfig.java:778)
    at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:299)
    at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:123)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5003)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    ... 44 more
Caused by: java.lang.ClassNotFoundException: org.springframework.context.ApplicationContext
    at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1269)
    at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1104)
    ... 57 more

27-May-2019 17:07:36.530 嚴重 [RMI TCP Connection(3)-127.0.0.1] org.apache.tomcat.util.modeler.BaseModelMBean.invoke Exception invoking method manageApp
 java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/wlf-voicebox]]
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:744)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:716)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:703)
    at org.apache.catalina.startup.HostConfig.manageApp(HostConfig.java:1729)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:287)
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
    at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
    at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:456)
    at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:405)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:287)
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
    at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
    at com.sun.jmx.remote.security.MBeanServerAccessController.invoke(MBeanServerAccessController.java:468)
    at javax.management.remote.rmi.RMIConnectionImpl.doOperation(RMIConnectionImpl.java:1468)
    at javax.management.remote.rmi.RMIConnectionImpl.access$300(RMIConnectionImpl.java:76)
    at javax.management.remote.rmi.RMIConnectionImpl$PrivilegedOperation.run(RMIConnectionImpl.java:1309)
    at java.security.AccessController.doPrivileged(Native Method)
    at javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(RMIConnectionImpl.java:1408)
    at javax.management.remote.rmi.RMIConnectionImpl.invoke(RMIConnectionImpl.java:829)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:324)
    at sun.rmi.transport.Transport$1.run(Transport.java:200)
    at sun.rmi.transport.Transport$1.run(Transport.java:197)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.Transport.serviceCall(Transport.java:196)
    at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:568)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:826)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:683)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:682)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

27-May-2019 17:07:36.532 嚴重 [RMI TCP Connection(3)-127.0.0.1] org.apache.tomcat.util.modeler.BaseModelMBean.invoke Exception invoking method createStandardContext
 javax.management.RuntimeOperationsException: Exception invoking method manageApp
    at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:295)
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
    at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
    at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:456)
    at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:405)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:287)
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
    at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
    at com.sun.jmx.remote.security.MBeanServerAccessController.invoke(MBeanServerAccessController.java:468)
    at javax.management.remote.rmi.RMIConnectionImpl.doOperation(RMIConnectionImpl.java:1468)
    at javax.management.remote.rmi.RMIConnectionImpl.access$300(RMIConnectionImpl.java:76)
    at javax.management.remote.rmi.RMIConnectionImpl$PrivilegedOperation.run(RMIConnectionImpl.java:1309)
    at java.security.AccessController.doPrivileged(Native Method)
    at javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(RMIConnectionImpl.java:1408)
    at javax.management.remote.rmi.RMIConnectionImpl.invoke(RMIConnectionImpl.java:829)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:324)
    at sun.rmi.transport.Transport$1.run(Transport.java:200)
    at sun.rmi.transport.Transport$1.run(Transport.java:197)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.Transport.serviceCall(Transport.java:196)
    at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:568)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:826)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:683)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:682)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/wlf-voicebox]]
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:744)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:716)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:703)
    at org.apache.catalina.startup.HostConfig.manageApp(HostConfig.java:1729)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:287)
    ... 35 more

27-May-2019 17:07:41.469 信息 [ContainerBackgroundProcessor[StandardEngine[Catalina]]] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory [D:\Dev\apache-tomcat-9.0.0.M26\webapps\manager]

  日志里告訴我們tomcat啟動時加載類失敗了,導致web容器無法啟動。定位問題首先得場景復現,這里我從頭開始進行。一開始我的tomcat是可以啟動的,但一修改了pom文件后就出現了上述異常,所以我從正常的設置開始。Eclipse與IDEA的一個不同點是tomcat的部署:Eclipse默認支持代碼改動后重啟tomcat;IDEA需要先自己打出個war包,再自己去重啟tomcat。為了避免每次都打包耗費大量時間(雖然每次打包時間不多,但你若頻繁變動代碼,積少成多,聚沙成塔,每天將耗費不少時間在打包上)。我們需要設置IDEA打war exploded包,它跟war有啥區別呢?

  war包:Web application ARchive,其實也是一種JAR文件,自然也是一種壓縮包,包含用來JSP、Java Servlet、Java類、XML文件、標簽庫、靜態網頁(HTML和相關文件),以及構成Web應用程序的其他資源;

  exploded包:其實就是war包的展開,也就是war、jar等產出物沒壓縮前的目錄結構。在開發的時候使用這種模式可使修改文件的效果立刻顯現出來。

  另外我這個項目的jar包都是本地引用,而非引用了maven倉庫的jar包,我的pom文件需要制定范圍和引用地址:

        <dependency>
            <groupId>javazoom</groupId>
            <artifactId>jlayer</artifactId>
            <version>1.0.1</version>
            <scope>system</scope>
            <systemPath>${project.basedir}/src/main/webapp/lib/jlayer-1.0.1.jar</systemPath>
        </dependency>

  上面可以看到我將jar包放在src/main/webapp/lib這個目錄下,而這個目錄並非maven的約定目錄(這點是關鍵)。接着我們需要進行部署的配置,通過快捷鍵Ctrl+Alt+Shift+S彈出項目結構(Project Structure)窗口,左邊菜單中的Project主要用來指定JDK,接着我們看下Modules,里面有3個tab

  • Sources:顯示項目的目錄資源,都是項目部署的時候需要的目錄,不同顏色代表不同的類型,選中左邊的目錄再點擊上面Mark as對應的類型即可設置。詳見下圖;
  • Paths:可以指定項目的編譯輸出目錄,即項目類和測試類的編譯輸出地址,使用默認路徑即可
  • Dependencies:項目的依賴,使用默認依賴即可

  這幾類目錄都比較好理解,需要注意的是Excluded Folders配置的是讓IDEA忽略的目錄,一般是編譯后的輸出目錄,這里加入的lib目錄是我們的本地jar包目錄,我們只是用來配置jar包,部署時會在WEB-INF自動生成對應lib包,所以可以忽略。

  跳過Libraries和Facets,我們直接進入部署的關鍵點。打開IDEA的artifact -> 點擊左邊菜單欄的Artifacts -> 選中原有的artifact(默認是war包的artifact)並點減號刪除 -> 點加號新增一個artifact -> 下拉框選第二個(Exploded) -> 繼續二級下拉框選來自Module(From Modules) -> 選中之前配置的Module即可。

  這時你可以看到默認設置了一個output目錄,tomcat啟動時讀取的就是該目錄下的相關文件和資源。Output Layout就是output里面的布局,我們可以看到其實就是WEB-INF目錄,它有編譯后的字節碼文件所在的classes目錄和引入的jar包所在的lib目錄。

  最后一步就是配置tomcat server,在Deployment中加入我們剛剛配置好的artifact。

  當你點擊運行tomcat時,IDEA開始干這些事情:

  • 編譯,IDEA在保存/自動保存后不會做編譯,不像Eclipse的保存即編譯,因此在運行server前會做一次編譯(其實就是maven構建,這就是為啥我們可以不用自己用maven跑一遍的原因)。編譯后class文件存放在指定的項目編譯輸出目錄(target)下;
  • 根據artifact中的設定對目錄結構(如上面的WEB-INF的classes和lib)進行創建;
  • 拷貝web資源的根目錄下的所有文件到artifact的目錄(不僅僅是WEB-INF的classes和lib)下;
  • 拷貝編譯輸出目錄下的classes目錄到artifact下的WEB-INF(WEB-INF/classes)下;
  • 拷貝lib目錄下所需的jar包到artifact下的WEB_INF/lib下;
  • 運行server,運行成功后,自動打開瀏覽器訪問指定url

  以上是正常情況,廢話不多說,復現異常:把pom文件的一把jar包由本地引用改為maven引入本地倉庫,如下:

        <dependency>
            <groupId>javazoom</groupId>
            <artifactId>jlayer</artifactId>
            <version>1.0.1</version>
        </dependency>

  接着按IDEA的提示Import Changes(導入pom文件變動),直接重啟tomcat,再看下我們的artifact的WEB-INF/lib目錄已經為空了:

  同樣的,Project Structure的Artifacts下的lib目錄不翼而飛了:

  這里因為jar包引用了maven的本地倉庫,導致我們的war結構(其實就是WEB-INF/lib目錄)發生了變動,lib目錄的jar包被清空了。為啥呢?因為我們通過maven引入jar包,那么就得按maven的規則來玩了。它將自動創建一個war包的artifact,它將從webapp/WEB-INF/lib目錄取jar包,而我們沒有該目錄,那么它會創建一個,但里面只有一個我們配置的jar包(jlayer-1.0.1.jar),然后tomcat啟動加載類時bug出現了。既然Spring的jar包都沒了,自然tomcat啟動時會找不到ApplicationContext這個類了。

  解決辦法有兩個,一個是將maven引入的那個jar包改用本地引入;另一個是遵守maven的約定,修改lib目錄,從webapp/lib挪到webapp/WEB-INF/lib並對應修改pom文件里引入本地jar包的路徑。第一個辦法還是上面的老路子,修改pom文件,重新設置Artifacts(先刪掉現有的所有artifact,因為maven創建了一個默認的war包artifact,再加上原來的war exploded,所以會有兩個,然后新增一個新的war exploded),刪掉前面maven自動生成的target/工程名/WEB-INF下的lib目錄,重啟tomcat(參見前面啟動tomcat時IDEA干的事,如果不重啟tomcat,artifact的輸出目錄下lib將會一直是空的,它需要tomcat啟動時去復制target目錄下的lib包到artifact的輸出目錄下);第二個辦法更合理一些,改完后同樣需要重新設置Artifacts,刪掉target/工程名下的lib目錄,重啟tomcat。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM