首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

什么?编译了三个版本Tomcat源码后,我才发现这个bug

背景

一产品是基于多模块开发的 SpringBoot 项目,发布时导出多个 war 包部署在同一个 Tomcat 。模块有五六个,发布时最大的问题就是每个包都很大,主要是各个模块的 WEB-INF/lib 下包含大量相同 jar ,因此有必要将公共包摘出来放到 Tomcat 的共享目录下。

然而,在捣鼓了两天后,我对 Tomcat 的多应用部署时共享公共包的能力产生了怀疑。理论上,同一个 Tomcat 下部署多个应用时,可以将所有共享 jar 放在 shared/lib 目录下,然后配置 shared.loader 就可以了。

实践的时候,抽取了公共包后,多个 war 部署时始终报错, WEB-INF/lib 下明明有对应的 Spring 框架包,还是报 Caused by:

java.lang.NoClassDefFoundError: org/springframework/beans/factory/FactoryBean 异常,反复测试,还是无法确定哪些包应该作为公共包。

所以,决定从源头来搞明白这个类加载过程,在编译的 Tomcat 版本下断点跟踪一下到底是怎么回事儿。第一件事儿,先编译 Tomcat 源码。

Tomcat 源码编译

Tomcat 源码导入 IDEA 的过程比较简单,步骤为:

1.下载 ANT 工具,最新版本为 1.10.9,配置环境变量 ANT_HOME:

2.下载 tomcat 源码,根据操作系统选择 zip 或者 tar.gz 文件;

3.进入源码目录,使用 ant 命令编译源码;

此操作耗时较长,耐心等待编译完成:

4. 创建一个 catalina-home 目录,将 output/build 目录下的所有文件拷贝到 catalina-home 目录下,将其作为 Tomcat 的工作目录:

5.进入源码目录,创建 pom.xml 添加依赖:

6.导入 IDEA 源码,配置启动参数 -Dcatalina.home="F:\Study\TomcateStudy\2021Tomcat\catalina-home" 。

总的来说,编译源码流程比较简单,但最开始因为随便选择了最新版本,导致无法启动,这可能是官网版本发布时的缺陷吧,反正换个版本就没有问题。

选错版本的问题

首先,在 MAC 操作系统下,随便选择了最新版本 tomcat8.5.63 的 tar.gz 版本,下载后,编译时报错。先报 @Version@ 校验错误:

修改为一个特定值后,又报下面的错误:

最初怀疑是 IDEA 配置问题,于是又在 windows 操作系统下,还是用最新版本的 tomcat8.5.63 的 zip 版本下载源码,配置参数如下:

奇怪的是,它能够编译通过、正常运行:

结论:Tomcat8.5.63 版本的 tar.gz 源码的 jdbc-pool 模块打包生成的 MANIFEST.MF 文件有问题,编译源码的时候应该避免使用该版本。本来以为哪个版本都一样,就随便选了最新版本,结果就踩坑了。

最后,更换为 Tomcat8.5.59 版本,MAC 下就能正确启动了。

控制台乱码问题

最后解决控制台乱码问题,主要涉及到两个类,它们使用了默认编码导致输出乱码的。具体操作如下,详细参考:

再重启 Tomcat 应用,输出信息就正常了:

启示录

到现在为止,还没找到答案的几个问题是:

多应用共享 lib 的原则是什么?

哪些包应该放在 shared/lib 下?【我是将纯第三方 jar ,无相关依赖的】

为什么只 WEB-INF/lib 下只保留某个应用自身的 jar 而且包含 SpringBoot 的 starter 依赖,还是报类异常?

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20210319A01B9800?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券