springboot实现动态定时任务

更新时间:2021-02-06 11:01:14点击次数:266次
1、maven引入quartz包
<!-- https://mvnrepository.com/artifact/org.quartz-scheduler/quartz -->
<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz</artifactId>
    <version>2.3.2</version>
</dep
2、创建定时任务工厂类
/**
 * 定时任务工厂类
 */
@Component
public class JobFactory extends SpringBeanJobFactory implements ApplicationContextAware {
    private transient AutowireCapableBeanFactory beanFactory;
    @Override
    protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
        final Object jobInstance = super.createJobInstance(bundle);
        beanFactory.autowireBean(jobInstance);
        return jobInstance;
    }
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.beanFactory = applicationContext.getAutowireCapableBeanFactory();
    }
}
3、创建定时任务抽象类
public abstract class AbstractTask implements Job {
    private Logger logger = LoggerFactory.getLogger(AbstractTask.class);
    protected abstract void executeInternal(JobExecutionContext context) throws Exception;
    /**
     * 定时任务标识
     */
    private String key;
    /**
     * 数据库里配置的主键id
     */
    private Long dataBaseId;
    @Override
    public void execute(JobExecutionContext context) {
        try {
            executeInternal(context);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            logger.error("job execute failed!");
        }
    }
    public String getKey() {
        return key;
    }
    public void setKey(String key) {
        this.key = key;
    }
    public Long getDataBaseId() {
        return dataBaseId;
    }
    public void setDataBaseId(Long dataBaseId) {
        this.dataBaseId = dataBaseId;
    }
}
4、创建定时任务业务实现类
这里可以写你的业务代码,实现具体的业务逻辑。
@Component("JobTask")
public class JobTask extends AbstractTask {
    @Override
    protected void executeInternal(JobExecutionContext context) {
        System.out.println("key = " + this.getKey());
        System.out.println("dataBaseId = " + this.getDataBaseId());
    }
}
5、创建定时任务管理器
包括项目启动时添加定时任务,手动添加定时任务,更新定时任务,删除定时任务方法。
/**
 * 定时任务管理容器 component (单例模式)
 */
@Component
@Scope("singleton")
public class JobQuartzManager implements ApplicationContextAware {
    /**
     * 创建新的scheduler
     */
    private static SchedulerFactory schedulerFactory = new StdSchedulerFactory();
    private Scheduler scheduler;
    /**
     * 定义组名称,不同的组用于区分任务
     */
    private static final String JOB_GROUP_NAME = "JOB_GROUP_NAME";
    private static final String TRIGGER_GROUP_NAME = "TRIGGER_GROUP_NAME";
    /**
     * 日志
     */
    private Logger logger = LoggerFactory.getLogger(JobQuartzManager.class);
    private ApplicationContext applicationContext;
    @Autowired
    private JobFactory jobFactory;
    public void start() {
        //启动定时任务(初始化)
        try {
            this.scheduler = schedulerFactory.getScheduler();
            scheduler.setJobFactory(jobFactory); //设置定时任务工厂模式
            //项目启动时默认给spring容器添加动态的定时任务
            this.addJob("job" + 100L, 100L, JobTask.class, "0/2 * * * * ?");
        } catch (SchedulerException e) {
            logger.error(e.getMessage(), e);
            throw new RuntimeException("init Scheduler failed");
        }
    }
    public boolean addJob(String jobName, Long dataBaseId, Class jobClass, String cronExp) {
        boolean result = false;
        if (!CronExpression.isValidExpression(cronExp)) {
            logger.error("Illegal cron expression format({})", cronExp);
            return result;
        }
        try {
            JobDetail jobDetail = JobBuilder.newJob().withIdentity(new JobKey(jobName, JOB_GROUP_NAME))
                    .ofType((Class<AbstractTask>) Class.forName(jobClass.getName()))
                    .build();
            //创建完jobDetail之后,使用语句传参数值,方便定时任务内部识别它是什么标识
            JobDataMap jobDataMap = jobDetail.getJobDataMap();
            jobDataMap.put("key", jobName);
            jobDataMap.put("dataBaseId", dataBaseId);
            Trigger trigger = TriggerBuilder.newTrigger()
                    .forJob(jobDetail)
                    .withSchedule(CronScheduleBuilder.cronSchedule(cronExp))
                    .withIdentity(new TriggerKey(jobName, TRIGGER_GROUP_NAME))
                    .build();
            scheduler.scheduleJob(jobDetail, trigger);
            scheduler.start();
            result = true;
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            logger.error("QuartzManager add job failed");
        }
        return result;
    }
    public boolean updateJob(String jobName, String cronExp) {
        boolean result = false;
        if (!CronExpression.isValidExpression(cronExp)) {
            logger.error("Illegal cron expression format({})", cronExp);
            return result;
        }
        JobKey jobKey = new JobKey(jobName, JOB_GROUP_NAME);
        TriggerKey triggerKey = new TriggerKey(jobName, TRIGGER_GROUP_NAME);
        try {
            if (scheduler.checkExists(jobKey) && scheduler.checkExists(triggerKey)) {
                JobDetail jobDetail = scheduler.getJobDetail(jobKey);
                Trigger newTrigger = TriggerBuilder.newTrigger()
                        .forJob(jobDetail)
                        .withSchedule(CronScheduleBuilder.cronSchedule(cronExp))
                        .withIdentity(new TriggerKey(jobName, TRIGGER_GROUP_NAME))
                        .build();
                scheduler.rescheduleJob(triggerKey, newTrigger);
                result = true;
            } else {
                logger.error("update job name:{},group name:{} or trigger name:{},group name:{} not exists..",
                        jobKey.getName(), jobKey.getGroup(), triggerKey.getName(), triggerKey.getGroup());
            }
        } catch (SchedulerException e) {
            logger.error(e.getMessage(), e);
            logger.error("update job name:{},group name:{} failed!", jobKey.getName(), jobKey.getGroup());
        }
        return result;
    }
    public boolean deleteJob(String jobName) {
        boolean result = false;
        JobKey jobKey = new JobKey(jobName, JOB_GROUP_NAME);
        try {
            if (scheduler.checkExists(jobKey)) {
                result = scheduler.deleteJob(jobKey);
            } else {
                logger.error("delete job name:{},group name:{} not exists.", jobKey.getName(), jobKey.getGroup());
            }
        } catch (SchedulerException e) {
            logger.error(e.getMessage(), e);
            logger.error("delete job name:{},group name:{} failed!", jobKey.getName(), jobKey.getGroup());
        }
        return result;
    }
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

}
6、创建定时任务启动类
项目运行时给spring注入定时任务
/**
 * 定时任务启动类
 */
@Component
public class JobRunner implements ApplicationRunner {
    //注入定时任务管理器
    @Autowired
    private JobQuartzManager quartzManager;
    /**
     * 项目启动时激活定时任务
     */
    @Override
    public void run(ApplicationArguments applicationArguments) {
        System.out.println("--------------------注入定时任务---------------------");
        quartzManager.start();
        System.out.println("--------------------定时任务注入完成---------------------");
    }

}
7、测试案例
@RestController
@RequestMapping("/job")
public class JobController {
    @Autowired
    JobQuartzManager quartzManager;
    @PostMapping("addJob")
    @ResponseBody
    public String addJob(@RequestParam("dataBaseId") Long dataBaseId, @RequestParam("cronExp") String cronExp){
        boolean success = quartzManager.addJob("job" + dataBaseId, dataBaseId, JobTask.class, cronExp);
        if(success){
            return "添加成功";
        }else{
            return "添加失败!";
        }
    }
    @PostMapping("deleteJob")
    @ResponseBody
    public String deleteJob(@RequestParam("jobName") String jobName){
        boolean success = quartzManager.deleteJob(jobName);
        if(success){
            return "删除成功";
        }else{
            return "删除失败!";
        }
    }
    @PostMapping("updateJob")
    @ResponseBody
    public String updateJob(@RequestParam("jobName") String jobName, @RequestParam("cronExp") String cronExp){
        boolean success = quartzManager.updateJob(jobName, cronExp);
        if(success){
            return "更新成功";
        }else{
            return "更新失败!";
        }
    }
}

本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责,本站只提供参考并不构成任何投资及应用建议。本站是一个个人学习交流的平台,网站上部分文章为转载,并不用于任何商业目的,我们已经尽可能的对作者和来源进行了通告,但是能力有限或疏忽,造成漏登,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。

  • 项目经理 点击这里给我发消息
  • 项目经理 点击这里给我发消息
  • 项目经理 点击这里给我发消息
  • 项目经理 点击这里给我发消息