问题
在初学 J2EE 的时候,我们会将 web 项目打包为一个 war 包,然后放到 tomcat 安装目录的 webapps 下,接着 tomcat 就会自动解压文件然后将项目启动起来了。
但是用了 IDEA 以后发现只需要将启动方式配置为 Tomcat-Server 的 local 启动,然后就可以在 IDEA 直接将项目启动起来了。但是之前也只是好奇,但是并没有去探究到底是怎么实现的。
这边文章就算是为之前的好奇填坑吧。
Tomcat 部署应用的三种方式
- 通过文件配置
- conf/server.xml文件中的Context标签
- conf/[enginename]/[hostname]/目录下以应用命名的xml文件
- 应用自己的/META-INF/context.xml文件
- conf/context.xml文件
- conf/[enginename]/[hostname]/context.xml.default文件
- 将 WAR 应用直接放到 Host(默认为 webapps) 目录下。
- 将应用到文件夹放到 Host(默认为 webapps) 目录下。
我们熟悉的方式是第 2 种。
IDEA 部署 web 应用的原理探究
- 首先我们需要准备一个最简单的 web 项目(项目名称为 test-web)
- 通过 IDEA 启动起来(由于只是探究原理,所以如何配置的这里就不再描述了)
启动起来后,我们就找到 tomcat 的安装目录挨着挨着验证,IDEA 选用的是哪种部署方式。
IDEA 启动的 Tomcat 如何找到当前应用
通过在 tomcat 的安装目录下查看,发现只有 conf/server.xml
和 conf/context.xml
,并且通过查询这两个文件,其中并没有我们所期望的内容。在这个时候其实已经陷入了死胡同,但是在观察 IDEA 控制台打印的启动日志时候发现一个关键信息。
...
CATALINA_BASE: /Users/xxx/Library/Caches/JetBrains/IntelliJIdea2020.3/tomcat/0c289466-0629-42c6-9adb-fc6bdfaaa238
CATALINA_HOME: /Users/xxx/Development/apache-tomcat-9.0.44
...
这里打印了一个 CATALINA_BASE
,后面好像有一个路径,然后我就找到了这个目录。结果居然发现这个文件夹居然和 Tomcat 安装目录结构类似。并且我们找到了想要找的文件 —— test-web.xml。
文件中的 docBase
也确实指向了 IDEA 编译输出的路径。
<!-- conf/Catalina/localhost/test-web.xml -->
<Context path="/test-web" docBase="/Users/xxx/IdeaProjects/test/test-web/out/artifacts/test_web_Web_exploded" />
到这里我们至少知道了 Tomcat 是如何找到项目,然后部署启动的。但是 Tomcat 启动程序是如何找到的 IDEA 创建的工作环境的呢。
Tomcat 是如何找到 IDEA 创建的工作环境
通过前面的启动日志信息,我们联想到了 CATALINA_BASE
,如果我们能知道这个值 Tomcat 是如何得到的,那么一切的疑惑就能解开了。
我将目标放到了 Tomcat 的启动程序,启动程序中应该会有关键信息。果然在注释中找到了它,在 catalina.sh
中提到 CATALINA_BASE
是从环境变量中获取的,如果没有的话则和 CATALINA_HOME
一致。
# [-z "$CATALINA_BASE" ] 如果取环境变量中的 CATALINA_BASE 长度为 0 则为 true,执行后面的步骤,设置 CATALINA_BASE 和 CATALINA_HOME 一致。
[ -z "$CATALINA_BASE" ] && CATALINA_BASE="$CATALINA_HOME"
既然知道了启动程序会先从当前系统环境中查询 CATALINA_BASE
的值,首先是查看对应的文件中是否有配置(由于不同的操作系统不同,所以这里就不粘贴出来了),结果发现并没有,那么就猜测应该是设置的临时环境变量。
由于是临时的,所以是控制台之间项目隔离的,就算同时启动多个应用也不会有影响,控制台关闭了也没有关系。
那么如果让我们来模拟 IDEA 来启动项目的话,只需要在控制台中执行两个指令就能完成如下效果。(前提条件是先用 IDEA 把对应的文件目录生成好)
Mac OS
export CATALINA_BASE=/Users/xxx/Library/Caches/JetBrains/IntelliJIdea2020.3/tomcat/0c289466-0629-42c6-9adb-fc6bdfaaa238
/Users/xxx/Development/apache-tomcat-9.0.44/bin/catalina.sh run
注:如果是 windows 系统添加临时的环境变量需要将 export
变为 set
。并且通过 catalina.bat
启动。
结论:
- 编译项目到指定文件中。
- IDEA 首先会创建一个全新的 Tomcat 工作空间(每个工程一个,如果有就不用再次创建)。
- 创建
conf/[enginename]/[hostname]/目录下以应用命名的xml文件
在其中设置编译输出的文件路径。 - 设置临时的环境变量让 Tomcat 启动程序找到这个工作空间。
- 启动 Tomcat 就能成功部署我们的应用了。