tomcat源码调试之环境搭建

准备工作

调试工具:
idea 2023.3.2 + maven-3.6.3 + jdk 1.8

源码获取方式:

tomcat源码地址:github.com/apache/tomc...

clone:github.com/apache/tomc...

考虑到很多国内网络环境原因,直接在gitee上新建仓库,导入即可,gitee操作如下

导入之后:

点击确定即可,这样源码就clone到gitee上了,我们在gitee上新建一个分支,以9.0.x分支为基准,建一个9.0x-study,接下来就是clone你gitee的分支,我相信大家都是clone的一把老手了,就忽略步骤了。

正式开始

接下来就开始我们的环境搭建,idea打开tomcat源码,切换到我们的目标分支上(9.0x-study)分支上,由于tomcat是用ant进行管理,我没有使用ant,我使用的是maven,原理都差不多,都是下载依赖jar包, 在tomcat目录下,新建一个pom.xml文件,这里我也是搜了一下别人的方案,有坑,经过排查之后的文件内容如下:

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>tomcat</artifactId>
  <name>tomcat</name>
  <version>9.0</version>
  <description>9.0.x分支有效,其他分支请自己尝试解决</description>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.13.2</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>ant</groupId>
      <artifactId>ant</artifactId>
      <version>1.6.5</version>
    </dependency>
    <dependency>
      <groupId>org.easymock</groupId>
      <artifactId>easymock</artifactId>
      <version>4.3</version>
    </dependency>
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.18.26</version>
    </dependency>
    <dependency>
      <groupId>biz.aQute.bnd</groupId>
      <artifactId>biz.aQute.bndlib</artifactId>
      <version>5.2.0</version>
      <scope>provided</scope>
    </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.6.1</version>
    </dependency> -->

   <!--此配置项才是正确的,上面那个包迁移了,有很多代码里配置项都找不到会报错-->
    <dependency>
      <groupId>org.eclipse.jdt</groupId>
      <artifactId>ecj</artifactId>
      <version>3.26.0</version>
    </dependency>


  </dependencies>

  <build>
    <finalName>tomcat</finalName>
    <sourceDirectory>java</sourceDirectory>
    <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>3.5.1</version>
        <configuration>
          <encoding>UTF-8</encoding>
          <source>1.8</source>
          <target>1.8</target>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <version>2.6</version>
      </plugin>
    </plugins>
  </build>
</project>

然后直接加载pom文件,开始下载依赖。

开始启动

首先我们需要找到tomcat的启动类,那该怎么找到呢? 回想我们启动tomcat的过程,以liunx为例,首先我们会去tomcat的bin目录下,执行startup.sh这个脚本,那么我们就顺着这个脚本往下看,一层层的去找到最后的方法,毕竟咱们java的启动入口是main方法,对吧!

在脚本里又去执行了catalina.sh,那么我们继续往下看catalina脚本,在脚本里,判断参数啥的,还有就是一些设置之类的,关键的在后,不管走什么分支,都会执行如下一行代码:

脚本具体的内容因为本人水平有限,不展开细说,主要关键的一句代码

bash 复制代码
org.apache.catalina.startup.Bootstrap "$@" start

这是主启动类,我们去看看对应的源码,里面有一个main方法,重要的事情说三遍,main方法、main方法、main方法.

我们java启动的函数入口,终于追到这个方法了,看情况是执行catalina.sh的时候,脚本传了一个参数:start,对应的源码里判断args的参数是不是start,那么我们启动的时候,肯定要给main方法也传入一个start参数,这样才能对应好里面的分支条件判断,执行分支的代码吧,当然也有别的参数要传入如下参数需要传:

ini 复制代码
-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
-Djava.util.logging.config.file=F:\workspace\java\tomcat\conf\logging.properties

怎么传入进去呢? 我们需要打开idea的启动选项如下所示:

编辑配置

添加一个应用程序

解释如下: 1、选择一个jdk版本,我这里用的是8,可以看看官网对应的版本就可以,而且idea可以管理多个Jdk版本,很方便,小伙伴搜一下就可以,这里不做过多的解释 2、填写我们的参数,直接复制就可以,里面的logging.properties 路径要根据你具体tomcat路径填写要绝对路径哈 3、填写我们的启动类,直接填写 org.apache.catalina.startup.Bootstrap 就可以,复制的时候注意空格 4、填写启动的参数start。 温馨提示,有很多小伙伴更新到最新的版本之后,只有一处填写启动参数的地方,可以打开选项,打开添加虚拟机选项,就会多一行

至此可以打开debug开启你的调试之路了,可以跟上源代码流程,以下是我遇到的问题,启动乱码,直接去 org.apache.tomcat.util.res.StringManager#getString 方法里面(注意哦,有重载),关注一个参数的方法 ,在最后返回str的时候,直接转码一下,因为默认的编码是ISO-8850-1,可能在启动参数的时候,加上编码字符集也可以,不过我没加

javascript 复制代码
if(str!=null){
    try {
            str = new String(str.getBytes("ISO-8859-1"), "UTF-8");
    }catch (Exception exception){

    }
}

如果解析jsp报错,可以尝试一下方法打开org.apache.catalina.startup.ContextConfig#configureStart 方法中,添加一行代码,是为了解析jsp的,默认是没有需要自己加

代码如下:

csharp 复制代码
context.addServletContainerInitializer(new JasperInitializer(), null);

至此,我本地启动已经可以了,而且直接访问127.0.0.1:8080 可以直接出现tomcat的首页,如果有问题,可以一起探讨。

相关推荐
WannaRunning34 分钟前
浅谈Tomcat数据源连接池
java·oracle·tomcat
兢兢业业的小白鼠16 小时前
Java高级JVM知识点记录,内存结构,垃圾回收,类文件结构,类加载器
java·开发语言·jvm·tomcat
chushiyunen17 小时前
tomcat使用笔记、启动失败但是未打印日志
java·笔记·tomcat
杉之20 小时前
SpringBlade 数据库字段的自动填充
java·笔记·学习·spring·tomcat
心灵宝贝21 小时前
Tomcat 部署 Jenkins.war 详细教程(含常见问题解决)
java·tomcat·jenkins
生命是有光的1 天前
【中间件安全计划】锚定Tomcat安全基线
安全·中间件·tomcat
qq_431510161 天前
tomcat组件概览
java·tomcat
ccc_9wy2 天前
玄机-第六章 流量特征分析-常见攻击事件 tomcat的测试报告
网络安全·tomcat·玄机靶场·攻击流程·溯源分析·定时任务反弹shell·gobuster
当归10242 天前
Tomcat中的webapps的访问方式和java -jar内置Tomcat的访问方式的区别
java·tomcat·jar
magic 2452 天前
监听器(Listener)详解
java·servlet·tomcat