Tomcat源码运行,踩坑总结(tomcat源码编译)

前言

  • tomcat 在web开发中的地位举足轻重,本文就对tomcat8 进行源码运行,使用的os是 mac10,jdk8

准备工作

  1. tomcat源码下载地址: https://tomcat.apache.org/download-80.cgi
  2. idea工具: https://www.jetbrains.com/idea/download
  1. maven: http://maven.apache.org/download.cgi
  2. jdk 这里用8的版本

解压后的项目结构

Tomcat源码运行,踩坑总结(tomcat源码编译)

配置工作

1. 解压完后在本地建立catalina-home(文件名称自定义即可,路径也自定义即可,一些文章介绍的是固定名称和路径的,大可不必)

2. 将tomcat解压中的conf 和webapps复制一份到 第一步中的catalina-home中(这两步不配置也是可以运行起来的,只是自定义一些配置方便调试)

3. 在tomcat根目录下创建pom.xml(位置见上述项目结构,这个就不多做解释,J2EE maven管理包是日常操作了),pom中的配置如下:

此配置是报错调试了几次之后的结果,如果你用的不同版本可能会遇到不同的问题,所以为了降低学习成本,尽量同一环境配置

<?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.0</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 编译 版本  -->
          <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>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.0</version>
    </dependency>
    <dependency>
      <groupId>org.eclipse.jdt.core.compiler</groupId>
      <artifactId>ecj</artifactId>
      <version>4.6.1</version>
    </dependency>
    <dependency>
      <groupId>com.unboundid</groupId>
      <artifactId>unboundid-ldapsdk</artifactId>
      <version>3.2.0</version>
    </dependency>
    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.17</version>
    </dependency>

  </dependencies>
</project>

4. 到这里配置就差不多完成了,可以配置以下VM参数(路径根据自己前边的步骤来定)

-Dcatalina.home=/Users/user/project/study/catalina-home
-Dcatalina.base=/Users/user/project/study/catalina-home
-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager 
-Djava.util.logging.config.file=/Users/user/project/study/catalina-home/conf/logging.properties

5. 启动tomcat (tomcat启动入口在 org.apache.catalina.startup.Bootstrap#main)

5.1 问题1:启动乱码

Tomcat源码运行,踩坑总结(tomcat源码编译)

这个问题在网上看了很多解决方案,但是都没有生效,最终根据源码debug,发现两个地方出来的字符串是乱码的

  • org.apache.jasper.compiler.Localizer#getMessage(java.lang.String) 这里 errMsg是乱码的,这里自己加下转码代码如下:
public static String getMessage(String errCode) {
        String errMsg = errCode;
        try {
            if (bundle != null) {
                errMsg = bundle.getString(errCode);
                //这里自己转下编码
                try {
                    errMsg = new String(errMsg.getBytes("ISO-8859-1"), "UTF-8");
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
            }
        } catch (MissingResourceException e) {
        }
        return errMsg;
    }
  • 第二个地方: org.apache.tomcat.util.res.StringManager#getString(java.lang.String)
public String getString(String key) {
        if (key == null){
            String msg = "key may not have a null value";
            throw new IllegalArgumentException(msg);
        }

        String str = null;

        try {
            // Avoid NPE if bundle is null and treat it like an MRE
            if (bundle != null) {
                str = bundle.getString(key);
            }
        } catch (MissingResourceException mre) {
            //bad: shouldn't mask an exception the following way:
            //   str = "[cannot find message associated with key '" + key +
            //         "' due to " + mre + "]";
            //     because it hides the fact that the String was missing
            //     from the calling code.
            //good: could just throw the exception (or wrap it in another)
            //      but that would probably cause much havoc on existing
            //      code.
            //better: consistent with container pattern to
            //      simply return null.  Calling code can then do
            //      a null check.
            str = null;
        }
        //这里处理下编码问题
        try {
            str = new String(str.getBytes("ISO-8859-1"),"UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return str;
    }

PS:网上有很多人写的文章是org.apache.tomcat.util.res.StringManager类中的getString(final String key, final Object... args)方法 这里处理编码问题,这里其实不彻底,他底层调用的还是

org.apache.tomcat.util.res.StringManager#getString(java.lang.String),只是修复了其中一条路,其他case还是会乱码,当然tomcat修改配置文件可以解决这些问题,不过修改代码更直接快速

 

5.2 处理好这些后 重新运行tomcat并访问 http://localhost:8080

Tomcat源码运行,踩坑总结(tomcat源码编译)

这是因为tomcat启动的时候没有初始化jsp解析器,需要在 org.apache.catalina.startup.ContextConfig#configureStart 加入以下代码(该方法内必定会执行的任意行即可,比如第一行):

context.addServletContainerInitializer(new JasperInitializer(), null);

6. 修改完成后,重新运行tomcat并访问 http://localhost:8080

Tomcat源码运行,踩坑总结(tomcat源码编译)

为您推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注