在本机使用maven编译tomcat8的源码并运作
前提说明:
1. 基于tomcat 8.0.26版本的源码
2. JDK1.7
操作说明:
1. 从Apache网站下载tomcat源码
2. 默认情况下,tomcat使用ant进行编译、打包,以下讲一下如何使用maven来编译、打包
3. 在Eclipse里新建一个maven标准Java项目
4. 将tomcat源码包下的Java里的文件拷贝到src/main/java下
5. 将conf和webapps拷贝到项目根路径下(请参考下图)
6. 使用以下maven配置
<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.test</groupId> <artifactId>tomcat8</artifactId> <version>0.0.1-SNAPSHOT</version> <properties> <maven.build.timestamp.format>yyyyMMdd HH:mm:ss</maven.build.timestamp.format> <VERSION>8.0.26</VERSION> <VERSION_NUMBER>8.0.26</VERSION_NUMBER> <VERSION_BUILT>${maven.build.timestamp}</VERSION_BUILT> </properties> <build> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.xml</include> <include>**/*.properties</include> <include>**/*.dtd</include> <include>**/*.xsd</include> </includes> <filtering>true</filtering> </resource> <resource> <directory>src/main/resources</directory> </resource> </resources> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.7</source> <target>1.7</target> <encoding>UTF-8</encoding> </configuration> </plugin> <plugin> <artifactId>maven-resources-plugin</artifactId> <configuration> <delimiters> <delimiter>@</delimiter> </delimiters> </configuration> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.1.3</version> </dependency> <dependency> <groupId>avalon-framework</groupId> <artifactId>avalon-framework</artifactId> <version>4.1.5</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <dependency> <groupId>logkit</groupId> <artifactId>logkit</artifactId> <version>1.0.1</version> </dependency> <dependency> <groupId>servletapi</groupId> <artifactId>servletapi</artifactId> <version>2.3</version> </dependency> <dependency> <groupId>geronimo-spec</groupId> <artifactId>geronimo-spec-jaxrpc</artifactId> <version>1.1-rc4</version> </dependency> <dependency> <groupId>wsdl4j</groupId> <artifactId>wsdl4j</artifactId> <version>1.6.2</version> </dependency> <dependency> <groupId>org.eclipse.jdt.core.compiler</groupId> <artifactId>ecj</artifactId> <version>4.4.2</version> </dependency> <dependency> <groupId>commons-daemon</groupId> <artifactId>commons-daemon</artifactId> <version>1.0.15</version> </dependency> <dependency> <groupId>org.apache.ant</groupId> <artifactId>ant</artifactId> <version>1.9.6</version> </dependency> </dependencies> </project>
最终项目的文件结构如下图:
经过以上步骤之后,编译应该能够通过了,如果这个时候我们使用Bootstrap启动tomcat,也能正常启动,但在打开页面时,会报Validator的什么NullPointException,主要是因为JspFactory里的工厂类没有被实例化,所以getFactory总是返回null。
JspFactory的实现类是JspFactoryImpl,然后在JasperInitializer里会被调用,如果JasperInitializer能够被正常启动,那么JspFactory就不会返回Null了。
在ContextConfig的1128行,有加载所有ServletContainerInitializer的机会,这里会去加载META-INF/services下面的所有ServletContainerInitializer的实现类,所以需要在META-INF/services下新建一个文件javax.servlet.ServletContainerInitializer,然后里面的内容是org.apache.jasper.servlet.JasperInitializer,这样再启动之后,就能够正常访问页面了。
以上这点也是我比较疑惑的,我在tomcat的bin版本发行包里,没有看到哪个jar包里面有META-INF/services/javax.servlet.ServletContainerInitializer这个文件,但是tomcat却可以直接运行,但为什么使用源码编译时,就必须添加这个文件呢?以后有时间再细细研究一下。