我们正在部署一个IIS站点,包括几个文件夹、几个虚拟目录和一个Tomcat主机。
在Java 8上运行Tomcat 8(8.0.46)时,一切正常。在升级到JDK 9 (OpenJDK 64位服务器VM(构建9.0.4+11,混合模式))之后,我们注意到每个servlet都被初始化了几次(即init(ServletConfig)方法被执行了几次),第一次是在主机上下文中(如预期的那样),并为站点中的每个文件夹修改一次。
不希望的副作用是servlet创建的临时文件/日志在站点的每个文件夹中都是重复的。
Tomcat server.xml包含Host定义:
<Host name="localhost" appBase="C:/Program Files (x86)/b4/Controller/bin/webserver/ebsc_web"
unpackWARs="true" autoDeploy="true">
<Context path="/servlets" docBase="C:/Program Files (x86)/b4/Controller/bin/webserverebsc_web" xmlValidation="false" xmlNamespaceAware="false">
<WatchedResource>WEB-INF/web.xml</WatchedResource>
</Context>
<!--
<Valve className="org.apache.catalina.authenticator.SingleSignOn" />
-->
<!-- Access log processes all example.
Documentation at: /docs/config/valve.html
Note: The pattern used is equivalent to using pattern="common" -->
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
相同的位置(C:Program Files (x86)b4Controllerbinwebserverebsc_web)是Web站点的物理路径,并包含子文件夹,例如:applet、images等。启动Tomcat时,在默认位置(ebsc_web)创建日志,并在每个子文件夹中复制日志。
我们注意到当servlet在正确的servlet上下文中初始化时,堆栈是:
Daemon Thread [localhost-startStop-1] (Suspended (breakpoint at line 49 in UpdateSchedulerLoader))
owns: StandardWrapper (id=63)
owns: StandardContext (id=64)
UpdateSchedulerLoader.init(ServletConfig) line: 49
StandardWrapper.initServlet(Servlet) line: 1227
StandardWrapper.loadServlet() line: 1140
StandardWrapper.load() line: 1027
StandardContext.loadOnStartup(Container[]) line: 5038
StandardContext.startInternal() line: 5348
StandardContext(LifecycleBase).start() line: 145
ContainerBase$StartChild.call() line: 1408
ContainerBase$StartChild.call() line: 1398
FutureTask<V>.run() line: 264
ThreadPoolExecutor.runWorker(ThreadPoolExecutor$Worker) line: 1167
ThreadPoolExecutor$Worker.run() line: 641
Thread.run() line: 844
,但在以下任何时候,当它用指向子文件夹的servlet上下文初始化时,堆栈为:
Daemon Thread [localhost-startStop-1] (Suspended (breakpoint at line 42 in UpdateSchedulerLoader))
owns: StandardWrapper (id=154)
owns: StandardContext (id=144)
UpdateSchedulerLoader.init(ServletConfig) line: 42
StandardWrapper.initServlet(Servlet) line: 1227
StandardWrapper.loadServlet() line: 1140
StandardWrapper.load() line: 1027
StandardContext.loadOnStartup(Container[]) line: 5038
StandardContext.startInternal() line: 5348
StandardContext(LifecycleBase).start() line: 145
StandardHost(ContainerBase).addChildInternal(Container) line: 753
StandardHost(ContainerBase).addChild(Container) line: 729
StandardHost.addChild(Container) line: 717
HostConfig.deployDirectory(ContextName, File) line: 1129
HostConfig$DeployDirectory.run() line: 1871
Executors$RunnableAdapter<T>.call() line: 514
FutureTask<V>.run() line: 264
ThreadPoolExecutor.runWorker(ThreadPoolExecutor$Worker) line: 1167
ThreadPoolExecutor$Worker.run() line: 641
Thread.run() line: 844
所以servlet第一次由ContainerBase$StartChild.call()
初始化,后来由HostConfig.deployDirectory(ContextName, File)
初始化…
你能解释/修复这个行为吗?
根据@PiotrP的指示,问题解决了。在server.xml的Host configuration中设置两个autoDeploy="false" deployOnStartup="false"
。