自從搞明白idea下,Jetty採用main方法啓動web項目後,準備大刀闊斧地把其餘web項目也改爲jetty啓動,不幸的是,第一個項目就遇到了問題,這裏記錄下整個排查流程及處理辦法。java
項目按idea下,Jetty採用main方法啓動web項目一文中所述的進行配置後,運行,發現出現了以下異常:web
java.lang.NoSuchMethodError: javax.servlet.ServletContext.getJspConfigDescriptor()Ljavax/servlet/descriptor/JspConfigDescriptor; at org.apache.jasper.servlet.TldScanner.scanJspConfig(TldScanner.java:158) at org.apache.jasper.servlet.TldScanner.scan(TldScanner.java:104) at org.apache.jasper.servlet.JasperInitializer.onStartup(JasperInitializer.java:103) ......
在idea中一查javax.servlet.ServletContext
,發現共有4個jar包中有這個類,分別是:apache
爲何會有這麼多servlet-api
的版本呢?主要是由於在當前的項目中,還有其餘web模塊,因爲版本控制沒作好,每一個web模塊使用了不一樣的servlet-api
,此外,還有一些jar包在引入時,一不當心就連帶引入了servlet-api
的jar包。api
因此當務之急,就是找到該web模塊中的javax.servlet.ServletContext
究竟來自於哪一個jar包。tomcat
爲了找到項目中類的加載狀況,須要在jvm的啓動參數中,添加-verbose:class
:app
再次啓動,能夠看到控制檯已經打出了類加載信息了,包括類名、jar包位置:eclipse
[Opened C:\Program Files\Java\jdk1.8.0_181\jre\lib\rt.jar] [Loaded java.lang.Object from C:\Program Files\Java\jdk1.8.0_181\jre\lib\rt.jar] [Loaded java.io.Serializable from C:\Program Files\Java\jdk1.8.0_181\jre\lib\rt.jar] [Loaded java.lang.Comparable from C:\Program Files\Java\jdk1.8.0_181\jre\lib\rt.jar] [Loaded java.lang.CharSequence from C:\Program Files\Java\jdk1.8.0_181\jre\lib\rt.jar] [Loaded java.lang.String from C:\Program Files\Java\jdk1.8.0_181\jre\lib\rt.jar] [Loaded java.lang.reflect.AnnotatedElement from C:\Program Files\Java\jdk1.8.0_181\jre\lib\rt.jar] [Loaded java.lang.reflect.GenericDeclaration from C:\Program Files\Java\jdk1.8.0_181\jre\lib\rt.jar] [Loaded java.lang.reflect.Type from C:\Program Files\Java\jdk1.8.0_181\jre\lib\rt.jar] [Loaded java.lang.Class from C:\Program Files\Java\jdk1.8.0_181\jre\lib\rt.jar] [Loaded java.lang.Cloneable from C:\Program Files\Java\jdk1.8.0_181\jre\lib\rt.jar] [Loaded java.lang.ClassLoader from C:\Program Files\Java\jdk1.8.0_181\jre\lib\rt.jar] [Loaded java.lang.System from C:\Program Files\Java\jdk1.8.0_181\jre\lib\rt.jar] [Loaded java.lang.Throwable from C:\Program Files\Java\jdk1.8.0_181\jre\lib\rt.jar] ......
異常中出現問題的類是javax.servlet.ServletContext
,在日誌搜索,發現以下記錄:webapp
[Loaded javax.servlet.ServletContext from file:/C:/Users/Administrator/.m2/repository/javax/servlet/servlet-api/2.4/servlet-api-2.4.jar]
能夠看到,項目中,javax.servlet.ServletContext
類是由servlet-api-2.4.jar
包引入的。jvm
關於「如何在控制檯中搜索」,能夠將控制檯日誌複製一份到文本編輯器中,如
notepad++
、vscode
等,而後使用搜索功能。jsp
maven
定位jar包來源目前已經知道,項目中的javax.servlet.ServletContext
類是由servlet-api-2.4.jar
包引入的,但servlet-api-2.4.jar
是從哪裏引入的呢?項目jar包是由maven來管理的,所以使用mvn命令來查找jar包引入狀況,命令以下:
mvn dependency:tree -Dverbose -Dincludes=*:*servlet*
運行以後,控制檯輸出以下:
[INFO] com.test:test-web:war:0.0.1-SNAPSHOT [INFO] +- javax.servlet:servlet-api:jar:2.4:provided [INFO] +- org.eclipse.jetty:jetty-webapp:jar:9.3.2.v20150730:test [INFO] | \- org.eclipse.jetty:jetty-servlet:jar:9.3.2.v20150730:test [INFO] \- org.eclipse.jetty:apache-jsp:jar:9.3.2.v20150730:test [INFO] +- org.eclipse.jetty:jetty-server:jar:9.3.2.v20150730:test [INFO] | \- (javax.servlet:javax.servlet-api:jar:3.1.0:test - omitted for duplicate) [INFO] \- javax.servlet:javax.servlet-api:jar:3.1.0:test [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS
能夠看到,項目中引入的servlet-api
版本是2.4,而jetty使用的servlet-api
版本是3.1.0,這樣就致使了jetty中使用了低版本的servlet-api
,從而出現異常。
明白了問題所在,解決就很簡單了,只要將項目servlet-api
的版本由2.4升級到3.1.0就好了。