SpringBoot 集成 Quartz 框架

前言:

        Quartz 框架是一个非常古老的框架,甚至可以说是其他定时框架(powerjod、xxl-job、scheduler)的始祖;其他框架要么是改造 quartz 而来、要么就是吸收 quartz 的核心思想而成。所以了解 quartz 的知识对使用其他框架很很大帮助,并且 quartz 的功能基本满足大部分场景。

一、Quartz 的核心概念

1. Job

 具体任务的实现类。需要实现 org.quartz.Job 接口,具体的执行逻辑需要重写 execute 方法。

2. JobDetail

Job 的进一步封装。

3. Trigger

触发器。任务实现的触发机制,包括定时任务的 cron 表达式就是在这里实现的。

4. Scheduler

调度器。会把 JobDetail 和 Trigger 结合在一起进行任务管理。

二、定时任务样例

1. Job 类

import lombok.extern.slf4j.Slf4j;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.springframework.stereotype.Component;

@Slf4j
@Component
public class ScheduleJob implements Job{

    @Override
    public void execute(JobExecutionContext jobExecutionContext) {
        JobDataMap jobDataMap = jobExecutionContext.getJobDetail().getJobDataMap();
        log.info("获取任务的一些其他信息:{}", jobDataMap);
        log.info("这里书写需要执行的逻辑......");
    }

}

2. 定时配置类

import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import quancheng.demo.quartz.job.ScheduleJob;

@Slf4j
@Configuration
public class QuartzConfig {

    @Bean
    public void config() throws SchedulerException {
        Scheduler scheduler = new StdSchedulerFactory().getScheduler();

        JobDetail jobDetail = JobBuilder.newJob(ScheduleJob.class)
                // 任务的唯一标识 key
                .withIdentity(JobKey.jobKey("job1"))
                // 带上任务的一些其他信息,方便后续处理使用
                .usingJobData(new JobDataMap() {{
                    put("key1", "value1");
                }})
                .build();
        Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity(TriggerKey.triggerKey("trigger1"))
                .withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ? "))
                .build();
        scheduler.scheduleJob(jobDetail, trigger);

        scheduler.start();

    }

}

三、定时任务的改造

上面的逻辑比较简单,实际使用的过程中会结合数据库和反射让定时任务去执行工程里面的其他服务。数据库表的设计这里不展开讲,一般核心都是 全类限定名+方法名 的形式,讲一下反射和springboot 工程的集成。

1. service 类

该类是一个非常普通的 service 类

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

@Slf4j
@Service
public class ScheduleService {

    public String job1() {
        log.info("job1 start");
        return "job1 end";
    }

}

2. 改造 Job 类的 excute 方法

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

@Slf4j
@Component
public class ScheduleJob implements Job, ApplicationContextAware {

    private static ApplicationContext context; // 需要实现 ApplicationContextAware 接口才能获取 spring 上下文实例


    @SneakyThrows
    @Override
    public void execute(JobExecutionContext jobExecutionContext) {
        String taskClass = "scheduleService"; //类名(不包含包名),且首字母需要小写,spring 管理类的方式就是首字母小写的类名。如果是通过数据库传入的全类限定名需要处理下。
        String taskMethod = "job1";

        Object object = context.getBean(taskClass); // 获取 spring 管理的类实例

        Method m = object.getClass().getMethod(taskMethod);

        String result = (String) m.invoke(object);

        log.info("result:{}", result);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if (ScheduleJob.context == null) {
            ScheduleJob.context = applicationContext;
        }
    }

}

四、其他说明

1.如果需要有管理任务的能力,需要使用调度器的(Scheduler )增删改查、暂停任务管理能力;另外注意使用单例管理 Scheduler 。

2.上述实现没有任务跟踪,需要设计一套任务执行跟踪体系,包括方法是否能执行、执行的结果、耗时等。

参考:

1.Spring Boot 集成Quartz的简单入门_springboot集成quartz_就看见扣扣号的博客-CSDN博客

2.SpringBoot2.0集成Quartz - 简书 (jianshu.com)

3.SpringBoot+Quartz+MySQL实现分布式定时任务 - 荒野猛兽 - 博客园 (cnblogs.com)

你可能感兴趣的:(后端,spring,boot,后端,java,quartz,定时框架)