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. “玲珑杯”ACM比赛 Round #18 C -- 图论你先敲完模板(和题目一点关系都没有,dp)

    题目链接:http://www.ifrog.cc/acm/problem/1146?contest=1020&no=2 题解:显然知道这是一道dp而且 dp[i]=min(dp[j]+2^(x ...

  2. Java IO写文件效率

    写入方法: /** *1 按字节写入 FileOutputStream * * @param count 写入循环次数 * @param str 写入字符串 */ public void output ...

  3. Servlet跳转方式sendReDirect()和forward()

    在web应用服务中,经常会面对不同SERVLET之间的跳转,目前我们可以通过以下两种方式实现: 1.RequestDispatcher.forward() 2.ServletResponse.send ...

  4. kubernetes部署jenkins(Docker in Docker)及认证

    引言 Jenkins是一款开源 CI&CD 软件,用于自动化各种任务,包括构建.测试和部署软件. 本文将Jenkins的master与slave置于Pod中,部署在namespace:jenk ...

  5. Winform中设置DevExpress的RadioGroup的items从配置文件中加载

    场景 DevExpress的RadioGroup的items选项如果是不确定的话,需要其从配置文件中加载. 实现 在项目目录下新建Config文件夹,文件夹下新建xml配置文件. <?xml v ...

  6. 【学习笔记】第三章 python3核心技术与实践--Jupyter Notebook

    可能你已经知道,Python 在 14 年后的“崛起”,得益于机器学习和数学统计应用的兴起.那为什么 Python 如此适合数学统计和机器学习呢?作为“老司机”的我可以肯定地告诉你,Jupyter N ...

  7. oracle 常用脚本以及语句

    oracle 常用脚本以及语句 一.oracle 安装10G 单机初始化环境: #!/bin/bash #关闭selinuxsed -i 's\SELINUX=enforcing\SELINUX=di ...

  8. Spring Boot + WebSocket 学习笔记

    首先需要了解一下背景,什么是WebSocket以及为什么要用WebSocket. 在常见的Web应用中,客户端与服务器通信,都是通过HTTP协议进行通信,客户端一次请求,服务端一次响应.而WebSoc ...

  9. java处理emoji(转)

    最近对接ios.安卓客户端,需要处理emoji等表情符号,网上总结: 1.过滤掉emoji表情符 2.修改数据库的编码格式等,让其支持存储emoji 以下分别对两种方案进行描述: 第一种:过滤掉emo ...

  10. 修改zabbix的端口号

    1.前言 zabbix-server的默认端口号是10051.如果存在端口号冲突,需要更改端口号. 以下为更改端口号的步骤. 2.更改配置文件  通常用安装包,也就是yum方式部署的话,其默认的配置文 ...