项目启动时遇到这样一个问题:
java.lang.LinkageError: loader constraint violation: loader (instance of org/apache/jasper/servlet/JasperLoader) previously initiated loading for a different type with name "javax/servlet/http/HttpServletRequest"
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2625)
at java.lang.Class.getDeclaredMethods(Class.java:1868)
at org.apache.catalina.util.DefaultAnnotationProcessor.processAnnotations(DefaultAnnotationProcessor.java:226)
at org.apache.jasper.servlet.JspServletWrapper.getServlet(JspServletWrapper.java:148)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:329)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:313)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:260)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:857)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
at java.lang.Thread.run(Thread.java:745)
解决办法:
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
servlet-api添加<scope>provided</scope>,也就是说,这个包的适用范围只有在部署以前。
为什么要这么做呢——为了避免jar包冲突。
请看下图:
可以看到,这里有3个jar包集合:
1、Tomcat包:运行时用到。
2、系统包:编译、运行时用。
3、Maven包:编译、运行时用(默认情况下)。
Tomcat包详情:
因为Tomcat中已经有servlet-api,但是只有在运行时才能用使用Tomcat中的包,在编译时是用不到的,为了在编译时不显示错误,就需要添加servlet-api包。
这样,编译时使用自己添加的包。
在运行时使用Tomcat自带的包。
这样就不至出错和冲突了。
还有一些其它的包,也可能会出现包冲突,所以要知道Tomcat下到底都有些啥包,以免再犯这种错误。
可能出错的,比如jsp-api.jar、jstl.jar、standard.jar等等吧。
但是情况远不止这么简单!
虽然Tomcat自带jstl.jar,但是maven中jstl.jar不能添加provided,不然启动会报错。
原因分析:tomcat7 不会自动添加jstl需要的类库到项目中,需要手动导入
顺便说一下maven中的<scope>标签:
compile
默认的scope,表示 dependency 都可以在生命周期中使用。而且,这些dependencies 会传递到依赖的项目中。适用于所有阶段,会随着项目一起发布
provided
跟compile相似,但是表明了dependency 由JDK或者容器提供,例如Servlet AP和一些Java EE APIs。这个scope 只能作用在编译和测试时,同时没有传递性。
runtime
表示dependency不作用在编译时,但会作用在运行和测试时,如JDBC驱动,适用运行和测试阶段。
test
表示dependency作用在测试时,不作用在运行时。 只在测试时使用,用于编译和运行测试代码。不会随项目发布。
system
跟provided 相似,但是在系统中要以外部JAR包的形式提供,maven不会在repository查找它。