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的首页,如果有问题,可以一起探讨。

相关推荐
QMY5205207 小时前
爬虫的意义
java·spring·tomcat·maven
5pace18 小时前
Mac Nginx安装、启动、简单命令(苍穹外卖、黑马点评前端环境搭建)
java·前端·nginx·macos·tomcat
旷野说1 天前
Spring Boot 1.x、2.x 3.x区别汇总
java·spring·tomcat·1024程序员节
JH30732 天前
jvm,tomcat,spring的bean容器,三者的关系
jvm·spring·tomcat
R.lin2 天前
使用 Undertow 替代 Tomcat
java·后端·tomcat
Live&&learn2 天前
Tomcat 10和Tomcat 9引入servlet的不同
java·servlet·tomcat
K_i1342 天前
Tomcat核心原理与运维实战指南
java·运维·tomcat
知其然亦知其所以然3 天前
我被问懵了:Tomcat 到底有几种部署方式?
后端·面试·tomcat
or77iu_N3 天前
Linux 解压安装(安装tomcat)
linux·运维·tomcat
星月昭铭3 天前
Spring MVC 接口匹配性能优化:.do后缀引发的性能瓶颈分析
spring·性能优化·tomcat