Spring容器被被多次初始化问题排查解决方案(转载)

问题描述
项目中使用quartz创建了一个定时任务,在系统启动后立即执行,我发现项目在启动过程中,会执行4次这个定时任务,也就是说项目被初始化了4次,这样会导致与任务相关的点出问题
最初我是现从精简Spring与SpringMVC的配置开始入手解决这个问题的,精简完成后由初始化4次降为了两次,后来又通过配置tomcat将初始化两次降为一次,至此解决了这个问题,下面就来详细讲一下这两步!
第一步:精简配置项
项目本身Spring与SpringMVC的配置文件是写在一起的, 在web.xml中配置为

<!-- 
	加载Spring应用上下文
	ContextLoaderListener加载应用中的bean,这些bean通常是驱动应用程序后端的中间层和数据层组件
 -->
<listener>
	<!-- Servlet监听器 -->
	<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
	<param-name>contextConfigLocation</param-name>
	<param-value>
		classpath*:/spring/applicationContext.xml
	</param-value>
</context-param>

<!-- 
	创建SpringMVC应用上下文
	DispatcherServlet加载包含Web组件的bean,如控制器、视图解析器以及处理器映射
-->
<servlet>
	<servlet-name>SpringMVC</servlet-name>
	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
	<!-- 指定SpringMVC配置文件加载地址 -->
	<init-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:/spring/applicationContext.xml</param-value>
	</init-param>
	<load-on-startup>1</load-on-startup>
	<!-- <async-supported>true</async-supported> -->
</servlet>
<servlet-mapping>
	<servlet-name>SpringMVC</servlet-name>
	<url-pattern>*.shtml</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>SpringMVC</servlet-name>
    <url-pattern>/dwr/*</url-pattern>
</servlet-mapping>

这样会有一个问题,会导致applicationContext.xml中配置的bean和被扫描到的注解类,都会被ContextLoaderListener与DispatcherServlet重复加载,这里是第一个问题点。
随后我将配置文件拆分为两个,applicationContext.xml与applicationContext-mvc.xml,我希望ContextLoaderListener与DispatcherServlet加载各自的上下文
第二步:配置tomcat
在tomcat中配置的Host与其子元素Context元素中的两个属性
的冲突配置会导致了应用程序重复加载

  <!-- 
  		Host代表虚拟主机,在同一个Engine中可以有多个Host,
  		Host元素主要属性
  			appBase : 指定虚拟主机的目录,可以指定绝对路径,也可以指定CATALINA_HOME的相对目录,
  				没有设置默认值为CATALINA_HOME/webapps
  			autoDeploy : 如果此项设置为true,标识当Tomcat服务器处于运行阶段,能够检测appBase下的文件,
  				如果有新的Web应用加入进来,则会自动发布这个Web应用
  			name : 指定虚拟主机的名称
  			unpackWARs :如果此项设为true,则表示把appBase属性指定目录下的web应用的WAR文件先展开为开放结构后再运行,
  				如果设为false,则直接运行WAR文件
   -->
  <Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true">
       <!-- 
		Context 元素代表了运行在虚拟主机<Host> 上的单个Web应用
		在Host中可以有多个Context元素
		主要属性:
			path : 指定访问该应用程序的URL入口
			docBase : 指定Web应用程序的文件路径,可以给定绝对路径,也可以给定相对于<Host>的appBase属性的相对路径
				如果Web应用采用开放目录机构,则指定Web应用的根目录;如果Web应用是个WAR文件,则指定WAR的文件路径
			reloadable : 属性默认为false,如果为true的话,Tomcat服务器会在运行状态下监视 WEB-INF/classes 和 WEB-INF/lib目录下的classes文件的改动,以及监视
					web应用的WEB-INF/web.xml文件的改动,如果检测到以上文件被改动,则服务器会自动重新加载WEB应用。在web应用开发调试阶段,把reloadable设为
					true,可以方便对web应用程序的调试,在web应用正式发布阶段,把reloadable设为false,可以降低tomcat的运行负荷
					提高tomcat的运行性能
			className : 
		标准Context组件的专有属性
			cachingAllowed :
			cacheMaxSize : 
			workDir : 
			uppackWar : 
	 -->
  	<Context docBase="pl" path="/pl" reloadable="true" source="org.eclipse.jst.jee.server:pl_web_20180807"/>
  </Host>

在Tomcat加载时会将Host元素的appbase属性配置的路径下所有应用程序启动,然后再启动Context元素的docBase属性配置的路径下的应用程序。
如果你Context元素的docBase属性配置的路径下的应用程序,同在Host元素的appbase属性配置的路径下,那么就会被启动两次,这是第二个问题点。
我是因为两个路径配置重叠了所以导致了启动了两次,所以我将Context元素docBase置为了空

完结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值