Tomcat 配置导致启动时,项目加载两次的解决办法
现象:
Tomcat 在启动的时候,由于配置原因,导致工程会被加载两次,很容易出现内存溢出。如果有定时任务,也可能导致定时任务执行两次,从而出现问题。
原因:
在 tomcat/conf/server.xml 配置虚拟目录引起,如下配置:
<Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true">
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
pattern="%h %l %u %t "%r" %s %b"
prefix="localhost_access_log" suffix=".txt"/>
<Context docBase="solo" path="/" reloadable="true" />
</Host>
首先介绍下 appBase 与 docBase 的区别
- appBase 是指定虚拟主机的目录,可以指定绝对目录,也可以指定相对于 Tomcat 目录的相对目录,如果没有此项,默认为 webapps
- docBase 是指定 Web 应用的文件路径,可以给定绝对路径,也可以给定相对于 Host 的 appBase 属性的相对路径;如果 Web 应用采用开放目录结构,那就指定 Web 应用的根目录;如果 Web 应用是个 WAR 文件,那就指定 WAR 文件的路径
分析:
- 根据 Tomcat 规则,当为 Host 容器设置了 appBase 属性时,Tomcat 会在启动时自动加载 appBase 指定目录下的所有合法工程;
- 同时 Context 的 docBase 属性设置了 Tomcat 默认工程, 所以指定的 工程又会被加载一次;
- 根据 server.xml 配置,Tomcat 首先根据
的配置内容生成第一个 StandardContext 对象,加载一次项目。 - 然后,再根据 Host/appBase 的配置对 webapps 下面的项目生成第二个 StandardContext,再加载一次项目。
Tomcat 针对同一项目生成两个 StandardContext 的原因就是因为他们的名字不同,Tomcat 认为是两个 Context,所以加载了两次。
上面,我们在 Host 标签里配置了 appBase="webapps",Tomcat 加载了一次应用。同时, 在
解决方法:
方法一
直接把项目放到 webapps 下,指定 appBase="webapps",不指定
方法二
不把项目放入 webapps 下,在 Tomcat 目录下新建文件夹,如 Solo,去掉 appBase 设置(经测试,设置 appBase="",貌似也不行),然后配置
<Context docBase="D:/Tomcat/solo" path="" reloadable="true"/>
方法三
直接把项目目录放到 webapps 下,并修改项目名称为 ROOT,指定 appBase="webapps",不指定
结论,如果 Tomcat 仅加载了少数的项目,可以使用方法一、三。另外,方法二也存在弊端,即如果项目中的链接或者图片是绝对路径的话,那么带有项目名称的绝对路径是无法正常使用的。
参见:https://blog.csdn.net/mrliar17/article/details/80898914
https://segmentfault.com/a/1190000002985203