maven与Tomcat包冲突问题

项目启动时遇到这样一个问题:

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)

解决办法:


javax.servlet
servlet-api
2.5
provided

servlet-api添加provided,也就是说,这个包的适用范围只有在部署以前。

为什么要这么做呢——为了避免jar包冲突。

请看下图:


maven与Tomcat包冲突问题_第1张图片


可以看到,这里有3个jar包集合:

1、Tomcat包:运行时用到。

2、系统包:编译、运行时用。

3、Maven包:编译、运行时用(默认情况下)。

Tomcat包详情:

maven与Tomcat包冲突问题_第2张图片

因为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中的标签:

compile
默认的scope,表示 dependency 都可以在生命周期中使用。而且,这些dependencies 会传递到依赖的项目中。适用于所有阶段,会随着项目一起发布
provided
跟compile相似,但是表明了dependency 由JDK或者容器提供,例如Servlet AP和一些Java EE APIs。这个scope 只能作用在编译和测试时,同时没有传递性。
runtime
表示dependency不作用在编译时,但会作用在运行和测试时,如JDBC驱动,适用运行和测试阶段。
test
表示dependency作用在测试时,不作用在运行时。 只在测试时使用,用于编译和运行测试代码。不会随项目发布。
system
跟provided 相似,但是在系统中要以外部JAR包的形式提供,maven不会在repository查找它。




你可能感兴趣的:(maven与Tomcat包冲突问题)