学习Java Web,学到将WAR包部署到Tomcat中时,遇到一个问题。

部署WAR包的过程本身没什么问题,把.war文件放在<Tomcat安装目录>/webapps/中,然后修改<Tomcat安装目录>/conf/server.xml,过程很顺利。因为是部署多个WebApp,每个WebApp都是基于根路径开发的,所以就在<Host name="localhost">后面增加了几个<Host>

<Host name="localhost" ……>
  ……
</Host>

<
Host name="my-web-app.com" appBase="webapps" unpackWARs="true" autoDeploy="true"> <Context docBase="my-web-app" path="/" /> </Host>

……

通过startup.bat启动Tomcat,部署的WebApp都能正常访问。

但是,再回到IDEA中(自己手动启动的Tomcat进程已关闭),通过IDEA启动Tomcat就报错了,关键日志如下:

……
Caused by: java.lang.IllegalArgumentException: 指定的主资源集 [C:\Users\tianlin\AppData\Local\JetBrains\IntelliJIdea2021.2\tomcat\643078ef-a97d-4f46-a4c3-5a50080f0431\webapps\my-web-app] 无效
……

可见,虽然我只想关注localhost主机的WebApp(即IDEA中正在开发的项目),但我在Tomcat安装目录中部署的这个my-web-app也存在于IDEA启动的这个Tomcat进程的配置之中,而且正是因为新增的<Host>导致了Tomcat无法启动。

经过一番研究,在搞清楚IDEA是如何控制Tomcat的基本原理之后,原因就很明了了:

因为IDEA使用的是临时配置目录,而这个my-web-app配置时使用的是相对路径,这就导致IDEA启动时,在临时配置目录下找不到my-web-app,所以就报错,无法启动。

解决方案:

  • 部署时<Host>使用绝对路径。这种方案下,在IDEA中运行Tomcat时,除了localhost之外的其他Host也都能正常访问到。
    <Host name="my-web-app.com" appBase="C:\Users\tianlin\Java\apache-tomcat-8.5.70\webapps\my-web-app" unpackWARs="true" autoDeploy="true">
        <Context docBase="/" path="" />
    </Host>
  • 部署用的Tomcat环境和IDEA开发用的Tomcat环境分离,各自使用不同的目录。