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;


帖子地址:点击打开链接




你可能感兴趣的:(spring,quartz,动态任务调度)