先看錯誤日誌:java
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有啥區別呢?web
war包:Web application ARchive,其實也是一種JAR文件,天然也是一種壓縮包,包含用來JSP、Java Servlet、Java類、XML文件、標籤庫、靜態網頁(HTML和相關文件),以及構成Web應用程序的其餘資源;spring
exploded包:其實就是war包的展開,也就是war、jar等產出物沒壓縮前的目錄結構。在開發的時候使用這種模式可以使修改文件的效果馬上顯現出來。apache
另外我這個項目的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個tabtomcat
這幾類目錄都比較好理解,須要注意的是Excluded Folders配置的是讓IDEA忽略的目錄,通常是編譯後的輸出目錄,這裏加入的lib目錄是咱們的本地jar包目錄,咱們只是用來配置jar包,部署時會在WEB-INF自動生成對應lib包,因此能夠忽略。app
跳過Libraries和Facets,咱們直接進入部署的關鍵點。打開IDEA的artifact -> 點擊左邊菜單欄的Artifacts -> 選中原有的artifact(默認是war包的artifact)並點減號刪除 -> 點加號新增一個artifact -> 下拉框選第二個(Exploded) -> 繼續二級下拉框選來自Module(From Modules) -> 選中以前配置的Module便可。webapp
這時你能夠看到默認設置了一個output目錄,tomcat啓動時讀取的就是該目錄下的相關文件和資源。Output Layout就是output裏面的佈局,咱們能夠看到其實就是WEB-INF目錄,它有編譯後的字節碼文件所在的classes目錄和引入的jar包所在的lib目錄。socket
最後一步就是配置tomcat server,在Deployment中加入咱們剛剛配置好的artifact。maven
當你點擊運行tomcat時,IDEA開始幹這些事情:
以上是正常狀況,廢話很少說,復現異常:把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。