目录
3、Tomcat源码用Maven下载依赖,从而导入到Idea
4、Idea 编译报错,缺少类util.CookieFilter
5、默认Tomcat源码未配置JSP引擎,需要修改ContextConfig类,在webConfig();代码下添加如下代码。否则启动Tomcat 后,访问JSP页面报错。
1、下载Tomcat源码
源码地址:https://mirrors.bfsu.edu.cn/apache/tomcat/tomcat-8/v8.5.66/src/apache-tomcat-8.5.66-src.zip
二进制文件地址(Windows或Linux可直接运行):
https://mirrors.bfsu.edu.cn/apache/tomcat/tomcat-8/v8.5.66/bin/apache-tomcat-8.5.66-windows-x64.zip
为什么需要把二进制直接运行的也需要下载下来?不是直接使用源码就可以吗?
- Tomcat运行起来,必须要配置项目,如果没有看不到效果。Tomcat源码已经给我们提供了一些案例项目,就是Webapps目录下的应用项目。为了方便简单,这里直接采用Tomcat提供的案例
- 源码中的Webapps 目录下的这些项目都没有编译,需要我们自己编译,打开源码可以看到,classes目录下都是 ***.java 文件。如果把未编译的examples项目部署到Tomcat下是不能够正常启动这个项目的。Tomcat 源码之前的有些版本,可以直接使用源码下webapps下的案例,但是这个8.5.66版本,不能使用了,跟踪原因发现源码下的案例都是***.java文件,没有对应的***.class 文件。
- 下载二进制直接运行的Tomcat,在Webapps下的都有***.class 已编译的二进制文件,Tomcat可直接加载
- 如果未下载已编译二进制的Tomcat,就需要用Ant 在Tomcat源码下编译项目,编译输出的目录output/build/webapps 下的项目即可直接部署到Tomcat。
- Ant编译时,有个错误,这里记录一下
ant build时报错:
BUILD FAILED
/Volumes/work/works/projects/apache-tomcat-8.5.66-src/build.xml:780: The following error occurred while executing this line:
/Volumes/work/works/projects/apache-tomcat-8.5.66-src/build.xml:3384: Failed to parse date string 06/06/2021 12:51:22 下午.
这个错误是Ant编译打包时,把当前打包日期写入到jar 包时,字符串格式转换错误。应该是使用的Apache Ant 编译版本有冲突导致的,这里使用的Ant版本是1.10.10。由于对于Ant不是太熟,这里直接把build.xml 文件下的tstamp.file 属性直接改成 123即可(任意字符串即可)。注意,modules/jdbc-pool/build.xml也需要修改。
<!--<format property="tstamp.file" pattern="MM/dd/yyyy hh:mm:ss aa"/>-->
<format property="tstamp.file" pattern="123"/>
2、配置catalina.home目录
在Tomcat源码目录下创建"catalina-home"目录,把Tomcat 二进制目录下的conf/lib/webapps 3个目录拷贝到"catalina-home"目录下
tomcat 源码目录如下所示:
3、Tomcat源码用Maven下载依赖,从而导入到Idea
在Tomcat目录下创建 pom.xml pom文件,用来Maven下载Tomcat需要的依赖:
<?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>Tomcat8.5</artifactId>
<name>Tomcat8.5</name>
<version>8.5</version>
<build>
<finalName>Tomcat8.5</finalName>
<!-- 指定源文件为java 、test -->
<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>2.3</version>
<configuration>
<encoding>UTF-8</encoding>
<!-- 指定jdk 编译 版本 ,没装jdk 1.7的可以变更为1.6 -->
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
<!-- 添加tomcat8 所需jar包依赖 -->
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.unboundid</groupId>
<artifactId>unboundid-ldapsdk</artifactId>
<version>5.1.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ant</groupId>
<artifactId>ant</artifactId>
<version>1.7.0</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.easymock</groupId>
<artifactId>easymock</artifactId>
<version>4.2</version>
</dependency>
<dependency>
<groupId>org.eclipse.jdt.core.compiler</groupId>
<artifactId>ecj</artifactId>
<version>4.6.1</version>
</dependency>
</dependencies>
</project>
直接用Idea打开当前项目即可,Idea会自动下载依赖,代依赖下载完成后,即可配置Idea,启动Tomcat。
4、Idea 编译报错,缺少类util.CookieFilter
Idea编译时会报异常,缺少类,这个类在GitHub上找到,这里粘贴在这里。把类添加到
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package util;
import java.util.Locale;
import java.util.StringTokenizer;
/**
* Processes a cookie header and attempts to obfuscate any cookie values that
* represent session IDs from other web applications. Since session cookie names
* are configurable, as are session ID lengths, this filter is not expected to
* be 100% effective.
*
* It is required that the examples web application is removed in security
* conscious environments as documented in the Security How-To. This filter is
* intended to reduce the impact of failing to follow that advice. A failure by
* this filter to obfuscate a session ID or similar value is not a security
* vulnerability. In such instances the vulnerability is the failure to remove
* the examples web application.
*/
public class CookieFilter {
private static final String OBFUSCATED = "[obfuscated]";
private CookieFilter() {
// Hide default constructor
}
public static String filter(String cookieHeader, String sessionId) {
StringBuilder sb = new StringBuilder(cookieHeader.length());
// Cookie name value pairs are ';' separated.
// Session IDs don't use ; in the value so don't worry about quoted
// values that contain ;
StringTokenizer st = new StringTokenizer(cookieHeader, ";");
boolean first = true;
while (st.hasMoreTokens()) {
if (first) {
first = false;
} else {
sb.append(';');
}
sb.append(filterNameValuePair(st.nextToken(), sessionId));
}
return sb.toString();
}
private static String filterNameValuePair(String input, String sessionId) {
int i = input.indexOf('=');
if (i == -1) {
return input;
}
String name = input.substring(0, i);
String value = input.substring(i + 1, input.length());
return name + "=" + filter(name, value, sessionId);
}
public static String filter(String cookieName, String cookieValue, String sessionId) {
if (cookieName.toLowerCase(Locale.ENGLISH).contains("jsessionid") &&
(sessionId == null || !cookieValue.contains(sessionId))) {
cookieValue = OBFUSCATED;
}
return cookieValue;
}
}
5、默认Tomcat源码为配置JSP引擎,需要修改ContextConfig类,在webConfig();代码下添加如下代码。否则启动Tomcat 后,访问JSP页面报错。
webConfig();
//启动后访问tomcat页面,包错 org.apache.jasper.JasperException: 无法为JSP编译类;
//没有JSP 解析问题,添加如下代码即可
context.addServletContainerInitializer(new JasperInitializer(),null);
6、配置Idea,Tomcat启动类
在Run/Debug Configurations 配置Application 启动类配置。
Main class:org.apache.catalina.startup.Bootstrap
VM options :-Dcatalina.home=catalina-home
配置完成后,可直接点击调试按钮,启动Tomcat了,控制台如下打印时,说明启动成功。
7、浏览器打开Tomcat 主页面
浏览器访问如下地址即可:http://localhost:8080
至此,Tomcat 8.5.66 源码已经用Idea成功编译并运行,后续会在此基础上讲解Tomcat源码相关信息。