spring3整合quartz2,实现动态添加、修改、暂停、重启定时任务

一、Quartz简介 

Quartz大致可分为三个主要的核心:

    1、调度器Scheduler:是一个计划调度器容器,容器里面可以盛放众多的JobDetail和Trigger,当容器启动后,里面的每个JobDetail都会根据Trigger按部就班自动去执行.

    2、任务Job:要执行的具体内容。JobDetail:具体的可执行的调度程序,包含了这个任务调度的方案和策略。

    3、触发器Trigger:调度参数的配置,什么时候去执行调度。


    可以这么理解它的原理:调度器就相当于一个容器,装载着任务和触发器。任务和触发器又是绑定在一起的,然而一个任务可以对应多个触发器,但一个触发器却只能对应一个任务。当JobDetail和Trigger在scheduler容器上注册后,形成了装配好的任务作业(JobDetail和Trigger所组成的一对儿),就可以伴随容器启动而调度执行了。


二、与spring的整合

    本文的用的是quartz-2.2.1与spring-3.2.2。之所以在这里特别对版本作一下说明,是因为spring和quartz的整合对版本是有要求的。spring3.1以下的版本必须使用quartz1.x系列,3.1以上的版本才支持quartz 2.x,不然会出错。原因主要是:spring对于quartz的支持实现,org.springframework.scheduling.quartz.CronTriggerBean继承了 org.quartz.CronTrigger,在quartz1.x系列中org.quartz.CronTrigger是个类,而在 quartz2.x系列中org.quartz.CronTrigger变成了接口,从而造成无法用spring的方式配置quartz的触发器 (trigger)。

spring中使用quartz有两种方式,具体请看http://blog.csdn.net/liuxiao723846/article/details/46879077


三、动态整合

   上面的整合只能应付简单的需求,但很多时候我们遇到的是需要动态的添加、暂停、修改任务。而spring中所提供的定时任务组件却只能够通过修改xml中trigger的配置才能控制定时任务的时间以及任务的启用或停止,这在带给我们方便的同时也失去了动态配置任务的灵活性。

   所以我们就得换种方式来解决。把任务与cronExpression存放在数据库中,最大化减少xml配置,创建一个工厂类,在实际调用时把任务的相关信息通过参数方式传入,由该工厂类根据任务信息来具体执行需要的操作,从而方便我们的动态修改。

1.spring配置(其实只要这一行足矣,去掉了原先"taskJob"、"myTrigger"等配置):

<bean id="schedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean" />


2、任务执行入口,实现Job接口,类似工厂类:

package com.quartz;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import com.quartz.model.ScheduleJob;
/**
 * 定时任务运行工厂
 * @author unique
 *
 */
public class QuartzJobFactory implements Job {
    public void execute(JobExecutionContext context) throws JobExecutionException {
         System.out.println("任务成功运行");
         ScheduleJob scheduleJob = (ScheduleJob)context.getMergedJobDataMap().get("scheduleJob");
         System.out.println("任务名称 = [" + scheduleJob.getJobName() + "]");
         //根据name 与 group组成的唯一标识来判别该执行何种操作……
    }
}
这里我们实现的是无状态的Job,如果要实现有状态的Job在以前是实现StatefulJob接口,在我使用的quartz 2.2.1中,StatefulJob接口已经不推荐使用了,换成了注解的方式,只需要给你实现的Job类加上注解 @DisallowConcurrentExecution即可实现有状态:
/** 
* 定时任务运行工厂类 
*/
@DisallowConcurrentExecution
public class QuartzJobFactory implements Job {...}
3、 创建任务。既然要动态修改任务,那任务就得保存在某个地方,所以我们需要个JavaBean来存放任务信息。
package com.quartz.model;
/**
 * 计划任务信息
 * @author unique
 */
public class ScheduleJob {
     /** 任务id */
    private String jobId;
    /** 任务名称 */
    private String jobName;
    /** 任务分组 */
    private String jobGroup;
    /** 任务状态 0禁用 1启用 2删除*/
    private String jobStatus;
    /** 任务运行时间表达式 */
    private String cronExpression;
    /** 任务描述 */
    private String desc;
    public ScheduleJob() {
        super();
    }
    public ScheduleJob(String jobId, String jobName, String jobGroup,
            String jobStatus, String cronExpression, String desc) {
        super();
        this.jobId = jobId;
        this.jobName = jobName;
        this.jobGroup = jobGroup;
        this.jobStatus = jobStatus;
        this.cronExpression = cronExpression;
        this.desc = desc;
    }
    public String getJobId() {
        return jobId;
    }
    public void setJobId(String jobId) {
        this.jobId = jobId;
    }
    public String getJobName() {
        return jobName;
    }
    public void setJobName(String jobName) {
        this.jobName = jobName;
    }
    public String getJobGroup() {
        return jobGroup;
    }
    public void setJobGroup(String jobGroup) {
        this.jobGroup = jobGroup;
    }
    public String getJobStatus() {
        return jobStatus;
    }
    public void setJobStatus(String jobStatus) {
        this.jobStatus = jobStatus;
    }
    public String getCronExpression() {
        return cronExpression;
    }
    public void setCronExpression(String cronExpression) {
        this.cronExpression = cronExpression;
    }
    public String getDesc() {
        return desc;
    }
    public void setDesc(String desc) {
        this.desc = desc;
    }
}
接下来这个类是最为主要的,请求地址跳往相对应的方法:
package com.wxapi.action;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.quartz.QuartzJobFactory;
import com.quartz.model.ScheduleJob;
import com.wxapi.bs.IQuartzBS;
@Controller
@RequestMapping("/quartz")
public class QuartzAction {
    @Autowired
    private SchedulerFactoryBean schedulerFactoryBean;
    @Autowired
    private IQuartzBS quartzBS;
    /**
     * 任务创建与更新(未存在的就创建,已存在的则更新)
     * @param request
     * @param response
     * @param scheduleJob
     * @param model
     * @return
     */
    @RequestMapping(value="/update", method={RequestMethod.POST,RequestMethod.GET})
    public String updateQuartz(HttpServletRequest request,HttpServletResponse response,
            @ModelAttribute("scheduleJob") ScheduleJob job,ModelMap model){
        try {
            Scheduler scheduler = schedulerFactoryBean.getScheduler();
            if(null!=job){
                //获取触发器标识
                TriggerKey triggerKey = TriggerKey.triggerKey(job.getJobName(), job.getJobGroup());
                //获取触发器trigger
                CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
                if(null==trigger){//不存在任务
                    //创建任务
                    JobDetail jobDetail = JobBuilder.newJob(QuartzJobFactory.class)
                            .withIdentity(job.getJobName(), job.getJobGroup())
                            .build();
                     
                    jobDetail.getJobDataMap().put("scheduleJob", job);
                     
                    //表达式调度构建器
                    CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job
                            .getCronExpression());
                     
                    //按新的cronExpression表达式构建一个新的trigger
                    trigger = TriggerBuilder.newTrigger()
                            .withIdentity(job.getJobName(), job.getJobGroup())
                            .withSchedule(scheduleBuilder)
                            .build();
                     
                    scheduler.scheduleJob(jobDetail, trigger);
                     
                    //把任务插入数据库
                    int result = quartzBS.add(job);
                    if(result!=0){
                        model.addAttribute("msg", "您的任务创建成功!");
                    }else{
                        model.addAttribute("msg", "您的任务创建失败!");
                    }
                }else{//存在任务
                     
                    // Trigger已存在,那么更新相应的定时设置
                    //表达式调度构建器
                    CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job
                            .getCronExpression());
                     
                    //按新的cronExpression表达式重新构建trigger
                    trigger = trigger.getTriggerBuilder()
                            .withIdentity(triggerKey)
                            .withSchedule(scheduleBuilder)
                            .build();
                     
                    //按新的trigger重新设置job执行
                    scheduler.rescheduleJob(triggerKey, trigger);
                     
                    //更新数据库中的任务
                    int result = quartzBS.update(job);
                    if(result==1){
                        model.addAttribute("msg", "您的任务更新成功!");
                    }else{
                        model.addAttribute("msg", "您的任务更新失败!");
                    }
                }
                 
            }
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
        return "/warn.jsp";
    }
     
    /**
     * 暂停任务
     * @param request
     * @param response
     * @param job
     * @param model
     * @return
     */
    @RequestMapping(value="/pause", method={RequestMethod.POST,RequestMethod.GET})
    public String pauseQuartz(HttpServletRequest request,HttpServletResponse response,
            @ModelAttribute("scheduleJob") ScheduleJob scheduleJob,ModelMap model){
 
        Scheduler scheduler = schedulerFactoryBean.getScheduler();
        JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
        try {
            scheduler.pauseJob(jobKey);
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
 
        return "/warn.jsp";
    }
    /**
     * 恢复任务
     * @param request
     * @param response
     * @param scheduleJob
     * @param model
     * @return
     */
    @RequestMapping(value="/resume", method={RequestMethod.POST,RequestMethod.GET})
    public String resumeQuartz(HttpServletRequest request,HttpServletResponse response,
            @ModelAttribute("scheduleJob") ScheduleJob scheduleJob,ModelMap model){
 
        Scheduler scheduler = schedulerFactoryBean.getScheduler();
        JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
        try {
            scheduler.resumeJob(jobKey);
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
 
        return "/warn.jsp";
    }
    /**
     * 删除任务
     * @param request
     * @param response
     * @param scheduleJob
     * @param model
     * @return
     */
    @RequestMapping(value="/delete", method={RequestMethod.POST,RequestMethod.GET})
    public String deleteQuartz(HttpServletRequest request,HttpServletResponse response,
            @ModelAttribute("scheduleJob") ScheduleJob scheduleJob,ModelMap model){
 
        Scheduler scheduler = schedulerFactoryBean.getScheduler();
        JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
        try {
            scheduler.deleteJob(jobKey);
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
        return "/warn.jsp";
    }
}
在运行工厂类中:

ScheduleJob scheduleJob = (ScheduleJob)context.getMergedJobDataMap().get("scheduleJob");

可获取任务分组和任务名称来确定任务的唯一性,然后在execute方法中通过判断任务分组和任务名来实现你具体的操作。



  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在使用Spring Quartz实现定时任务时,如果需要修改定时时间而不重启服务,可以考虑以下几种方式: 1. 使用Quartz动态定时任务更新功能: Quartz提供了动态修改定时任务的功能,可以通过更新Cron表达式来实现修改定时时间。首先,在配置文件中设置定时任务的Cron表达式为一个变量,然后在代码中通过调用Quartz的API读取配置文件的变量,并更新定时任务的Cron表达式。通过这种方式,不需要重启服务即可修改定时时间。 2. 使用数据库表保存定时任务配置参数: 可以将定时任务的配置参数,如定时时间、执行类等保存在数据库表中。然后在代码中通过查询数据库表的方式动态获取定时任务的配置参数。当需要修改定时时间时,只需更新数据库表中的相应字段,代码动态读取到新的定时时间并生效,而不需要重启服务。 3. 使用Spring动态Bean注册功能: 在项目启动时,通过编程的方式动态注册定时任务的Bean。将定时任务的配置属性作为参数传入Bean,当需要修改定时时间时,通过修改Bean的相关属性值来实现Spring自动重新加载Bean的定义,并根据新的配置参数重新创建定时任务对象,从而实现修改定时时间而不重启服务。 综上所述,使用Quartz动态定时任务更新功能、数据库表保存定时任务配置参数或者Spring动态Bean注册功能,都可以实现在不重启服务的情况下修改定时时间。根据实际项目需求和技术架构选择合适的方式即可。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值