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:

Tomcat源码分析一:编译Tomcat源码的更多相关文章

  1. php中foreach源码分析(编译原理)

    php中foreach源码分析(编译原理) 一.总结 编译原理(lex and yacc)的知识 二.php中foreach源码分析 foreach是PHP中很常用的一个用作数组循环的控制语句.因为它 ...

  2. [Tomcat 源码分析系列] (二) : Tomcat 启动脚本-catalina.bat

    概述 Tomcat 的三个最重要的启动脚本: startup.bat catalina.bat setclasspath.bat 上一篇咱们分析了 startup.bat 脚本 这一篇咱们来分析 ca ...

  3. Tomcat源码分析----eclipse中搭建源码环境

    前提:JDK,至少1.7,ant,要设置ANT_HOME环境变量,需要再classpath中增加ant的lib目录,在path变量中增加ant的bin目录 1.官网下载tomcat源码包:apache ...

  4. Tomcat源码分析三:Tomcat启动加载过程(一)的源码解析

    Tomcat启动加载过程(一)的源码解析 今天,我将分享用源码的方式讲解Tomcat启动的加载过程,关于Tomcat的架构请参阅<Tomcat源码分析二:先看看Tomcat的整体架构>一文 ...

  5. 精尽Spring Boot源码分析 - 内嵌Tomcat容器的实现

    该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...

  6. 精尽Spring Boot源码分析 - 支持外部 Tomcat 容器的实现

    该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...

  7. [转] jQuery源码分析-如何做jQuery源码分析

    jQuery源码分析系列(持续更新) jQuery的源码有些晦涩难懂,本文分享一些我看源码的方法,每一个模块我基本按照这样的顺序去学习. 当我读到难度的书或者源码时,会和<如何阅读一本书> ...

  8. Redis源码分析:serverCron - redis源码笔记

    [redis源码分析]http://blog.csdn.net/column/details/redis-source.html   Redis源代码重要目录 dict.c:也是很重要的两个文件,主要 ...

  9. 序列化器中钩子函数源码分析、many关键字源码分析

    局部钩子和全局钩子源码分析(2星) # 入口是 ser.is_valid(),是BaseSerializer的方法 # 最核心的代码 self._validated_data = self.run_v ...

  10. k8s client-go源码分析 informer源码分析(5)-Controller&Processor源码分析

    client-go之Controller&Processor源码分析 1.controller与Processor概述 Controller Controller从DeltaFIFO中pop ...

随机推荐

  1. Node基础-CommonJS模块化规范

    1.在本地项目中基于NPM/YARN安装第三方模块 第一步:在本地项目中创建一个"package.json"的文件 作用:把当前项目所有依赖的第三方模块信息(包含:模块名称以及版本 ...

  2. Integer和Integer常量池

    Integer中有个静态内部类 IntegerCache ,里面有个cache[],也就是Integer常量池  大小为一个字节(-128-127). (jdk1.8.0_101)源码 private ...

  3. 【Nginx】应用场景

    一.概述 二.Nginx虚拟主机配置 2.1 外网映射工具 2.2 基于虚拟主机配置域名 2.3 基于端口的虚拟主机 三.Nginx配置反向代理 3.1 反向代理的作用 3.2 反向代理的好处 3.3 ...

  4. d3.js 实现烟花鲜果

    今天在d3.js官网上看到了一个烟花的DEMO,是canvas制作的,于是我想用d3.js来实现它,js代码只有几行.好了废话不多说,先上图. 1 js 类 因为烟花要有下落的效果,所以里面用到了一些 ...

  5. ubuntu下安装rtl8811cu/rtl8821cu网卡 Tplink WDN5200H网卡

    博客园第一篇博客,CSDN现在让人眼花缭乱了 @_@ 由于需要wifi调试,笔记本内置的网卡有点不太灵光,买了个TPLINK的WDN5200H AC网卡,给虚拟机用,折腾一下成功了github上有rt ...

  6. HTML连载37-边框属性(下)、边框练习

    一.边框属性 1.连写(分别设置四条边的边框) border-width:上 右 下 左: border-style:上 右 下 左: border-color:上 右 下 左: 注意点: (1)这三 ...

  7. 多场景抢红包业务引发.NETCore下使用适配器模式实现业务接口分离

    事情的起因 我们公司现有一块业务叫做抢红包,最初的想法只是实现了一个初代版本,就是给指定的好友单发红包,随着业务的发展,发红包和抢红包的场景也越来越多,目前主要应用的场景有:单聊发红包.群聊发红包.名 ...

  8. C++ 基础中的基础 ---- 引用

    C++ 基础中的基础 ---- 引用 引用的概念:引用变量是一个别名,也就是说,它是某个已存在变量的另一个名字.一旦把引用初始化为某个变量,就可以使用该引用名称或变量名称来指向变量.比如: int n ...

  9. rabbitmqctl: Error unable to connect to node 'rabbit@xxxxx' nodedown

    RabbitMQ使用rabbitmqctl add_user的时候报以下错误: Creating user "xxxx" ... Error: unable to connect ...

  10. Node.js之模块机制

    > 文章原创于公众号:程序猿周先森.本平台不定时更新,喜欢我的文章,欢迎关注我的微信公众号. ![file](https://img2018.cnblogs.com/blog/830272/20 ...