自从搞明白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就好了。