Tomcat源码分析一:编译Tomcat源码
Tomcat源码分析一:编译Tomcat源码
1 内容介绍
在之前的《Servlet与Tomcat运行示例》一文中,给大家带来如何在Tomcat中部署Servlet应用的相关步骤,本文将就上文为基础,开始Tomcat源码分析之旅,我将详细的分析Tomcat的启动过程及运行原理。本文将是最基础的一节课,也就是本地编译好Tomcat源码,为后面的分析做基础!
2 编译Tomcat源码
2.1 下载Tomcat源码
我们去Tomcat官网下载最新的Tomcat源码包,目前最新的版本为9.0.26,我们下载其source源码包tar.gz版本,如下图:

2.2 解压源码包apache-tomcat-9.0.26-src.tar.gz
解压源码包apache-tomcat-9.0.26-src.tar.gz之后得到的内容为:

2.3 解压后的文件夹中添加pom.xml
因为要使用Maven的方式导入Tomcat项目,故需要添加相应的maven依赖,此处添加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>com.github.sources</groupId>
<artifactId>source-tomcat</artifactId>
<version>9.0.26</version>
<name>source-tomcat</name>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant</artifactId>
<version>1.10.1</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</groupId>
<artifactId>org.eclipse.jdt.core</artifactId>
<version>3.18.0</version>
</dependency>
<dependency>
<groupId>org.eclipse.jdt.core.compiler</groupId>
<artifactId>ecj</artifactId>
<version>4.6.1</version>
</dependency>
</dependencies>
<build>
<finalName>Tomcat9.0</finalName>
<sourceDirectory>java</sourceDirectory>
<testSourceDirectory>test</testSourceDirectory>
<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.6.1</version>
<configuration>
<encoding>UTF-8</encoding>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
2.4 IDEA导入tomcat源码工程
使用IDEA开发工具,以Maven的方式导入tomcat工程,导入之后工程结构如下:

2.5 启动Tomcat工程
运行org.apache.catalina.startup包下的Bootstrap类的main方法

此时,我们发现了一些错误,下面我们来解决这些错误。
3 异常问题解决
3.1 trailers.ResponseTrailers不存在
我们可以去webapps/examples/WEB_INF/classes/trailers 目录下找到该类,我们将这个类复制一份到test下:

拷贝完成之后的情况如下:

3.2 CookieFilter不存在
同样,我们去将home\webapps\examples\WEB-INF\classes\util\CookieFilter.java 文件拷贝到 test\util 目录下:

3.3 FileNotFoundException: /Library/ApacheTomcat/source/test/source-tomcat/conf/server.xml (No such file or directory)
在解决上述3.1和3.2的问题之后,又出现了下图所示的问题:

- 解决方案:
在启动的配置中,添加VM options的参数,添加项目路径,本机为/Library/ApacheTomcat/source/test/apache-tomcat-9.0.26-src,故而添加参数内容为:
-Dcatalina.home=/Library/ApacheTomcat/source/test/apache-tomcat-9.0.26-src, 如下图所示:

3.4 java.lang.ClassNotFoundException: listeners.ContextListener
在解决上述3.3问题之后,再次启动Bootstrap类的main方法,程序出现以下错误信息:

- 解决方案: 删除 webapps 下的 examples 文件夹!程序再次运行不报此错误!
3.5 Servlet.service() for servlet [jsp] in context with path [] threw exception [org.apache.jasper.JasperException: Unable to compile class for JSP] with root cause
在解决上述问题之后,启动Bootstrap类的main方法,程序正常启动,此时我们在浏览器访问127.0.0.1:8080, 程序出现以下错误信息:


- 解决方案:编辑 org.apache.catalina.startup.ContextConfig 文件的 configureStart() 方法,添加初始化 JSP 解析器的代码:
context.addServletContainerInitializer(new JasperInitializer(), null);

添加之后,再次启动main方法,浏览器输入127.0.0.1:8080得到的结果为Tomcat的界面:

3.6 日志乱码
启动的日志中含有很多的乱码,虽然对程序整体并不影响,但是在之后查看日志时,还是影响比较大的,先看下日志乱码的情况:

- 解决方案:
修改vm options 内容,将环境设置为美国-英文,设置内容如下:
-Duser.language=en -Duser.region=US -Dfile.encoding=UTF-8

再次运行main方法,程序日志正常显示:

至此,我们已经将Tomcat的源码导入到IDEA的工具中,也解决了一些问题,之后,我们将利用这份源码来分析Tomcat的启动及运行原理。
Blog:
- 简书: https://www.jianshu.com/u/91378a397ffe
- csdn: https://blog.csdn.net/ZhiyouWu
- 开源中国: https://my.oschina.net/u/3204088
- 掘金: https://juejin.im/user/5b5979efe51d451949094265
- 博客园: https://www.cnblogs.com/zhiyouwu/
- 微信公众号: 源码湾
- 微信: WZY1782357529 (欢迎沟通交流)
Tomcat源码分析一:编译Tomcat源码的更多相关文章
- php中foreach源码分析(编译原理)
php中foreach源码分析(编译原理) 一.总结 编译原理(lex and yacc)的知识 二.php中foreach源码分析 foreach是PHP中很常用的一个用作数组循环的控制语句.因为它 ...
- [Tomcat 源码分析系列] (二) : Tomcat 启动脚本-catalina.bat
概述 Tomcat 的三个最重要的启动脚本: startup.bat catalina.bat setclasspath.bat 上一篇咱们分析了 startup.bat 脚本 这一篇咱们来分析 ca ...
- Tomcat源码分析----eclipse中搭建源码环境
前提:JDK,至少1.7,ant,要设置ANT_HOME环境变量,需要再classpath中增加ant的lib目录,在path变量中增加ant的bin目录 1.官网下载tomcat源码包:apache ...
- Tomcat源码分析三:Tomcat启动加载过程(一)的源码解析
Tomcat启动加载过程(一)的源码解析 今天,我将分享用源码的方式讲解Tomcat启动的加载过程,关于Tomcat的架构请参阅<Tomcat源码分析二:先看看Tomcat的整体架构>一文 ...
- 精尽Spring Boot源码分析 - 内嵌Tomcat容器的实现
该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...
- 精尽Spring Boot源码分析 - 支持外部 Tomcat 容器的实现
该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...
- [转] jQuery源码分析-如何做jQuery源码分析
jQuery源码分析系列(持续更新) jQuery的源码有些晦涩难懂,本文分享一些我看源码的方法,每一个模块我基本按照这样的顺序去学习. 当我读到难度的书或者源码时,会和<如何阅读一本书> ...
- Redis源码分析:serverCron - redis源码笔记
[redis源码分析]http://blog.csdn.net/column/details/redis-source.html Redis源代码重要目录 dict.c:也是很重要的两个文件,主要 ...
- 序列化器中钩子函数源码分析、many关键字源码分析
局部钩子和全局钩子源码分析(2星) # 入口是 ser.is_valid(),是BaseSerializer的方法 # 最核心的代码 self._validated_data = self.run_v ...
- k8s client-go源码分析 informer源码分析(5)-Controller&Processor源码分析
client-go之Controller&Processor源码分析 1.controller与Processor概述 Controller Controller从DeltaFIFO中pop ...
随机推荐
- Codeforces 939 D Love Rescue
Love Rescue 题意:Valya 和 Tolya 是一对情侣, 他们的T恤和头巾上都有小写字母,但是女朋友嫌弃男朋友上T恤上的字不和她的头巾上的字一样,就很生气, 然后来了一个魔法师, 它可以 ...
- Treasure Hunt CodeForces - 979B
After the big birthday party, Katie still wanted Shiro to have some more fun. Later, she came up wit ...
- R语言基础入门
请先安装好R和RStudio 如果不干别的,控制台就是一个内置计算器 2 * 3 #=> 6 sqrt(36) #=> 6, square root log10(100) #=> 2 ...
- pt工具校验主从数据一致性之dsns方式
mysql主从数据一致性校验,常用的方法是Percona-Toolkit的组件pt-table-checksum,这东西怎么用网上一大堆,就不啰嗦了.主要说一下通过dsns方式发现从库的一种方式. p ...
- Java日志框架总结
1. 前言 从写代码开始,就陆陆续续接触到了许多日志框架,较常用的属于LOG4J,LogBack等.每次自己写项目时,就copy前人的代码或网上的demo.配置log4j.properties或者lo ...
- Java的8种基本数据类型的内存占用字节数和取值范围
这是8中基本类型的内存中占用字节数(取值范围是2的(字节数X8-1)次方) 1.整型 类型 存储需求 bit数 取值范围 byte 1字节 1*8 -128-127 short 2字节 2*8 -32 ...
- Alodi:为了保密我开发了一个系统
每天都在愉快的造轮子,这次可以一键创建测试环境 咖啡君维护了几十个不同类型项目,其中有相当一部分项目是对保密性有很高要求的,也就是说下个版本要上线的内容是不能提前泄露的,就像苹果新产品的介绍网站决不允 ...
- Python文件访问编码格式问题UnicodeDecodeError: 'gbk' codec can't decode byte 0x80 in position xx: 解决方案
1.Python读取文件 # .打开文件 file = open("ReadMe") # .读取文件类容 text = file.read() print(text) # .关闭文 ...
- Hive函数大全-完整版
现在虽然有很多SQL ON Hadoop的解决方案,像Spark SQL.Impala.Presto等等,但就目前来看,在基于Hadoop的大数据分析平台.数据仓库中,Hive仍然是不可替代的角色.尽 ...
- Django跳转到不同的页面的方法和实例–使用Django建立你的第一个网站
1 前记 这次记录的这些东西,主要是自己在搭建个人网站的时候遇到的一些问题记录,不算严格意义上的教程和使用说明.按照目前自己的web水平,去写这方面的教程无疑是误人子弟.因为自己虽然做程序员很多年,但 ...