Tomcat源码学习 - 环境搭建

一. 源码下载

PS: 多图预警

在开始阅读源码之前,我们需要先构建一个环境,这样才能便于我们对源码进行调试,具体源码我们可以到官网进行下载(这里我以8.5.63版本为例)。

image

二. 项目导入

下载并解压 apache-tomcat-8.5.63-src.zip。

image

然后进入 apache-tomcat-8.5.63-src 目录,新增一个 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>apache-tomcat-8.5.63-src</artifactId>
    <version>8.5</version>
    <name>Tomcat8.5</name>

<!-- Tomcat基础依赖包 -->
<dependencies>
    <!-- 远程过程调用工具包 -->
    <dependency>
        <groupId>javax.xml</groupId>
        <artifactId>jaxrpc</artifactId>
        <version>1.1</version>
    </dependency>
    <!-- soap协议处理工具包 -->
    <dependency>
        <groupId>javax.xml.soap</groupId>
        <artifactId>javax.xml.soap-api</artifactId>
        <version>1.4.0</version>
    </dependency>
    <!-- 解析webservice的wsdl文件工具 -->
    <dependency>
        <groupId>wsdl4j</groupId>
        <artifactId>wsdl4j</artifactId>
        <version>1.6.2</version>
    </dependency>
    <!-- Eclipse Java编译器 -->
    <dependency>
        <groupId>org.eclipse.jdt.core.compiler</groupId>
        <artifactId>ecj</artifactId>
        <version>4.5.1</version>
    </dependency>
    <!-- ant管理工具 -->
    <dependency>
        <groupId>ant</groupId>
        <artifactId>ant</artifactId>
        <version>1.7.0</version>
    </dependency>
    <!-- easymock辅助单元测试 -->
    <dependency>
        <groupId>org.easymock</groupId>
        <artifactId>easymock</artifactId>
        <version>3.4</version>
    </dependency>
</dependencies>

    <build>
        <!-- 指定源目录 -->
        <finalName>Tomcat8.5</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>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

通过IDEA引入项目

image

打开项目之后,全局搜索一下 main 方法,找到 tomcat 的入口

image

一共有6个 main 方法,其中有一个 Bootstrap 类,翻译过来就是引导程序的意思,我们直接跳转到这个类过去,跑一下看看有没有什么问题。


image

项目启动成功了,控制台输出的信息有乱码,暂时不管,我们看看能不能访问到首页。

image

显示500状态码,给出的信息也很多是乱码,那我们来看一下是什么原因导致的吧。

三. 乱码的原因

找到最开始出现乱码的地方,选中这个类名,双击 Shift 键查找并跳转到对应方法处。

image
image

打个断点,然后开始 DEBUG,先一层层进入,跟踪下看看首次出现乱码的地方是在哪

image

在这里我们可以看到,通过 handleGetObject() 方法得到的对象是有乱码的情况,在这里打上一个断点,然后继续深入

先一层层进入,跟踪下看看首次出现乱码的地方是在哪

// Debug跳转线路
VersionLoggerListener.java
private void log(){ ... }

    ↓

StringManager.java
public String getString(String key){ ... }

    ↓

ResourceBundle.java
public final Object getObject(String key){ 
    Object obj = handleGetObject(key);
    ...
}

    ↓

protected abstract Object handleGetObject(String key);

    ↓

PropertyResourceBundle.java
public Object handleGetObject(String key){
    return lookup.get(key);
}

protected abstract Object handleGetObject(String key); 这是一个抽象方法,点击 Setp into 按钮跳转进到对应的具体实现方法中

image

在这个方法中我们可以看到他实际上是在一个 HashMap 中根据传入的 key 来获取对应的 value,选择该代码块,按 AIT + F8 进行查看

在这里插入图片描述

发现起因了,在这个 HashMap 中存储的 value 都是乱码的,才会导致后面调用到的地方显示的都是乱码

image

起因发现了,那么我们就得来找一下这个 HashMap 对象的 put 操作是在哪一处进行的,才好真正的解决问题。

选择 lookupCtrl + F 查找一下,找到一下两个方法,都给他打上断点,然后重启项目,看看具体是由哪个方法来实现的。

image

在这里我们可以看到他是通过输入流的形式来实现的,在下方的 Variables 窗口中可以看到 Properties 加载出来的数据已经是乱码的了

image

Frames 窗口点击上一栈帧,找到当前方法的调用入口,回溯上去找到 stream 的来源

image

image

image

按照上面给出的路径找到对应的文件,可以看到里面是 UTF-8 编码的中文字符。

image

文件编码没有问题,那么问题就是出在 is = classLoader.getResourceAsStream(resourceName); 这个方法上了,这时候我们想对他进行一个修改,发现该类是锁定状态,无法修改,只能看不能碰这有点难度呀~

四. 解决乱码

我们还得重新来一遍,看看这个配置信息再哪个可编辑的类中有使用,然后再进行修改

// Debug跳转线路
VersionLoggerListener.java
private void log(){ ... }

    ↓

StringManager.java
public String getString(String key){ ... }

我们可以看到再 StringManager 这个类中有一个获取的方法,再往下走就是加锁的类了,那么我们尝试着在这一层对该结果进行编码转换,看看效果如何

image

image

有效果,控制台这边显示的信息已经没有乱码了,再看一下页面这边如何


image
image

页面这边还是有一部分显示是乱码的,看来还有地方需要修改,继续找下看


image

通过查看控制台的错误信息,全局搜索一下该提示出现位置进行定位


image

跳转到对应位置,Ctrl + 左键 定位到调用的地方,在这里可以看到 error() 方法中有具体的一些信息参数,我们用老方法对这 e.getMessage 这个参数修改一下看

image

image

控制台的乱码解决了,可是页面这边的还是乱码,看来是找错地方了,再来!


image

image

根据页面的提示找到 JspCompilationContext 类的 compile 方法,逐行查看,找到出错的地方

image

看到这里有个 Localizer.getMessage() 方法用来获取信息的,跳进来看一下,果然是这里,找到地方了,直接办他!

image

image

重启项目,再次刷新查看效果,终于搞定了,不容易呀~


image

五. 解决 ‘无法为JSP编译类’ 异常

导致页面显示500状态码的原因是 Tomcat 源码中 jsp 引擎 Jasper 没有被初始化,从而无法编译处理 jsp (以为 jsp 是需要被转换成 servlet 进一步编译处理的),我们只需要在 Tomcat 的源码 ContextConfig 类的 configureStart 方法中把该引擎进行初始化即可,代码如下:

context.addServletContainerInitializer(new JasperInitializer(), null);
image

现在就大公告成拉!!!


image

我收集有众多的 计算机电子书籍,有需要的小伙伴自提哦~

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271

推荐阅读更多精彩内容