报错内容:
Invocation of init method failed; nested exception is java.lang.IllegalStateException: Task already scheduled or cancelled
同样的一段定时任务的配置,放在不同的配置文件中效果却不同,配置文件内容如下:
<bean class="org.springframework.scheduling.timer.TimerFactoryBean">
<property name="scheduledTimerTasks">
<list>
<ref bean="orderTask" />
<ref bean="wuYeFeiTask"/>
</list>
</property>
</bean>
<bean id="orderTask" class="org.springframework.scheduling.timer.ScheduledTimerTask">
<property name="timerTask" ref="orderInfoDetailTask" />
<property name="delay" value="0"></property>
<property name="period" value="7200000"></property>
</bean>
测试一开始,我将这段配置放在servlet-config.xml文件中,报了上面的错误。但是当我把同样的一段配置放在了另外一个配置文件:task-config.xml文件中,却没有报错。感觉非常诡异,决定要排查一下原因。
首先报出的异常是什么意思:一个TimerTask 通过schedule方法使用之后,不能通过schedule方法调用第二次,想重复使用是不行的,是一次性用品。(网上拷贝,不能确定,但是从现在报错的情况看是有一定道理的)
从对异常的理解看,问题的原因可能是:同一个定时任务实例被两次定时,顺着这个路线查找问题。最终发现,在web.xml配置文件中有这样一段配置:
<!-- 启动SpringMVC-->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:servlet-config.xml;</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- 加载Spring的配置文件-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:*-config.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
这样就造成了-config.xml文件被web服务器加载了两次,那么就会出现上面的异常了。
为了验证问题,做了下面的测试,将servlet-config.xml文件名改成非-config.xml结尾的文件名。定时器顺利启动,没有报错。
问题成功解决。