一般来说对于开源软件都有自己的官方网站,并且会附上使用文档以及一些特性和二次构建的方法,那么我们首先的话需要从官网或者tomcat上下载到我们需要的源码包。下载地址:官网、Github。
这里需要声明一下,我们是通过源码来进行编译的,所以我们需要下载src下的源码包,然后才能进行构建,而对于bin包下的是官网已经构建好的软件。
因为tomcat是JAVA语言编写的,所以在这里默认我们已经有了JAVA环境,然后我们直接进行安装ant。安装地址
因为在tomcat的官方网站上,明确的指出官方所支持的构建方式是ant构建,所以我们在这采用ant的方式来构建环境。
然后我们需要像安装JDK一样来进行配置环境变量,创建环境变量ANT_HOME=解压路径的根路径,再向PATH中添加%ANT_HOME%\bin,在控制台输入ant -version,观察到ANT的版本后就说明ant已经安装成功。
我们首先需要配置一下构建的一些配置文件,先新建build.properties文件在主目录,并输入下面的几行配置。
#依赖下载的位置
base.path=D:\\Programe\\apache-tomcat-9.0.68-src\\dependency
#代理
proxy.host=127.0.0.1
proxy.port=7890
#是否使用代理
proxy.use=on
在执行构建的过程中,我们需要下载依赖包,所以会比较的缓慢。
我们直接在tomcat的主目录执行 ant 这个命令。然后就可以开启构建的流程了。
在看到上述的图片后就说明我们已经构建完成,到这里或许你会有疑问,为什么我们要构建一个tomcat,直接使用官方的不好吗。其实对于我们来说tomcat在使用的过程中更像是一个黑盒的容器,我们不知道它的内部具体实现,一般也只是在使用。构建tomcat能够帮助我们来二次开发和构建适合我们自己业务的软件,也可以让我们自己写的代码打入tomcat容器中。
上述的话便是官方方式推荐的构建tomcat,而我们的学习需要在编译器中把tomcat给跑起来,然后方便我们调试和学习,下来我们将进行IDEA版本的构建。
众所周知Tomcat实际上是一个JAVA的项目,而对于JAVA项目来说我们可以通过maven的方式来构建一个具有很方便的依赖管理方式的项目,就不再需要我们去下载依赖,而是直接通过maven仓库的方式进行管理,有效的规范了我们的依赖存放方式。
首先,我们需要将tomcat的源码通过IDEA打开,然后我们在根目录中进行新建一个pom.xml,并把此项目标记为maven项目。
<?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.0</artifactId>
<name>Tomcat8.0</name>
<version>8.0</version>
<build>
<finalName>Tomcat8.0</finalName>
<!--声明JAVA源代码路径-->
<sourceDirectory>java</sourceDirectory>
<!--声明JAVA测试代码路径-->
<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.5.1</version>
<configuration>
<encoding>UTF-8</encoding>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<!--单元测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!--mock对象-->
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<version>3.4</version>
</dependency>
<!--构建工具-->
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant</artifactId>
<version>1.10.14</version>
</dependency>
<!--解析WSDL文本的常用工具-->
<dependency>
<groupId>wsdl4j</groupId>
<artifactId>wsdl4j</artifactId>
<version>1.6.3</version>
</dependency>
<!--Java Web服务开发包(WSDP)的应用程序接口(API)-->
<dependency>
<groupId>javax.xml</groupId>
<artifactId>jaxrpc</artifactId>
<version>1.1</version>
</dependency>
<!--JavaTM 认可的Java 编译工具-->
<dependency>
<groupId>org.eclipse.jdt.core.compiler</groupId>
<artifactId>ecj</artifactId>
<version>4.6.1</version>
</dependency>
<dependency>
<groupId>biz.aQute.bnd</groupId>
<artifactId>biz.aQute.bndlib</artifactId>
<version>6.3.1</version>
</dependency>
</dependencies>
</project>
我们点击add as maven project
,并刷新依赖关系,等待具体的依赖包下载完毕后就可以了。
我们一般的启动方式是通过tomcat的bin目录下的start.bat或者是start.sh来进行启动,那么我们心中是否会有这样一个疑问?tomcat是否是有main函数的。这个回答是当然,对于JAVA程序来说main函数是方法执行的入口,如果没有入口函数,那么tomcat容器就不可能会进行启动,接下来我们就来通过启动脚本来探索一下tomcat启动的具体步骤。
setlocal
set "CURRENT_DIR=%cd%"
if not "%CATALINA_HOME%" == "" goto gotHome
set "CATALINA_HOME=%CURRENT_DIR%"
if exist "%CATALINA_HOME%\bin\catalina.bat" goto okHome
cd ..
set "CATALINA_HOME=%cd%"
cd "%CURRENT_DIR%"
:gotHome
if exist "%CATALINA_HOME%\bin\catalina.bat" goto okHome
echo The CATALINA_HOME environment variable is not defined correctly
echo This environment variable is needed to run this program
goto end
:okHome
set "EXECUTABLE=%CATALINA_HOME%\bin\catalina.bat"
rem Check that target executable exists
if exist "%EXECUTABLE%" goto okExec
echo Cannot find "%EXECUTABLE%"
echo This file is needed to run this program
goto end
:okExec
rem Get remaining unshifted command line arguments and save them in the
set CMD_LINE_ARGS=
:setArgs
if ""%1""=="""" goto doneSetArgs
set CMD_LINE_ARGS=%CMD_LINE_ARGS% %1
shift
goto setArgs
:doneSetArgs
call "%EXECUTABLE%" start %CMD_LINE_ARGS%
:end
主要的就是找到catalina.bat,然后调用这个批处理命令,我们继续来看catalina.bat,这里就不进行贴出代码了,主要讲一下逻辑。
catalina.bat设置了几个环境变量,CATALINA_HOME和CATALINA_BASE,获取了安装的JAVA虚拟机的路径和参数,设置了日志文件的配置。
在这里面我们可以看到所指定的MAINCLASS,然后这个文件就是我们启动的main函数的所在类。
这样我们就知道了,在启动主类的时候我们要向虚拟机指定一些环境变量,不然的话导致main函数中的部分代码找不到资源文件,这里我们只指定必要的几个变量。
-Dcatalina.home=D:\apache-tomcat-9.0.68-src\apache-tomcat-9.0.68-src
-Dcatalina.base=D:\apache-tomcat-9.0.68-src\apache-tomcat-9.0.68-src
-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
-Djava.util.logging.config.file=D:\apache-tomcat-9.0.68-src\apache-tomcat-9.0.68-src\conf\logging.properties
我们来在IDEA里面新添加一个应用配置
选择主类为我们刚才找到的Bootstrap.java文件,并将上述的几个参数添加进虚拟机的运行时的参数列表。(这里请注意不是项目参数是虚拟机参数)
最后我们来进行启动项目。
这里可能会遇到编译错误,我们只需要将JDT的所有爆红的改为自己的版本即可,例如我是CompilerOptions.VERSION_1_8。
我们发现启动成功了,但是会有乱码的问题。
在我们自己安装的时候我们是通过配置文件解决的乱码,就是将所有的编码方式设置为GBK实现的,在这里呢我们来通过修改代码来实现。
修改org.apache.tomcat.util.res#getString(final String key, final Object… args)
try {
value = new String(value.getBytes("ISO-8859-1"), "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
修改org.apache.jasper.compiler.Localizer#getMessage()
try {
if (bundle != null) {
errMsg = bundle.getString(errCode);
}
errMsg = new String(errMsg.getBytes("ISO-8859-1"), "UTF-8");
} catch (MissingResourceException | UnsupportedEncodingException e) {
}
然后我们再进行启动,就可以看到如下图的启动结果。
然后我们来进行访问我们我们熟悉的8080端口。
发生了空指针异常,这是因为我们没有添加jsp的解析类,导致了解析jsp时出现了异常,我们需要在ContextConfig.java中载入jsp的解析类。
最终
我们再进行启动就可以获得我们的主页了。
今天我们通过了官网和编译器的方式构建了tomcat环境,之后我们可以很方便的对于我们自己的tomcat进行调试开发,然后通过官网的方式进行构建我们自己的二次开发的tomcat容器。
技术无难事,只是走的人少便成了难事,让我们共同学习,一起进步。