可以到Tomcat官网下载源码压缩包,也可以去GitHub仓库Clone。
目前最新的是2021-12-08发布的10.0.14版。
前往网址Tomcat官网:Apache Tomcat® - Apache Tomcat 10 Software Downloads
仓库地址:apache/tomcat: Apache Tomcat (github.com)
如果想在代码中做一些注释,可以fork到自己的账号。执行如下命令,下载10.0.14版本:
git clone -b 10.0.14 https://github.com/apache/tomcat.git
Tomcat默认采用的是Ant方式构建,官网中也对用其他方式做了提示:
重要提示:这不是构建 Tomcat 的支持方法; 此信息不提供任何保证:-)。 构建 Tomcat 的唯一支持方法是使用上述 Ant 构建。 但是,一些开发人员喜欢使用 Java IDE 处理 Java 代码。
为了方便调试,我们采用Maven方式在Idea中调试源码。
首先在下载的代码根目录创建一个Maven的pom.xml文件,添加需要的依赖:
<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.0modelVersion>
<groupId>org.apache.tomcatgroupId>
<artifactId>tomcat10artifactId>
<version>10.0.14version>
<name>tomcat10name>
<dependencies>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.13.2version>
<scope>testscope>
dependency>
<dependency>
<groupId>org.easymockgroupId>
<artifactId>easymockartifactId>
<version>4.3version>
dependency>
<dependency>
<groupId>org.apache.antgroupId>
<artifactId>antartifactId>
<version>1.10.12version>
dependency>
<dependency>
<groupId>wsdl4jgroupId>
<artifactId>wsdl4jartifactId>
<version>1.6.3version>
dependency>
<dependency>
<groupId>javax.xmlgroupId>
<artifactId>jaxrpc-apiartifactId>
<version>1.1version>
dependency>
<dependency>
<groupId>org.eclipse.jdtgroupId>
<artifactId>org.eclipse.jdt.coreartifactId>
<version>3.28.0version>
dependency>
<dependency>
<groupId>org.eclipse.jdtgroupId>
<artifactId>ecjartifactId>
<version>3.28.0version>
dependency>
<dependency>
<groupId>org.apache.tomcatgroupId>
<artifactId>jakartaee-migrationartifactId>
<version>1.0.0version>
dependency>
<dependency>
<groupId>biz.aQute.bndgroupId>
<artifactId>biz.aQute.bndlibartifactId>
<version>6.1.0version>
<scope>providedscope>
dependency>
<dependency>
<groupId>com.unboundidgroupId>
<artifactId>unboundid-ldapsdkartifactId>
<version>6.0.2version>
<scope>testscope>
dependency>
dependencies>
<build>
<finalName>Tomcat10.0finalName>
<sourceDirectory>javasourceDirectory>
<testSourceDirectory>testtestSourceDirectory>
<resources>
<resource>
<directory>javadirectory>
resource>
resources>
<testResources>
<testResource>
<directory>testdirectory>
testResource>
testResources>
<plugins>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-compiler-pluginartifactId>
<version>3.6.1version>
<configuration>
<encoding>UTF-8encoding>
<source>1.8source>
<target>1.8target>
configuration>
plugin>
plugins>
build>
project>
右键点击代码文件夹,选择用Idea打开。或者再Idea中通过File->New->Project from Sources的方式打开代码文件夹:
点击Maven的Reload按钮开始加载依赖:
等待加载完成。
点击Build按钮开始构建项目,会提示:“java: 程序包trailers不存在。”和“找不到符号 ResponseTrailers”,两个错误都出现在test文件夹。缺少的文件都在webapps/examples/WEB-INF/classes文件夹,
拷贝文件夹“webapps/examples/WEB-INF/classes/trailers”到“test”文件夹下。
拷贝文件“webapps/examples/WEB-INF/classes/util/CookieFilter.java”到“test/util”文件夹下。
此时再次Build不再出错。
找到文件“java/org/apache/catalina/startup/Bootstrap.java”,其中的main方法是Tomcat的启动起点。
Run这个方法,启动Tomcat,默认地址为“http://localhost:8080/“。
默认会监听8080端口,如图提示被占用,可以去“conf/server.xml”文件中修改:
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
修改“java/org/apache/catalina/startup/ContextConfig.java”文件,在configureStart方法中添加一行代码,位置如下面所示:
protected synchronized void configureStart() {
// 此处省略一部分代码
webConfig();
// 添加下面一行代码
context.addServletContainerInitializer(new JasperInitializer(), null);
if (!context.getIgnoreAnnotations()) {
applicationAnnotationsConfig();
}
再次启动,可以看到熟悉的页面了。
可以看到如下错误:
和2.2中遇到的错误类似,对应的文件还是存在于“webapps/examples/WEB-INF/classes”文件夹中:
而“webapps/examples/WEB-INF/web.xml”中对这几个Listener做了引用。
这个Webapps文件夹就是我们平时正常使用Tomcat的时候,用于放置网站的目录。里面现有的文件也是平时安装Tomcat之后存在的默认网站。出问题的原因是这个默认网站也是源代码状态,未编译,所以导致找不到对应的类。
如果下载Tomcat的安装文件(64-bit Windows zip),对比一下examples文件夹的内容,如下图,左侧为源代码目录,右侧为安装包中的文件目录,可以看到对右侧编译后的文件。
处理这个问题,一种方案是删掉examples文件夹,但这个文件夹其实提供了我们用来调试的样例,想办法利用起来。将右侧的内容拷贝到左侧(文件夹复制,跳过存在的文件),再次运行,问题已解决。
上文说到webapp里的examples文件夹即默认网站的examples菜单对应内容.
examples提供了一些样例,正好可以用于调试Tomcat源码:
例如我在CoyoteAdapter的service方法中添加了一个断点
点击Hello World后面对应的Execute链接,断点被激活,一个请求的处理就这么开始了。可以根据自己的调试需求去添加断点调试了。