java - tomcat config 导致 2 个 @Service 副本运行
问题描述
我有一个ScheduledExecutor
运行在@PostConstruct
我的一些@Service
. 但是,这个 tomcat 配置会导致 2 个副本@Service
运行,删除任何一个都会导致@Controller
in the wars 无法正常工作。
如何解决这个问题?我需要@Service
成为单身人士,以便只有一个Executor
运行一些代码。
设置Executor
tostatic
只会使它成为一个Executor
,但是有没有办法在配置级别实现这一点?
web.xml
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/classes/applicationContext.xml</param-value>
</context-param>
<servlet>
<servlet-name>servlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
</servlet>
servlet-context.xml
<import resource="applicationContext.xml" />
应用程序上下文.xml
<bean id="properties" class="my.package.common.properties.MyPropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>WEB-INF/classes/system.properties</value>
<value>WEB-INF/classes/db.properties</value>
<value>WEB-INF/classes/applicationContext.properties</value>
</list>
</property>
</bean>
<context:annotation-config />
<context:component-scan base-package="my.package" />
解决方案
该问题很可能与您的以下导入有关servlet-context.xml
:
<import resource="applicationContext.xml" />
可能在您的web.xml
文件中包含以下 Web 应用程序上下文侦听器:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
在典型的 Spring MVC 应用程序中,此侦听器负责根据 Web 应用程序上下文参数中指示的 XML 文件中提供的信息初始化 Spring根应用contextConfigLocation
程序上下文:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/classes/applicationContext.xml</param-value>
</context-param>
另一方面,您在配置 Spring 时启动了第二个子应用程序上下文DispatcherServlet
:
<servlet>
<servlet-name>servlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
</servlet>
在您的示例中,第二个上下文基于servlet-context.xml
.
理解这两个上下文以这样一种方式相关非常重要,即根应用程序上下文中定义的所有 bean 都可以被与其关联的子上下文访问DispatcherServlet
(反之则不然)。
这允许您为 bean 组织和提供正确的层次结构:例如,根应用程序上下文通常定义服务和公共组件和配置(数据库、安全性、异步支持、缓存等),而子上下文定义与 MVC 相关的 bean东西。
Spring 文档中很好地解释了这种上下文层次结构:
import
正如您所说,当您在文件中包含以下内容时servlet-context.xml
:
<import resource="applicationContext.xml" />
您实际上是在复制根上下文中定义的所有内容。
要解决此问题,请从servlet-context.xml
.
根据您的评论,您的所有控制器都报告了错误404
。可能原因是删除applicationContext.xml
Spring 后无法找到任何Controller
s: 请确保您也包含component-scan
在servlet-context.xml
其中,指向定义控制器的包。其中servlet-context.xml
包括:
<context:component-scan base-package="my.package.controllers" />`
以这种方式包含在servlet-context.xml
您需要的任何其他 MVC 资源中(查看解析器等)。
理想情况下,applicationContext.xml
只需要扫描服务、存储库和类似内容等组件。
推荐阅读
- react-native - 从抽屉导航反应原生“requireNativeComponent”
- angular - 如何在数组上找到最小值、最大值以及如何使用角度更改最小绿色和最大红色的颜色文本
- pandas - 使用 loc() 加速 pandas 多行分配
- c# - 检测自动化对等方何时附加侦听器的更好方法?
- api - 不遵守有限制的卡车路线
- css - CSS - 如何从角落创建颜色过渡?
- c# - 调用 OnPostPrint,第 1 次,第 3 次调用我得到默认日期 0001-01-01 00:00,第 2 次,第 4 次调用我得到真实日期,例如 2021-10-14 12:28
- python - 检查字符串是否包含字典python中的单词
- ios - 打印:条目,“:CFBundleIdentifier”,不存在 - 反应原生
- c++ - C++ 硬件破坏性和建设性干扰大小如何与强制声明顺序一起使用?