前言

最近开始研究下Tomcat源码,毕竟用了这么多年了,却没有深入了解它,最多网上看看博文帖子,知道它由什么Server、Service、Engine、Host、Context、Wrapper等组件,却完全不知道,真正的数据流动,比如怎么解析浏览器请求,怎么到Servlet的,所以考虑搭建下源码环境,仔细Debug下。

下载源码

这个只需要访问官网https://tomcat.apache.org/

然后点击左边的Download,这里下载的是Tomcat8,版本为8.5.75,进入到Tomcat8的页面https://tomcat.apache.org/download-80.cgi

点击最下面的Source Code Distributions-zip,具体链接为https://dlcdn.apache.org/tomcat/tomcat-8/v8.5.75/src/apache-tomcat-8.5.75-src.zip

还有eclipse,jdk,maven等这些必备的工具环境,话说网上有人说应为tomcat是用ant构建的,所以也要下载ant,然后进入源码目录里面cmd执行ant,可惜我这里不知怎么回事,一直报如下错误,可能是网络不行。

在eclipse中配tomcat的步骤(Tomcat篇Tomcat源码Eclipse环境搭建)(1)

所以还是采取maven的方式

导入源码

我们在源码目录里面新建pom.xml文件,内如如下(改为自己的tomcat版本)

<?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>apache-tomcat-8.5.75-src</artifactId> <name>Tomcat8.5.75</name> <version>8.5.75</version> <build> <!--指定源⽬录 --> <finalName>Tomcat8.5.75</finalName> <sourcedirectory>java</sourceDirectory> <resources> <resource> <directory>java</directory> </resource> </resources> <plugins> <!--引⼊编译插件 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <encoding>UTF-8</encoding> <source>8</source> <target>8</target> </configuration> </plugin> </plugins> </build> <!--tomcat 依赖的基础包 --> <dependencies> <dependency> <groupId>org.easymock</groupId> <artifactId>easymock</artifactId> <version>3.4</version> </dependency> <dependency> <groupId>ant</groupId> <artifactId>ant</artifactId> <version>1.7.0</version> </dependency> <dependency> <groupId>wsdl4j</groupId> <artifactId>wsdl4j</artifactId> <version>1.6.2</version> </dependency> <dependency> <groupId>javax.xml</groupId> <artifactId>jaxrpc</artifactId> <version>1.1</version> </dependency> <dependency> <groupId>org.eclipse.jdt.core.compiler</groupId> <artifactId>ecj</artifactId> <version>4.5.1</version> </dependency> <dependency> <groupId>javax.xml.soap</groupId> <artifactId>javax.xml.soap-api</artifactId> <version>1.4.0</version> </dependency> </dependencies> </project>

然后用eclipse导入已存在的maven项目就可以了

启动测试

Tomcat的启动类是org.apache.catalina.startup.Bootstrap,只有这个类有个main方法,右键配置Debug Configurations,配置Arguments下面的VM arguments添加如下配置

-Dcatalina.home=F:/Source/apache-tomcat-8.5.75-src -Dcatalina.base=F:/Source/apache-tomcat-8.5.75-src -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.util.logging.config.file=F:/Source/apache-tomcat-8.5.75-src/conf/logging.properties

然后右键debug启动,发现启动成功

26-Feb-2022 15:07:02.364 信息 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory 26-Feb-2022 15:07:02.442 信息 [main] org.apache.catalina.startup.Catalina.start Server startup in 2810 ms

浏览器访问http://localhost:8080/,发现乱码了

在eclipse中配tomcat的步骤(Tomcat篇Tomcat源码Eclipse环境搭建)(2)

看错误是JSP解析引擎未初始化,我们去org.apache.catalina.startup.ContextConfig的configureStart方法webConfig();后面加上

//初始化JSP解析引擎 context.addServletContainerInitializer(new JasperInitializer(),null);

protected synchronized void configureStart() { // Called from StandardContext.start() if (log.isDebugEnabled()) { log.debug(sm.getString("contextConfig.start")); } if (log.isDebugEnabled()) { log.debug(sm.getString("contextConfig.xmlSettings", context.getName(), Boolean.valueOf(context.getXmlValidation()), Boolean.valueOf(context.getXmlNamespaceAware()))); } webConfig(); //初始化JSP解析引擎 context.addServletContainerInitializer(new JasperInitializer(),null); if (!context.getIgnoreAnnotations()) { applicationAnnotationsConfig(); } if (ok) { validateSecurityRoles(); } // Configure an authenticator if we need one if (ok) { authenticatorConfig(); } // Dump the contents of this pipeline if requested if (log.isDebugEnabled()) { log.debug("Pipeline Configuration:"); Pipeline pipeline = context.getPipeline(); Valve valves[] = null; if (pipeline != null) { Valves = pipeline.getvalves(); } if (valves != null) { for (Valve valve : valves) { log.debug(" " valve.getClass().getName()); } } log.debug("======================"); } // Make our application available if no problems were encountered if (ok) { context.setConfigured(true); } else { log.error(sm.getString("contextConfig.unavailable")); context.setConfigured(false); } }

再启动访问就完美了

在eclipse中配tomcat的步骤(Tomcat篇Tomcat源码Eclipse环境搭建)(3)

,