SSI框架下同一个Bean加载了2次问题解决

SSI框架下同一个Bean加载了2次

问题:需要通过http请求读取开放平台的数据。但是由于某一条数据量太大,用户使用的时候需要等待的时间过长。所以想通过缓存来解决,但是线上的缓存每隔一段时间会清理一次。于是用定时器每隔一段时间去执行校验拉取的操作,如果缓存有相应的数据就不执行任何操作,如果缓存中没有相应的数据,那么就重新读取接口得到数据缓存。

public void init() {
	log.info("进入init方法");
	new Timer().schedule(new TimerTask() {

		@Override
		public void run() {
			log.info("定时器开始执行");
		}
	}, 0, 6 * 60 * 60 * 1000);
}

整个项目用的是SSI,在spring配置init-method,每次重启服务的时候执行定时器。这一切都执行的很顺利,并且在定时器中打了启动日志,以便观察它的启用情况。发现每次服务器重启的时候这个init方法都会执行2次。然后又在本地相同的代码跑了一遍发现在本地只执行了一次。于是上网查了一些资料。问题大概定位到是“ Spring(实例被构造两次)”,继续查找问题发现造成该现象主要有以下两个方面

  • applicationContext.xml在加载的时候会被DispatcherServlet和ContextLoaderListener加载两次。
  • Tomcat的server.xml配置文件的Host节点的属性 appBase='webapps'同时还配置了Context元素并且其docBase属性指向webapps下的该工程。这样子这个工程就会被加载2次。bean也就会被加载2次

关于第一个观点,查的资料作者用的是spring自带的quartz定时器。因为时间有限没有去实现。
(PS:web.xml配置下的ContextLoaderListener监听器。如果context-param不指定的话会去加载/WEB-INF/applicationContext.xml下的文件。
DispatcherServlet如果init-param不指定的话会自动加载[servlet-name]-servlet.xml。)

	<listener>  
	<listener-class>
		org.springframework.web.context.ContextLoaderListener
	</listener-class>  
	</listener> 
	<context-param>  
	<param-name>contextConfigLocation</param-name> 
	<param-value>/WEB-INF/classes/applicationContext.xml</param-value>  
	</context-param>   


	
	<servlet>  
    <servlet-name>[servlet-name]</servlet-name>  
    <servlet-class>org.springframework.web.servlet.DispatcherServlet
	</servlet-class>  
    <init-param>  
        <param-name>contextConfigLocation</param-name>  
        <param-value>classpath:servletContext.xml</param-value>  
    </init-param>  
    <load-on-startup>1</load-on-startup>  
	</servlet>  
	<servlet-mapping>  
    <servlet-name>spring</servlet-name>  
    <url-pattern>/*</url-pattern>  
	</servlet-mapping>

这里如果ContextLoaderListener和DispatcherServlet加载的配置文件都一样的话。那么可能这个init方法会被执行两次。

但是我去看了下我得web.xml的配置,这两个类加载的xml文件都有明确说明的。所以造成第一个观点是不是这个原因造成的。以后有时间一定要去证实一下。说到底这都是spring和struts源码上做的文章。

结论:Tomcat的server.xml配置文件appBase属性至为空。

原文地址:https://www.cnblogs.com/iMouseWu/p/4215372.html