Spring+quartz 动态任务调度
需求是这样的:系统中会有很多的执行时间,三个或者四个这样,不确定,以后可能是五个!当用户在页面添加执行时间时,我们后台也要对应执行用户添加的时间。
数据库设计:
- DROP TABLE IF EXISTS `test_time_task`;
- CREATE TABLE `test_time_task` (
- `status` int(11) DEFAULT NULL COMMENT ’状态:0为正常,1为禁用’,
- `job` varchar(255) CHARACTER SET utf8 DEFAULT NULL COMMENT ’执行时间’,
- `id` int(11) DEFAULT NULL COMMENT ’编号’
- ) ENGINE=InnoDB DEFAULT CHARSET=utf-8;
- – —————————-
- – Records of test_time_task
- – —————————-
- INSERT INTO `test_time_task` VALUES (’0′, ’0 30 9 * * ?’, ’1′);
- INSERT INTO `test_time_task` VALUES (’0′, ’0 30 11 * * ?’, ’2′);
- INSERT INTO `test_time_task` VALUES (’0′, ’0 30 16 * * ?’, ’3′);
查询语句,其中的#{hourMinute}为查询条件,格式——’12:11′:
- select case when (select job
- from (select job,RTRIM(substr(substr(job,6,7),1,2)) as hour, LTRIM(substr(job,2,3)) as minute from test_time_task where status = 0 ) as mytable
- where
- str_to_date( CONCAT(hour,’:',minute),’%k:%i’)> str_to_date( #{hourMinute} ,’%k:%i’) order by str_to_date(hour,’%k’) LIMIT 1) is null then
- (select job
- from (select job,RTRIM(substr(substr(job,6,7),1,2)) as hour, LTRIM(substr(job,2,3)) as minute from test_time_task where status = 0 ) as mytable
- order by str_to_date( CONCAT(hour,’:',minute),’%k:%i’) LIMIT 1) else
- (select job
- from (select job,RTRIM(substr(substr(job,6,7),1,2)) as hour, LTRIM(substr(job,2,3)) as minute from test_time_task where status = 0 ) as mytable
- where
- str_to_date( CONCAT(hour,’:',minute),’%k:%i’)> str_to_date( #{hourMinute} ,’%k:%i’) order by str_to_date(hour,’%k’) LIMIT 1) end
Spring配置文件:
- <?xml version=”1.0″ encoding=”UTF-8″?>
- <!DOCTYPE beans PUBLIC ”-//SPRING//DTD BEAN//EN” ”http://www.springframework.org/dtd/spring-beans.dtd”>
- <beans>
- <!– 被执行类 –>
- <bean id=”testQuarzt” class=”cmcc.gz.pmp.timetest.service.ScheduleInfoService”>
- <property name=”scheduler” ref=”schedulerFactory” />
- </bean>
- <!– 将testQuarzt注入到job中 –>
- <bean id=”testQuartzJob”
- class=”org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean”>
- <property name=”targetObject” ref=”testQuarzt” />
- <property name=”targetMethod” value=”loadJob” />
- <property name=”concurrent” value=”false” />
- </bean>
- <!– 将job注入到定时触发器 –>
- <bean id=”testTrigger” class=”org.springframework.scheduling.quartz.CronTriggerBean”>
- <property name=”jobDetail” ref=”testQuartzJob” />
- <property name=”cronExpression”>
- <value>0/1 * * * * ?</value>
- </property>
- </bean>
- <!– 将触发器注入任务工程 –>
- <bean id=”schedulerFactory”
- class=”org.springframework.scheduling.quartz.SchedulerFactoryBean”>
- <property name=”triggers”>
- <list>
- <ref bean=”testTrigger” />
- </list>
- </property>
- </bean>
- </beans>
java程序代码:
- import java.text.ParseException;
- import java.util.Date;
- import org.quartz.Scheduler;
- import org.quartz.SchedulerException;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.scheduling.quartz.CronTriggerBean;
- import cmcc.gz.pmp.timetest.db.mapper.JobMapper;
- import cmcc.gz.pmp.util.CommonDate;
- /**
- *
- * 类描述:时间任务调度测试方法
- * @author 胡汉三
- * 创建时间:2014-5-26 下午6:11:55
- *
- */
- public class ScheduleInfoService {
- @Autowired
- private JobMapper mapper;
- private Scheduler scheduler;
- // 设值注入,通过setter方法传入被调用者的实例scheduler
- public void setScheduler(Scheduler scheduler) {
- this.scheduler = scheduler;
- }
- public void loadJob() throws SchedulerException, ParseException{
- Object j = mapper.findJob(CommonDate.getTimeNow(new Date()));
- // 运行时可通过动态注入的scheduler得到trigger,注意采用这种注入方式在有的项目中会有问题,如果遇到注入问题,可以采 取在运行方法时候,获得bean来避免错误发生。
- CronTriggerBean trigger = (CronTriggerBean)scheduler.getTrigger(“testTrigger”,Scheduler.DEFAULT_GROUP);
- String originConExpression = trigger.getCronExpression();
- // 如果相等,则表示用户并没有重新设定数据库中的任务时间,这种情况不需要重新rescheduleJob 也不需要去执行任务
- if(!originConExpression.equalsIgnoreCase(j.toString())){
- //如果不是系统启动时的任务,就去执行它
- if(!originConExpression.equalsIgnoreCase(“0/1 * * * * ?”)){
- /** 执行任务 **/
- test();
- }
- System.out.println(j.toString());
- trigger.setCronExpression(j.toString());
- scheduler.rescheduleJob(“testTrigger”, Scheduler.DEFAULT_GROUP, trigger);
- }
- }
- /**
- * 执行任务
- */
- public void test(){
- System.out.println(“XML任务进行中…”);
- }
- }
测试时,当我把我的系统时间改为九点29的时候等到30就会执行,结果跟过程都正常,
更改到十一点半正常,更改到十六点半正常,当我更改到第二天九29的时候,执行就出错了:
Invocation of method
'resetJob'
on target
class
[
class
cmcc.gz.pmp.timetest.service.ScheduleInfoService$$EnhancerByCGLIB$$11b080f3] failed; nested exception is org.springframework.transaction.CannotCreateTransactionException: Could not open JDBC Connection
for
transaction; nested exception is com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
解决办法:
Mysql服务器默认的“wait_timeout”是8小时,也就是说一个connection空闲超过8个小时,Mysql将自动断开该connection。
它默认是8小时,我们手动改大一些,在测试就通过了!
查看:show
global
variables
like
'wait_timeout'
;
修改:
set
global
wait_timeout=86999;
帖子地址:点击打开链接
http://blog.csdn.net/hzw2312/article/details/27358795