文章目录
前言
一直对Tomcat的源码挺感兴趣,里面挺多过程的实现都想瞅一瞅,所以把tomcat源码下载下来跑一下
下文详细介绍用maven方式Tomcat源码跑起来,并运行自己的Web项目
本文地址:https://blog.csdn.net/weixin_54430656/article/details/122440049
参考文章
步骤
1.下载tomcat源码
Tomcat官网
https://tomcat.apache.org/
Tomcat 10下载页链接
https://tomcat.apache.org/download-10.cgi
下载地址,这里下载的是Tomcat 10.0.14
https://dlcdn.apache.org/tomcat/tomcat-10/v10.0.14/src/apache-tomcat-10.0.14-src.zip
2.解压并配置maven
2.1 找个空目录解压,并在同层目录下新建pom.xml
文件
pom.xml
内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>gxf</groupId>
<artifactId>apache-tomcat-10</artifactId>
<name>apache-tomcat-10-source</name>
<version>1.0</version>
<packaging>pom</packaging>
<modules>
<module>apache-tomcat-10.0.14-src</module>
</modules>
</project>
2.2 在解压出来的文件夹下再新建一个pom.xml
文件,内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.apache.tomcat</groupId>
<artifactId>Tomcat10.0</artifactId>
<name>Tomcat10.0</name>
<version>10.0</version>
<build>
<finalName>Tomcat10.0</finalName>
<sourceDirectory>java</sourceDirectory>
<testSourceDirectory>test</testSourceDirectory>
<resources>
<resource>
<directory>java</directory>
</resource>
</resources>
<testResources>
<testResource>
<directory>test</directory>
</testResource>
</testResources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
<configuration>
<encoding>UTF-8</encoding>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>ant</groupId>
<artifactId>ant</artifactId>
<version>1.7.0</version>
</dependency>
<dependency>
<groupId>ant</groupId>
<artifactId>ant-apache-log4j</artifactId>
<version>1.6.5</version>
</dependency>
<dependency>
<groupId>ant</groupId>
<artifactId>ant-commons-logging</artifactId>
<version>1.6.5</version>
</dependency>
<dependency>
<groupId>wsdl4j</groupId>
<artifactId>wsdl4j</artifactId>
<version>1.6.2</version>
</dependency>
<dependency>
<groupId>javax.xml.rpc</groupId>
<artifactId>javax.xml.rpc-api</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>org.eclipse.jdt.core.compiler</groupId>
<artifactId>ecj</artifactId>
<version>4.6.1</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>jakartaee-migration</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>biz.aQute.bnd</groupId>
<artifactId>biz.aQute.bndlib</artifactId>
<version>5.2.0</version>
</dependency>
</dependencies>
</project>
2.3 目录结构层次如下
-- tomcat
-- apache-tomcat-10.0.14-src
-- pom.xml
-- pom.xml
3.用idea打开
用idea打开最外层的tomcat目录
4.配置tomcat工作目录
可以在原先的解压目录apache-tomcat-10.0.14-src
新建一个home
目录,这个目录是tomcat的工作目录,到时候其下会放置有work、webapps、logs、lib、conf等文件夹,然后复制这个目录,例如xxx\Tomcat\apache-tomcat-10.0.14-src\home
,后面需要用到这个目录
5.配置启动类及相关参数
5.1 随便填个名字
5.2 配置启动类,填下面内容
org.apache.catalina.startup.Bootstrap
5.3 配置虚拟机选项,填下面内容
-Dfile.encoding=UTF-8
-Dcatalina.home="这里添刚刚复制的目录"
5.4 在选项中选择子模块那个
6.取消test文件夹标记
这个文件夹下主要为tomcat的测试目录,里面有许多我们用不到的,许多依赖也是我们不需要的,不把他取消标记的话,等一下会报一堆依赖缺失
7.尝试启动
7.1 然后他会提示找不到,这些找不到的都是因为环境变量引用的,直接把报红的注释掉就好
8.再次启动
再次启动后会提示缺少配置文件,并且有乱码问题
8.1 找到我们原先电脑上安装过的tomcat,然后把那里的配置文件拷贝一份过去,考到将conf
文件夹拷到刚刚新建的home
目录下
9.拷贝完成后再次启动
这个时候成功启动起来了,但是有乱码问题
10.解决乱码问题
这里的乱码不是因为JVM的问题,而是那些目录下那些.properties
文件是以UTF-8形式保存的,而java读取的时候默认却以iso8859-1
的形式读取,才导致的中文乱码
有两种解决的思路
方式一:把文件转码转为iso8859-1
在给tomcat读取(可用JDK下的工具native2ascii.exe将properties文件转为Unicode编码)
方式二:Debug找到读取位置的代码,把读取后的字符单独转码
下面我用的是方式二
10.1
尝试DeBug找到打印出第一行乱码的代码位置
DeBug思路就是入口类org.apache.catalina.startup.Bootstrap的入口函数直接打断点,然后逐步单行过语句。
如果过掉的当前这一行没有打印出乱码,就说明和这行没关系;如果打印出了乱码,那就进入这一行的方法里面细看,看是方法内的哪个位置,重复第一步,逐渐深入,这样很快就找到了出乱码的准确位置StringManager类内
10.2
通过Debug我们一步一步确定乱码的最终来源在StringManager
类这里,可以看到正常的一个key,在ResourceBundle中获取之后就变成乱码了
StringManager
类位置如下:
org.apache.tomcat.util.res.StringManager
bundle.getString(key)调用之前
bundle.getString(key)调用之后
10.3
所以问题就出在这个ResourceBundle(ResourceBundle是资源包,从硬盘文件加载而来),然后我们把断点直接打在ResourceBundle的初始化的位置
10.4
然后可以看到,ResourceBundle下的lookup属性在加载出来的时候就已经乱码了
10.5
然后找到他加载时的输入流,根据输入流找到所加载的那个文件的位置,然后打开中文版发现文件没乱码,但是加载之后乱码了——加载方式不对,编码不对应,文件是UTF-8
的,而java加载文件默认使用iso8859-1
下面是位置
org\apache\catalina\startup\LocalStrings.properties
打开源文件可以看到是显示正常的,所以我们可以回到刚刚那个StringManager
类里面读取bundle的那个位置(步骤10.1),把读取到的字符转码,转位UTF-8
回到原来那个StringManager,它原先是这样子
添加下面这一句,用于转码
str= new String(str.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
10.6 类似的还有一处需要转码的
在类Localizer的getMessage(String errCode)方法中
位置如下
org.apache.jasper.compiler.Localizer
添加下面这句
errMsg= new String(errMsg.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
11.再次启动
一切正常
12.部署项目
将打包好的war
包放到刚刚新建的home
目录下的webapps
下,然后重启tomcat就行了,最后项目成功跑起来并可以访问
恭喜你,看到这你应该成功启动了Tomcat源码了,通过Debug去源码中找寻你想要的东西吧