Example of Implementation Method of springboot Dynamic Timing Task

  • 2021-08-16 23:49:48
  • OfStack

1. maven introduces quartz packet


<!-- https://mvnrepository.com/artifact/org.quartz-scheduler/quartz -->
<dependency>
 <groupId>org.quartz-scheduler</groupId>
 <artifactId>quartz</artifactId>
 <version>2.3.2</version>
</dependency>

2. Create a timed task factory class


/**
 *  Timed task factory class 
 */
@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. Create a timed task abstract class


public abstract class AbstractTask implements Job {

 private Logger logger = LoggerFactory.getLogger(AbstractTask.class);

 protected abstract void executeInternal(JobExecutionContext context) throws Exception;

 /**
 *  Timed task identification 
 */
 private String key;

 /**
 *  The primary key configured in the database 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. Create a timed task business implementation class

Here you can write your business code and realize specific business logic.


@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. Create Timing Task Manager

Including adding timed tasks when the project starts, manually adding timed tasks, updating timed tasks, deleting timed task methods.


/**
 *  Timed task management container  component  (Singleton Mode) 
 */
@Component
@Scope("singleton")
public class JobQuartzManager implements ApplicationContextAware {

 /**
 *  Create a new scheduler
 */
 private static SchedulerFactory schedulerFactory = new StdSchedulerFactory();

 private Scheduler scheduler;

 /**
 *  Define group names, and different groups are used to distinguish tasks 
 */
 private static final String JOB_GROUP_NAME = "JOB_GROUP_NAME";

 private static final String TRIGGER_GROUP_NAME = "TRIGGER_GROUP_NAME";

 /**
 *  Journal 
 */
 private Logger logger = LoggerFactory.getLogger(JobQuartzManager.class);

 private ApplicationContext applicationContext;

 @Autowired
 private JobFactory jobFactory;

 public void start() {
 // Start Timing Task (Initialization) 
 try {
  this.scheduler = schedulerFactory.getScheduler();
  scheduler.setJobFactory(jobFactory); // Setting Timed Task Factory Mode 
  // Default to when the project starts spring Container to add dynamic timed tasks 
  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();
  // Finish creating jobDetail After that, the statement is used to pass the parameter value, which is convenient for the timer task to identify what it is 
  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. Create a timed task startup class

Inject timing tasks into spring at project runtime


/**
 *  Timed task startup class 
 */
@Component
public class JobRunner implements ApplicationRunner {

 // Injection Timing Task Manager 
 @Autowired
 private JobQuartzManager quartzManager;

 /**
 *  Activate timed tasks when the project starts 
 */
 @Override
 public void run(ApplicationArguments applicationArguments) {
 System.out.println("-------------------- Injection timing task ---------------------");
 quartzManager.start();
 System.out.println("-------------------- Timed task injection completed ---------------------");
 }

}

7. Test cases


@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 " Successful addition ";
 }else{
  return " Add failed! ";
 }
 }

 @PostMapping("deleteJob")
 @ResponseBody
 public String deleteJob(@RequestParam("jobName") String jobName){
 boolean success = quartzManager.deleteJob(jobName);
 if(success){
  return " Delete succeeded ";
 }else{
  return " Delete failed! ";
 }
 }

 @PostMapping("updateJob")
 @ResponseBody
 public String updateJob(@RequestParam("jobName") String jobName, @RequestParam("cronExp") String cronExp){
 boolean success = quartzManager.updateJob(jobName, cronExp);
 if(success){
  return " Update succeeded ";
 }else{
  return " Update failed! ";
 }
 }

}

Summarize


Related articles: