引发原因:定时器被启动了两次,重启了两个定时器线程(spring中timer定时器;quartz定时器);
第一次:web容器启动的时候,读取applicationContext.xml文件时,会加载一次。
第二次:Spring本身会加载applicationContext.xml一次。
根源定时器配置与其它spring配置全部写在applicationContext.xml文件里.
遗留问题:
web容器读取spring配置文件时是如何进行第一次加载定时器的?
解决方案:
1,通过程序设置标志变量方式改变,此种方式不建议,从根本上不能解决问题,不作介绍
2,将定时器配置从spring主配置文件中分离,进行分次加载定时功能只由web容器加载;
配置文件样例如下(spring用的是3.0,quartz用的是2.0):
web.xml配置文件主要涉及部分
<context-param> <param-name>contextConfigLocation</param-name> <!--spring主配置文件--> <param-value>classpath:springConf/applicationContext.xml, <!--Quartz定时器配置文件使用quartz时配置--> classpath:springConf/timerQuartz-Context.xml, <!--timer定时器配置文件使用spring timer时配置--> classpath:springConf/timertask-Context.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <servlet> <display-name>springDispacher</display-name> <servlet-name>springDispacher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springConf/applicationContext.xml</param-value> </init-param> <load-on-startup>0</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springDispacher</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping>
主spring配置文件中说明applicationContext.xml:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <import resource="datasource-Context.xml" /> <import resource="user-Context.xml" /> <import resource="app-Context.xml" /> <!--如果将定时器配置在这里或直接import进这里就会导致启动两次--> <!--<import resource="timertask-Context.xml"/> --> <!--<import resource="timerQuartz-Context.xml"/> --> </beans>
顺利也复习一下定时器如何配置:
spring中timer定时器的配置方法timertask-Context.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <!--定时器任务的主类--> <bean id="timerTask" class="business.timertask.action.TimerTaskAction"> <property name="taskService" ref="taskService"></property> </bean> <!--aop事物配置 --> <bean id="taskServiceAop" parent="serviceAop"> <property name="target" ref="taskService"></property> </bean> <!--任务处理的业务类--> <bean id="taskService" class="business.timertask.services.IMPTaskService"> <property name="taskDao" ref="taskDao"></property> </bean> <!--任务处理的dao类 --> <bean id="taskDao" class="business.timertask.dao.IMPTaskDAO"> <property name="dataSource" ref="dataSource"></property> <property name="sqlMapClient" ref="sqlMapClient"></property> </bean> <!-- 启动定时器 --> <bean id="start" class="org.springframework.scheduling.timer.TimerFactoryBean"> <property name="scheduledTimerTasks"> <list> <ref bean="scheduledTask" /> </list> </property> </bean> <!--定时器启动参数配置--> <bean id="scheduledTask" class="org.springframework.scheduling.timer.ScheduledTimerTask"> <!--延迟2秒执行 --> <property name="delay"> <value>2000</value> </property> <!--每3百秒执行一次 --> <property name="period"> <value>300000</value> </property> <property name="timerTask" ref="timerTask"></property> </bean> </beans>
quartz定时器配置方法:timerQuartz-Context.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <!--调度工厂配置 --> <bean id="schedulerFactory" class="org.quartz.impl.StdSchedulerFactory"> </bean> <!--定时表达式 --> <bean id="cronExc" class="org.quartz.CronExpression"> <constructor-arg> <value>0/5 * * * * ?</value> </constructor-arg> </bean> <!--表达式的触发器配置 --> <bean id="cronTrigger" class="org.quartz.impl.triggers.CronTriggerImpl"> <!--触发器名 --> <property name="name" value="cronTrigger" /> <!--触发器组 --> <property name="group" value="cronTriggerGroup" /> <!--触发器执行参数,每5秒一次 --> <property name="cronExpression"> <value>0/5 * * * * ?</value> </property> </bean> <!--自定义任务类job --> <bean id="customJob" class="business.timerTaskForQuatz.bean.CustomJob"> </bean> <!--jobDetail类 --> <bean id="jobDetail" class="org.quartz.impl.JobDetailImpl"> <!--jobDetail任务名 --> <property name="name" value="cornJob" /> <!--jobDetail组名 --> <property name="group" value="cornJobGroup" /> <!--自定义任务类job包classname --> <property name="jobClass" value="business.timerTaskForQuatz.bean.CustomJob" /> </bean> <!--quartz主类 --> <bean id="quartzAction" class="business.timerTaskForQuatz.action.QuartzAction" init-method="start"> <!--jobDetail类 --> <property name="jobDetail" ref="jobDetail"></property> <!--定时表达式 --> <property name="cronExpression" ref="cronExc"></property> <!--调度工厂--> <property name="sFactory" ref="schedulerFactory"></property> <!--触发器 --> <property name="cronTrigger" ref="cronTrigger"></property> </bean> </beans>
项目源码
列出jar包附件图