摘要
Spring boot 项目部署linux tomcat 报:java.io.IOException: java.lang.ClassCastException: Cannot cast ch.qos.logback.classic.servlet.LogbackServletContainerInitializer to javax.servlet.ServletContainerInitializer解决办法
Spring boot 项目部署linux tomcat 报:java.io.IOException: java.lang.ClassCastException: Cannot cast ch.qos.logback.classic.servlet.LogbackServletContainerInitializer to javax.servlet.ServletContainerInitializer解决办法
一个Spring boot项目,使用log4j打印日志,在windows tomcat中部署正常启动,但是在linux系统中部署到tomcat 中时报了如下的错误:
java.io.IOException: java.lang.ClassCastException: Cannot cast ch.qos.logback.classic.servlet.LogbackServletContainerInitializer to javax.servlet.ServletContainerInitializer at org.apache.catalina.startup.WebappServiceLoader.loadServices(WebappServiceLoader.java:185) at org.apache.catalina.startup.WebappServiceLoader.load(WebappServiceLoader.java:151) at org.apache.catalina.startup.ContextConfig.processServletContainerInitializers(ContextConfig.java:1597) at org.apache.catalina.startup.ContextConfig.webConfig(ContextConfig.java:1125) at org.apache.catalina.startup.ContextConfig.configureStart(ContextConfig.java:768) at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:303) at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117) at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90) at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5058) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:726) at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:702) at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:697) at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:1134) at org.apache.catalina.startup.HostConfig$DeployDirectory.run(HostConfig.java:1780) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748) Caused by: java.lang.ClassCastException: Cannot cast ch.qos.logback.classic.servlet.LogbackServletContainerInitializer to javax.servlet.ServletContainerInitializer at java.lang.Class.cast(Class.java:3369) at org.apache.catalina.startup.WebappServiceLoader.loadServices(WebappServiceLoader.java:182) ... 19 more
看报错提示很明显,一开始以为是jar引入冲突造成的,可以分析了Pom.xml文件和application.properties文件发现,并没有明显的引入jar和配置错误啊,甚至我都没引入log4j的依赖(Spring boot框架默认继承的父类pom.xml中已经引入了相关的依赖,如下图)
那么这就奇怪了,明明父类中已经引入了logging依赖,为啥还会强行转换为 javax.servlet.ServletContainerInitializer呢?
首先想到的是度娘,搜索了很久,很失望的发现,根本没有能帮助我解决问题的文章啊,于是去google上搜索该问题,找到了一篇文章,说linux下tomcat 运行 maven项目时加载的jar有一个优先级,可能会把apach-tomcat下lib下的jar先加载上,于是我去搜索如何修改tomcat加载jar优先级的方法,感觉绝望的是,只是找到了一些关于tomcat加载jar优先级的文章:tomcat中加载class和jar优先级,但是却没有如何修改这个优先级的文章;感觉自己找错了方向,于是再次回去翻阅google上查到的文章,再次会想起上文报的错误,忽然想到,能不能在pom.xml中直接屏蔽下面的这个类呢?
javax.servlet.ServletContainerInitializer
于是我尝试在pom.xml的下面位置加上了一段代码:
以屏蔽打包时打入servlet.api.jar
<dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> <!-- 编译测试期间有效 --> <scope>provided</scope> </dependency>
clearn 后再次install打包,部署,OK,终于成功。