`
lee1177
  • 浏览: 117797 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

quartz+spring-单机版任务动态载入及修改

阅读更多

    quartz的使用比较普遍,动态修改修改也比较成型,这里只列举自己在项目中已比较简单的方式来实现的quartz的动态修改。

    首先把所有quartz任务定义放入放入数据库中,对应java自定义实体如下

 

public class SchedulerJob {
    public static final int STATUS_USED = 1;	//可用状态
    /** 任务id spring的bean名称*/
    private String jobId;
    /** 任务名称 */
    private String jobName;
    /** 任务状态 0停用 1启用 */
    private Integer jobStatus;
    /** 任务运行时间表达式 */
    private String cronExpression;
 

 

    对应定义任务运行的接口定义

 

/**
 * 
 * @ClassName: SchedulerJobBean
 * @Description: 定时任务Bean的顶级接口
 * @Create In 2014年9月23日 By lee
 */
public interface SchedulerJobBean {
	/**
	 * 定时任务执行业务逻辑方法体
	 * @Methods Name execute
	 * @Create In 2014年9月23日 By lee
	 * @param context
	 */
	public void execute(JobExecutionContext context);
}

    SchedulerJob中的jobId即是SchedulerJobBean实现的spring bean id,因此所有定时任务需实现SchedulerJobBean接口。

 

  然后自定义一个quartz运行工厂类,来执行定时任务实现

 

/**
 * 单机任务执行工厂
 * @ClassName: SingleQuartzJobFactory
 * @Description: TODO
 * @Create In 2015年1月14日 By lee
 */
@DisallowConcurrentExecution
public class SingleQuartzJobFactory implements Job {
	private static final Logger log = LoggerFactory.getLogger(SingleQuartzJobFactory.class);
	public void execute(JobExecutionContext context) throws JobExecutionException {
    	SchedulerJob scheduleJob = (SchedulerJob)context.getMergedJobDataMap().get("scheduleJob");
    	try{
    		SchedulerJobBean jobBean = (SchedulerJobBean) ContextHolder.getBean(scheduleJob.getJobId());
            jobBean.execute(context);
		} catch (Exception ex){
			log.error("====================Scheduler-error-begin====================");
			log.error(ex.toString());
			StackTraceElement[] element = ex.getStackTrace();
			for(int i=0;i<element.length;i++){
				log.error("位置:"+element[i]);
			}
	        log.error("====================Scheduler-error-end====================");
		}
    }
}
 

 

   最后需要一个加载器来实现加载功能,这里我封装了一个manager来处理。由于为集群情况考虑,先封装了一个基类管理器(其中关于集群部分下篇介绍)

 

/**
 * quartz任务管理器基类
 * @ClassName: AbstractQuartzManager
 * @Description: TODO
 * @Create In 2015年1月14日 By lee
 */
public abstract class AbstractQuartzManager {
	private static final Logger log = LoggerFactory.getLogger(AbstractQuartzManager.class);
	private static String schedulerState = "";	//定任务状态(single单机状态、cluster集群状态、null未启动状态)
	public static final String STATE_SINGLE = "single";		//单机状态
	public static final String STATE_CLUSTER = "cluster";	//集群状态
	public static final String STATE_NULL = "null";			//未启动状态
	/**
	 * 更新定时任务
	 * @Methods Name update
	 * @Create In 2014年9月23日 By lee
	 * @param job
	 * @throws SchedulerException 
	 */
	public static void update(SchedulerJob oldJob, SchedulerJob newJob) throws SchedulerException{
		if(oldJob==null){
			if(SchedulerJob.STATUS_USED==newJob.getJobStatus()){
				create(newJob);
			}
		}else{
			SchedulerFactoryBean schedulerFactoryBean = ContextHolder.getBean(SchedulerFactoryBean.class);
			Scheduler scheduler = schedulerFactoryBean.getScheduler();
			//获取触发器标识
	        TriggerKey triggerKey = TriggerKey.triggerKey(oldJob.getJobId(), SchedulerJob.JOB_GOURP);
	        //获取触发器trigger
	        CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
	        if(null!=trigger){//如果已存在任务
	        	delete(oldJob);
	        }
	        if(SchedulerJob.STATUS_USED==newJob.getJobStatus()){
				create(newJob);
			}
		}
	}
	public static void update(SchedulerJob job) throws SchedulerException{
		if(job!=null){
			SchedulerFactoryBean schedulerFactoryBean = ContextHolder.getBean(SchedulerFactoryBean.class);
			Scheduler scheduler = schedulerFactoryBean.getScheduler();
			//获取触发器标识
	        TriggerKey triggerKey = TriggerKey.triggerKey(job.getJobId(), SchedulerJob.JOB_GOURP);
	        //获取触发器trigger
	        CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
	        if(null!=trigger){//如果已存在任务
	        	delete(job);
	        }
	        if(SchedulerJob.STATUS_USED==job.getJobStatus()){
				create(job);
			}
		}
	}
	/**
	 * 新建任务
	 * @Methods Name create
	 * @Create In 2014年9月23日 By lee
	 * @param scheduleJob
	 * @throws SchedulerException 
	 */
	public static void create(SchedulerJob scheduleJob) throws SchedulerException {
		SchedulerFactoryBean schedulerFactoryBean = ContextHolder.getBean(SchedulerFactoryBean.class);
		Scheduler scheduler = schedulerFactoryBean.getScheduler();
		//创建任务
        JobDetail jobDetail = null;
        if(AbstractQuartzManager.getState().equalsIgnoreCase(AbstractQuartzManager.STATE_SINGLE)){
        	jobDetail = JobBuilder.newJob(SingleQuartzJobFactory.class)
                    .withIdentity(scheduleJob.getJobId(), SchedulerJob.JOB_GOURP)
                    .build();
        }else if(AbstractQuartzManager.getState().equalsIgnoreCase(AbstractQuartzManager.STATE_CLUSTER)){
        	jobDetail = JobBuilder.newJob(ClusterQuartzJobFactory.class)
                    .withIdentity(scheduleJob.getJobId(), SchedulerJob.JOB_GOURP)
                    .build();
        }else{
        	return;
        }
        jobDetail.getJobDataMap().put("scheduleJob", scheduleJob);
        //表达式调度构建器
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob
                .getCronExpression());
        //按新的cronExpression表达式构建一个新的trigger
        CronTrigger trigger = TriggerBuilder.newTrigger()
                .withIdentity(scheduleJob.getJobId(), SchedulerJob.JOB_GOURP)
                .withSchedule(scheduleBuilder)
                .build();
		scheduler.scheduleJob(jobDetail, trigger);
		log.debug("=====定时任务["+scheduleJob.getJobId()+"/"+scheduleJob.getJobName()+"]载入成功=====");
	}
	/**
	 * 修改
	 * @Methods Name modify
	 * @Create In 2014年9月23日 By lee
	 * @param scheduleJob
	 * @throws SchedulerException 
	 */
	public static void modify(SchedulerJob scheduleJob) throws SchedulerException {
		SchedulerFactoryBean schedulerFactoryBean = ContextHolder.getBean(SchedulerFactoryBean.class);
		Scheduler scheduler = schedulerFactoryBean.getScheduler();
		TriggerKey triggerKey = TriggerKey.triggerKey(scheduleJob.getJobId(), SchedulerJob.JOB_GOURP);
        //获取触发器trigger
        CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
		// Trigger已存在,那么更新相应的定时设置
        //表达式调度构建器
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob
                .getCronExpression());
        //按新的cronExpression表达式重新构建trigger
        trigger = trigger.getTriggerBuilder()
                .withIdentity(triggerKey)
                .withSchedule(scheduleBuilder)
                .build();
        //按新的trigger重新设置job执行
        scheduler.rescheduleJob(triggerKey, trigger);
        log.debug("=====定时任务["+scheduleJob.getJobId()+"/"+scheduleJob.getJobName()+"]更新成功=====");
	}
	/**
	 * 暂停任务
	 * @Methods Name pause
	 * @Create In 2014年9月23日 By lee
	 * @param scheduleJob
	 * @throws SchedulerException 
	 */
	public static void pause(SchedulerJob scheduleJob) throws SchedulerException {
		SchedulerFactoryBean schedulerFactoryBean = ContextHolder.getBean(SchedulerFactoryBean.class);
		Scheduler scheduler = schedulerFactoryBean.getScheduler();
        JobKey jobKey = JobKey.jobKey(scheduleJob.getJobId(), SchedulerJob.JOB_GOURP);
        scheduler.pauseJob(jobKey);
        log.debug("=====定时任务["+scheduleJob.getJobId()+"/"+scheduleJob.getJobName()+"]暂停成功=====");
	}
	/**
	 * 恢复任务
	 * @Methods Name resume
	 * @Create In 2014年9月23日 By lee
	 * @param scheduleJob
	 * @throws SchedulerException 
	 */
	public static void resume(SchedulerJob scheduleJob) throws SchedulerException {
		SchedulerFactoryBean schedulerFactoryBean = ContextHolder.getBean(SchedulerFactoryBean.class);
		Scheduler scheduler = schedulerFactoryBean.getScheduler();
        JobKey jobKey = JobKey.jobKey(scheduleJob.getJobId(), SchedulerJob.JOB_GOURP);
        scheduler.resumeJob(jobKey);
        log.debug("=====定时任务["+scheduleJob.getJobId()+"/"+scheduleJob.getJobName()+"]恢复成功=====");
	}
	/**
	 * 删除任务
	 * @Methods Name delete
	 * @Create In 2014年9月23日 By lee
	 * @param scheduleJob
	 * @throws SchedulerException 
	 */
	public static void delete(SchedulerJob scheduleJob) throws SchedulerException {
		SchedulerFactoryBean schedulerFactoryBean = ContextHolder.getBean(SchedulerFactoryBean.class);
		Scheduler scheduler = schedulerFactoryBean.getScheduler();
		JobKey jobKey = JobKey.jobKey(scheduleJob.getJobId(), SchedulerJob.JOB_GOURP);
        scheduler.deleteJob(jobKey);
        log.debug("=====定时任务["+scheduleJob.getJobId()+"/"+scheduleJob.getJobName()+"]注销成功=====");
	}
	/**
	 * 获取定时任务状态配置(single表示单机版,cluster表示集群版)
	 * @Methods Name getState
	 * @Create In 2015年1月14日 By lee
	 * @return
	 */
	public static String getState(){
		if(StringUtils.isEmpty(schedulerState)){
			schedulerState = PropertiesUtils.getProperty("app.scheduler.state");
		}
		return schedulerState;
	}
}
 针对单机增加一个SingleQuartzManager实现如下

 

 

/**
 * Quartz单机管理器
 * @ClassName: SingleQuartzManager
 * @Create In 2014年12月31日 By lee
 */
public class SingleQuartzManager extends AbstractQuartzManager{
	private static final Logger log = LoggerFactory.getLogger(SingleQuartzManager.class);
	public static final int STATE_RUN = 1;	//运行状态
	public static final int STATE_WAIT = 0;	//等待状态
	/**
	 * 启动所有定时任务
	 * @throws SchedulerException 
	 * @Methods Name startAll
	 * @Create In 2014年9月23日 By lee
	 */
	public static void startAll() throws SchedulerException{
		
		if(AbstractQuartzManager.getState().equalsIgnoreCase(AbstractQuartzManager.STATE_SINGLE)){
			SchedulerJobService schedulerJobService = ContextHolder.getBean(SchedulerJobService.class);
			List<SchedulerJob> jobs = schedulerJobService.findAll();
			for(SchedulerJob job : jobs){
				if(SchedulerJob.STATUS_USED==job.getJobStatus()){
					create(job);
				}
			}
			log.debug("=====定时任务启动完成=====");
		}
	}
	
}

 

 

   最最后补上配置文件

   

<?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-4.0.xsd">
	<bean id="schedulerFactory" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
	</bean>

</beans>

   

    这个实现只需要在spring中声明一下schedulerFactory,其他全部交给代码来完成。主要完成以下几个功能:

  1. 减少quartz配置;
  2. 通过配置文件动态修改quartz是否运行(我的配置文件也是动态的);
  3. 动态修改定时任务的状态预计运行规则。

  PS:

  1. 代码中ContextHolder.getBean及获取spring bean实例方法类。
  2. SingleQuartzManager.startAll()项目启动的时候调一下就不提供代码了

 

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics