解决Docker中Tomcat部署war失败
问题描述
博主在接手实验室祖传项目的开发的时候,本地测试都没啥问题,于是直接部署上云服务器,但是死活404
部署失败。首先由于是祖传项目,用的还是JDK8,而且打包的方式也是war包的形式,打包成功再部署到Tomcat
里面。但是部署进去后,访问项目路径,却一直是404错误。
问题分析
博主一开始以为是Tomcat
的问题,因为项目在本地跑的好好的,而且部署的时候用的是docker
,我就怀疑是不是我docker
起的Tomcat
容器有没有问题,于是最简单的方式在webapps
目录下建立一个ROOT
文件夹,里面写个Hello World,然后再访问根路径看有没有。
事实证明Tomcat
是没有问题的:
那么就是war包启动的时候有问题了,最好的方法就是看日志了。
进入Tomcat
的logs
目录,直接查看日志:
日志一堆,但是最主要的是看catalina
加日期的那个启动日志文件,那么查看今天的日志:
从上往下分析,发现是启动的时候Spring里面的一个容器无法完成注入,再往下分析,发现在日志的最后一个错误是:
1 | Caused by: java.lang.IllegalStateException: Failed to introspect Class [com.gsy.ms.wechat.wechatmp.service.impl.WechatMPServiceImpl] from ClassLoader [ParallelWebappClassLoader^M |
最重要的就是这句:
1 | Caused by: java.lang.ClassNotFoundException: javax.xml.bind.JAXBException |
不就是找不到类吗?但是这就比较奇怪了,本地启动为啥就没有报错了呢?
直接搜索这句报错,发现是Java版本的问题造成的:
这个错误是因为在Java 11及以上版本中,
javax.xml.bind
包已经不再包含在系统库中12。这个包在Java 6/7/8中是作为JDK的一部分提供的,但在Java 9中,它被认为是Java EE API,因此不再包含在默认的类路径中2。在Java 11中,它们完全从JDK中移除了2。解决这个问题的方法有两种:
就是在Java8的时候这个包还在rt.jar
下面,可以直接用,到了Java9之后,由于Java9的模块化,很多这种包都被闭包处理了,直接就用不了了。
那么更近一步分析就知道,就是Tomcat容器它用的JDK版本肯定不是Java8了。看一下我这个容器是用的什么镜像,查看启动容器的docker-compose.yaml
:
1 | version: '3.3' |
只知道用的是Tomcat8的容器,至于JDK版本就看不到了,那就进入这个容器看看呗:
1 | docker exec -it tomcat bash #进入容器 |
查看Java版本:
好家伙,用的Java版本这么新吗?直接17了。以前光听说企业现在都在往Java17和Java21转移,没想到这种容器真就用最新的了,牛的,支持一波。
那么问题可以说都分析完了,解决起来也就很简单了。
问题解决
就如上所说,问题的根源就是Tomcat容器里面的JDK版本太高了,解决那也就很简单了,直接给JDK降低版本不就行了。但是我这个是用的docker镜像啊?怎么修改?直接到dockerhub里面找一下有没有JDK是8的版本不就行了,直接搜索JDK8,果然有一堆:
找了一下,就拉个写起来简单的吧:
1 | docker pull tomcat:9-jdk8 |
重新启动个Tomcat容器,部署,成功解决问题。