玩转 Spring Boot 集成篇(任务动态管理代码篇)

Posted 一猿小讲

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了玩转 Spring Boot 集成篇(任务动态管理代码篇)相关的知识,希望对你有一定的参考价值。

* 定时任务管理**/ @ private TaskInfoService taskInfoService; @ public Result list(@RequestBody TaskInfoReq reqVo) @ public Result edit(@RequestBody TaskInfoReq reqVo) @ public Result pause(Integer taskId) @ public Result add(@RequestBody TaskInfoReq taskInfoReq) @ public Result resume(Integer taskId) @ public Result delete(@RequestBody TaskInfoReq reqVo) com.example.demo.quartz.task;com.example.demo.quartz.entity.TaskInfo;com.example.demo.quartz.utils.SpringContextUtils;com.example.demo.quartz.vo.TaskInfoReq;org.quartz.*;org.slf4j.Logger;org.slf4j.LoggerFactory;org.springframework.beans.factory.annotation.Autowired;org.springframework.stereotype.Component;* 任务管理* 1、添加任务 2、更新任务 3、暂停任务 4、恢复任务**/ Logger LOGGER = LoggerFactory.getLogger(TaskManager.class); String JOB_DEFAULT_GROUP_NAME = String TRIGGER_DEFAULT_GROUP_NAME = Scheduler scheduler; SpringContextUtils springContextUtils; * 添加任务 */ flag = (!CronExpression.isValidExpression(taskInfoReq.getCron())) LOGGER.error( String className = springContextUtils.getBean(taskInfoReq.getJobName()).getClass().getName(); JobDetail jobDetail = JobBuilder.newJob().withIdentity(JobKey(taskInfoReq.getJobName(), JOB_DEFAULT_GROUP_NAME)) .ofType((Class<Job>) Class.forName(className)) .build(); Trigger trigger = TriggerBuilder.newTrigger() .forJob(jobDetail) .withSchedule(CronScheduleBuilder.cronSchedule(taskInfoReq.getCron())) .withIdentity(TriggerKey(taskInfoReq.getJobName(), TRIGGER_DEFAULT_GROUP_NAME)) .build(); scheduler.scheduleJob(jobDetail, trigger); scheduler.start(); (Exception e) LOGGER.error( flag = flag; * 更新任务 */ flag = JobKey jobKey = JobKey(taskInfo.getJobName(), JOB_DEFAULT_GROUP_NAME); TriggerKey triggerKey = TriggerKey(taskInfo.getJobName(), TRIGGER_DEFAULT_GROUP_NAME); JobDetail jobDetail = scheduler.getJobDetail(jobKey); (scheduler.checkExists(jobKey) && scheduler.checkExists(triggerKey)) Trigger newTrigger = TriggerBuilder.newTrigger() .forJob(jobDetail) .withSchedule(CronScheduleBuilder.cronSchedule(taskInfo.getCron())) .withIdentity(triggerKey) .build(); scheduler.rescheduleJob(triggerKey, newTrigger); LOGGER.info( LOGGER.info( (SchedulerException e) LOGGER.error( flag = flag; * 暂停任务 */ scheduler.pauseJob(JobKey.jobKey(taskInfo.getJobName(), JOB_DEFAULT_GROUP_NAME)); LOGGER.info( (SchedulerException e) LOGGER.error( * 恢复任务 */ scheduler.resumeJob(JobKey.jobKey(taskInfo.getJobName(), JOB_DEFAULT_GROUP_NAME)); LOGGER.info( (SchedulerException e) LOGGER.error( com.example.demo.quartz.common.EnumTaskEnable;com.example.demo.quartz.entity.TaskInfo;com.example.demo.quartz.service.TaskInfoService;com.example.demo.quartz.vo.TaskInfoReq;org.quartz.Scheduler;org.quartz.SchedulerException;org.slf4j.Logger;org.slf4j.LoggerFactory;org.springframework.beans.BeanUtils;org.springframework.beans.factory.annotation.Autowired;org.springframework.stereotype.Component;org.springframework.util.StringUtils;javax.annotation.PostConstruct;java.util.List; logger = @ scheduler; @ springJobFactory; @ taskInfoService; @ void start() scheduler.setJobFactory(springJobFactory); (taskInfo : tasks) ( data=new taskInfoService.addJob(data); logger.info( (e) logger.error(e.getMessage(), e); new com.example.demo.quartz.config;org.quartz.spi.TriggerFiredBundle;org.springframework.beans.factory.annotation.Autowired;org.springframework.beans.factory.config.AutowireCapableBeanFactory;org.springframework.scheduling.quartz.AdaptableJobFactory;org.springframework.stereotype.Component;* 解决spring bean注入Job的问题*/ AutowireCapableBeanFactory capableBeanFactory; Object Exception Object jobInstance = capableBeanFactory.autowireBean(jobInstance); jobInstance; ( AUTO_INCREMENT datetime datetime PRIMARY (AUTO_INCREMENT=lombok.Data;java.io.Serializable;java.util.Date;TaskInfo Serializable Integer id; cron; jobName; status; createTime; updateTime; com.example.demo.quartz.common.Result;com.example.demo.quartz.entity.TaskInfo;com.example.demo.quartz.vo.TaskInfoReq;java.util.List;* 定时任务接口**/interface TaskInfoService List<TaskInfo> selectTasks(); com.example.demo.quartz.service.impl;com.example.demo.quartz.common.CodeMsg;com.example.demo.quartz.common.EnumTaskEnable;com.example.demo.quartz.common.ResponseFactory;com.example.demo.quartz.common.Result;com.example.demo.quartz.dao.TaskInfoDao;com.example.demo.quartz.entity.TaskInfo;com.example.demo.quartz.service.TaskInfoService;com.example.demo.quartz.task.TaskManager;com.example.demo.quartz.vo.TaskInfoReq;com.github.pagehelper.PageHelper;com.github.pagehelper.PageInfo;org.quartz.CronExpression;org.slf4j.Logger;org.slf4j.LoggerFactory;org.springframework.beans.BeanUtils;org.springframework.stereotype.Service;org.springframework.transaction.javax.java.util.Date;java.util.List;java.util.Objects;* 定时任务业务实现**/ static Logger LOGGER = LoggerFactory.getLogger(TaskInfoServiceImpl. TaskInfoDao taskInfoDao; TaskManager taskManager; Result selectTaskListByPage(TaskInfoReq taskInfoReq) PageHelper.startPage(taskInfoReq.getPageCurrent(), taskInfoReq.getPageSize()); List<TaskInfo> list = taskInfoDao.selectTaskInfos(taskInfoReq); PageInfo<TaskInfo> pageInfo = new PageInfo<>(list); ResponseFactory.build(pageInfo); Result updateJob(TaskInfoReq taskInfoReq) (!CronExpression.isValidExpression(taskInfoReq.getCron())) LOGGER.error( ResponseFactory.build(CodeMsg.TASK_CRON_ERROR); TaskInfo isExistData = taskInfoDao.selectByJobName(taskInfoReq.getJobName()); ((!Objects.isNull(isExistData)) && (!isExistData.getId().equals(taskInfoReq.getId()))) ResponseFactory.build(CodeMsg.TASK_CRON_DOUBLE); TaskInfo = taskInfoDao.selectByPrimaryKey(taskInfoReq.getId()); (== ResponseFactory.build(CodeMsg.TASK_NOT_EXITES); BeanUtils.copyProperties(taskInfoReq, taskInfoDao.updateByPrimaryKeySelective( (!taskManager.updateJob( ResponseFactory.build(CodeMsg.TASK_EXCEPTION); ResponseFactory.build(); Result pauseJob(Integer taskId) TaskInfo = taskInfoDao.selectByPrimaryKey(taskId); (== ResponseFactory.build(CodeMsg.TASK_NOT_EXITES); (!taskManager.pauseJob( ResponseFactory.build(CodeMsg.TASK_EXCEPTION); taskInfoDao.updateByPrimaryKeySelective( ResponseFactory.build(); Result resumeJob(Integer taskId) TaskInfo = taskInfoDao.selectByPrimaryKey(taskId); (== ResponseFactory.build(CodeMsg.TASK_NOT_EXITES); (!taskManager.resumeJob( ResponseFactory.build(CodeMsg.TASK_EXCEPTION); taskInfoDao.updateByPrimaryKeySelective( ResponseFactory.build(); Result addJob(TaskInfoReq taskInfoReq) (!taskManager.addJob(taskInfoReq)) ResponseFactory.build(CodeMsg.TASK_EXCEPTION); TaskInfo = taskInfoDao.selectByJobName(taskInfoReq.getJobName()); (Objects.isNull( = new TaskInfo(); BeanUtils.copyProperties(taskInfoReq, taskInfoDao.insertSelective( ResponseFactory.build(); ResponseFactory.build(CodeMsg.TASK_CRON_DOUBLE); Result delete(TaskInfoReq reqVo) Result result = (CodeMsg.SUCCESS == result.getCode()) taskInfoDao.deleteByPrimaryKey(reqVo.getId()); ResponseFactory.build(); ResponseFactory.build(CodeMsg.TASK_EXCEPTION); (Exception e) ResponseFactory.build(CodeMsg.TASK_EXCEPTION); List<TaskInfo> selectTasks() taskInfoDao.selectAll(); id, cron, job_name, status, create_time, update_time select from sc_task_info where id = #id,jdbcType=INTEGER delete from sc_task_info where id = #id,jdbcType=INTEGER SELECT LAST_INSERT_ID() insert into sc_task_info (cron, job_name, status, create_time, update_time) values (#cron,jdbcType=VARCHAR, #jobName,jdbcType=VARCHAR, #status,jdbcType=CHAR, #createTime,jdbcType=TIMESTAMP, #updateTime,jdbcType=TIMESTAMP) SELECT LAST_INSERT_ID() insert into sc_task_info cron, job_name, status, create_time, update_time, #cron,jdbcType=VARCHAR, #jobName,jdbcType=VARCHAR, #status,jdbcType=CHAR, #createTime,jdbcType=TIMESTAMP, #updateTime,jdbcType=TIMESTAMP, update sc_task_info cron = #cron,jdbcType=VARCHAR, job_name = #jobName,jdbcType=VARCHAR, status = #status,jdbcType=CHAR, create_time = #createTime,jdbcType=TIMESTAMP, update_time = #updateTime,jdbcType=TIMESTAMP, where id = #id,jdbcType=INTEGER update sc_task_info set cron = #cron,jdbcType=VARCHAR, job_name = #jobName,jdbcType=VARCHAR, status = #status,jdbcType=CHAR, create_time = #createTime,jdbcType=TIMESTAMP, update_time = #updateTime,jdbcType=TIMESTAMP where id = #id,jdbcType=INTEGER select * from sc_task_info where job_name=#jobName select * from sc_task_info select * from sc_task_info lombok.Data;* 任务请求类**/TaskInfoReq Integer id; cron; status; jobName; int pageSize= int pageCurrent=com.example.demo.quartz.common;lombok.Data; code; String msg; Object retData;* 响应工具类*/ Result code, String errmsg) Result result = Result(); result.setCode(code); (errmsg == || errmsg.trim().length() == result.setMsg(CodeMsg.getMsg(code)); result.setMsg(errmsg); result; Result code) commonBuild(code, CodeMsg.getMsg(code)); Result commonBuild(CodeMsg.SUCCESS, Result Result json = commonBuild(CodeMsg.SUCCESS, json.setRetData(data); json; EnumTaskEnable START( STOP( code; msg; EnumTaskEnable(code, msg) getCode() code; com.example.demo.quartz.common;java.util.HashMap;java.util.Map;* 公共返回码*/ Map<Integer, String> MSG = HashMap<Integer, String>(); SUCCESS = ERROR = TASK_NOT_EXITES = TASK_EXCEPTION = TASK_CRON_ERROR = TASK_CRON_DOUBLE = MSG.put(SUCCESS, MSG.put(ERROR, MSG.put(TASK_NOT_EXITES, MSG.put(TASK_EXCEPTION, MSG.put(TASK_CRON_ERROR, MSG.put(TASK_CRON_DOUBLE, String errcode) MSG.get(errcode); com.example.demo.quartz.utils;org.springframework.beans.BeansException;org.springframework.context.ApplicationContext;org.springframework.context.ApplicationContextAware;org.springframework.context.annotation.Lazy;org.springframework.stereotype.Component; ApplicationContext applicationContext; * 实现ApplicationContextAware接口的回调方法,设置上下文环境 * * applicationContext */ SpringContextUtils.applicationContext = applicationContext; * ApplicationContext */ ApplicationContext applicationContext; * 获取对象 * 这里重写了bean方法,起主要作用 * * name * Object 一个以所给名字注册的bean的实例 * BeansException */ <T> (T) applicationContext.getBean(name); (Exception e) <T> applicationContext.getBean(clazz); (Exception e) mysql 链接信息Mapper资源文件存放的路径Dao 接口文件存放的目录开启 debug,输出 SQL com.example.demo.quartz.task;org.apache.commons.logging.Log;org.apache.commons.logging.LogFactory;org.quartz.JobExecutionContext;org.quartz.JobExecutionException;org.springframework.scheduling.quartz.QuartzJobBean;org.springframework.stereotype.Component;* 定义一个调度器要执行的任务*/ Log logger = LogFactory.getLog(DongAoJob.class); JobExecutionException logger.info( com.example.demo.quartz;org.springframework.boot.SpringApplication;org.springframework.boot.autoconfigure.SpringBootApplication; SpringApplication.run(DemoJobApplication.class, args);


6. 运行验证


其实挂个简单页面就能轻松完成页面化配置任务,本次用 Postman 方式直接调用任务管理的 API


6.1 添加任务



此时库任务 Id 为7:

控制台:



6.2 查询任务


6.3 编辑任务



控制台输出:



6.4 暂停任务

  • http://localhost:15158/task/pause?taskId=7

    6.5 恢复任务

  • http://localhost:15158/task/resume?taskId=7

    7. 例行回顾


    本文是 Spring Boot 项目集成 Quartz 来实现任务的动态管理,主要是代码,感兴趣的可以自行拿去验证改造并用于实践。



    玩转 Spring Boot 集成定时任务篇就写到这里,希望大家能够喜欢。


    一起聊技术、谈业务、喷架构,少走弯路,不踩大坑,会持续输出更多精彩分享,欢迎关注,敬请期待!

    历史系列文章:

    玩转  Spring Boot 入门篇

    玩转 Spring Boot 集成篇(MySQL、Druid、HikariCP

    玩转  Spring Boot 集成篇(MyBatis、JPA、事务支持

    玩转  Spring Boot 集成篇(Redis

    玩转 Spring Boot 集成篇(Actuator、Spring Boot Admin

    玩转 Spring Boot 集成篇(RabbitMQ)

    玩转 Spring Boot 集成篇(@Scheduled、静态、动态定时任务)

    Spring Boot集成Quartz注入Spring管理的类

    摘要: 在Spring Boot中使用Quartz时,在JOB中一般需要引用Spring管理的Bean,通过定义Job Factory实现自动注入

    Spring有自己的Schedule定时任务,在Spring boot中使用的时候,不能动态管理JOB,于是就使用Quartz来实现。

    在Spring Boot中配置Quartz:

    import java.io.IOException;
    import java.util.Properties;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.config.PropertiesFactoryBean;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.core.io.ClassPathResource;
    import org.springframework.scheduling.annotation.EnableScheduling;
    import org.springframework.scheduling.quartz.SchedulerFactoryBean;
    
    @Configuration
    @EnableScheduling
    public class QuartzSchedule {
    
        @Autowired
        private MyJobFactory myJobFactory;
    
        @Bean
        public SchedulerFactoryBean schedulerFactoryBean() throws IOException {
            SchedulerFactoryBean factory = new SchedulerFactoryBean();
    
            factory.setOverwriteExistingJobs(true);
    
            // 延时启动
            factory.setStartupDelay(20);
    
            // 加载quartz数据源配置
            factory.setQuartzProperties(quartzProperties());
    
            // 自定义Job Factory,用于Spring注入
            factory.setJobFactory(myJobFactory);
    
            return factory;
        }
    
        /**
         * 加载quartz数据源配置
         * 
         * @return
         * @throws IOException
         */
        @Bean
        public Properties quartzProperties() throws IOException {
            PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
            propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties"));
            propertiesFactoryBean.afterPropertiesSet();
            return propertiesFactoryBean.getObject();
        }
    
    }

     

    为了在JOB中使用Spring管理的Bean,需要重新定义一个Job Factory:

    @Component
    public class MyJobFactory extends AdaptableJobFactory {
        
        @Autowired
        private AutowireCapableBeanFactory capableBeanFactory;
    
        @Override
        protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
            // 调用父类的方法
            Object jobInstance = super.createJobInstance(bundle);
            // 进行注入
            capableBeanFactory.autowireBean(jobInstance);
            return jobInstance;
        }
    }

     

    然后在JOB中就可以使用Spring管理的Bean了

    public class MyJob implements Job, Serializable {
        private static final long serialVersionUID = 1L;
        private Logger logger = LoggerFactory.getLogger(this.getClass());
    
        @Autowired
        private SomeService someService;
    
        @Override
        public void execute(JobExecutionContext context) throws JobExecutionException {
            someService.doSomething();
        }
    }

     

    下面代码是创建JOB:

    JobDetail jobDetail = JobBuilder.newJob(((Job) Class.forName(job.getClazz()).newInstance()).getClass())
                        .withIdentity(job.getJobName(), job.getJobGroup()).build();
                jobDetail.getJobDataMap().put("extdata", job.getExtData());
    
                // 表达式调度构建器
                CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression())
                        .withMisfireHandlingInstructionDoNothing();
                // 构建一个trigger
                TriggerBuilder<CronTrigger> triggerBuilder = TriggerBuilder.newTrigger().withIdentity(triggerKey)
                        .withSchedule(scheduleBuilder);
                if (job.getStartTime() != null) {
                    triggerBuilder.startAt(job.getStartTime());
                }
                if (job.getEndTime() != null) {
                    triggerBuilder.endAt(job.getEndTime());
                }
                CronTrigger trigger = triggerBuilder.build();
    
                scheduler.scheduleJob(jobDetail, trigger);// 注入到管理类

     

     https://my.oschina.net/hhaijun/blog/698498

    以上是关于玩转 Spring Boot 集成篇(任务动态管理代码篇)的主要内容,如果未能解决你的问题,请参考以下文章

    Spring Boot集成Quartz注入Spring管理的类

    玩转Spring Boot 集成Dubbo

    玩转 Spring Boot 原理篇(源码环境搭建)

    玩转 Spring Boot 原理篇(自动装配源码剖析)

    玩转 Spring Boot 原理篇(核心注解知多少)

    Quartz+Spring Boot实现动态管理定时任务