小工具知识网

当前位置: 首页 > 行业知识 > SpringBoot(二)集成 Quartz

行业知识

SpringBoot(二)集成 Quartz

2026-11-07 12:49:43 来源:互联网转载

Quartz是一个广泛使用的开源任务调度框架,用于在Java应用程序中执行定时任务和周期性任务。它提供了强大的调度功能,允许您计划、管理和执行各种任务,从简单的任务到复杂的任务。

以下是Quartz的一些关键特点和功能:

  • 灵活的调度器:Quartz提供了一个高度可配置的调度器,允许您根据不同的时间表执行任务,包括固定的时间、每日、每周、每月、每秒等。您可以设置任务执行的时间和频率。
  • 多任务支持:Quartz支持同时管理和执行多个任务。您可以定义多个作业和触发器,并将它们添加到调度器中。
  • 集群和分布式调度:Quartz支持集群模式,可以在多台机器上协调任务的执行。这使得Quartz非常适合大规模和分布式应用,以确保任务的高可用性和负载均衡。
  • 持久化:Quartz可以将任务和调度信息持久化到数据库中,以便在应用程序重启时不会丢失任务信息。这对于可靠性和数据保持非常重要。
  • 错过任务处理:Quartz可以配置在任务错过执行时如何处理,例如,是否立即执行、延迟执行或丢弃任务。
  • 监听器:Quartz提供了各种监听器,可以用来监视任务的执行,以及在任务执行前后执行自定义操作。
  • 多种作业类型:Quartz支持不同类型的作业,包括无状态作业(Stateless Job)和有状态作业(Stateful

    Job)。这允许您选择最适合您需求的作业类型。

  • 插件机制:Quartz具有灵活的插件机制,可以扩展其功能。您可以创建自定义插件,以满足特定需求。
  • 丰富的API:Quartz提供了丰富的Java API,使任务调度的配置和管理非常方便。

    依赖

                       org.springframework.boot            spring-boot-starter-quartz            2.5.4        

    配置

    spring.quartz.job-store-type=jdbc# The first boot uses ALWAYSspring.quartz.jdbc.initialize-schema=neverspring.quartz.auto-startup=truespring.quartz.startup-delay=5sspring.quartz.overwrite-existing-jobs=truespring.quartz.properties.org.quartz.scheduler.instanceName=ClusterQuartzspring.quartz.properties.org.quartz.scheduler.instanceId=AUTOspring.quartz.properties.org.quartz.jobStore.class=org.springframework.scheduling.quartz.LocalDataSourceJobStorespring.quartz.properties.org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.PostgreSQLDelegatespring.quartz.properties.org.quartz.jobStore.tablePrefix=QRTZ_spring.quartz.properties.org.quartz.jobStore.isClustered=truespring.quartz.properties.org.quartz.jobStore.acquireTriggersWithinLock=truespring.quartz.properties.org.quartz.jobStore.misfireThreshold=12000spring.quartz.properties.org.quartz.jobStore.clusterCheckinInterval=5000spring.quartz.properties.org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPoolspring.quartz.properties.org.quartz.threadPool.threadCount=1spring.quartz.properties.org.quartz.threadPool.threadPriority=5spring.quartz.properties.org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread=true

    配置解释

    spring.quartz.job-store-type=jdbc:指定使用数据库作为Quartz的作业存储。spring.quartz.jdbc.initialize-schema=never:此属性设置为"never",表示不会自动初始化Quartz数据库架构。这意味着您需要手动创建Quartz数据库表,以便Quartz正常运行。您可以使用Quartz提供的SQL脚本来创建这些表。spring.quartz.auto-startup=true:设置为true,表示Quartz在Spring Boot应用程序启动时自动启动。spring.quartz.startup-delay=5s:Quartz启动延迟时间,设置为5秒。spring.quartz.overwrite-existing-jobs=true:设置为true,表示如果任务已经存在,则覆盖现有的任务。spring.quartz.properties.org.quartz.scheduler.instanceName=ClusterQuartz:为Quartz调度器设置实例名称。spring.quartz.properties.org.quartz.scheduler.instanceId=AUTO:Quartz调度器实例ID设置为"AUTO",这意味着它会自动分配一个唯一的实例ID。spring.quartz.properties.org.quartz.jobStore.class=org.springframework.scheduling.quartz.LocalDataSourceJobStore:指定使用org.springframework.scheduling.quartz.LocalDataSourceJobStore作为作业存储。spring.quartz.properties.org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.PostgreSQLDelegate:指定使用PostgreSQL数据库的委托类。spring.quartz.properties.org.quartz.jobStore.tablePrefix=QRTZ_:为Quartz数据库表添加前缀,以避免与其他表冲突。spring.quartz.properties.org.quartz.jobStore.isClustered=true:启用Quartz集群模式。spring.quartz.properties.org.quartz.jobStore.acquireTriggersWithinLock=true:设置为true,以确保在获取触发器时使用锁来处理并发。spring.quartz.properties.org.quartz.jobStore.misfireThreshold=12000:设置Quartz任务的超时时间,以确定任务是否错过执行。spring.quartz.properties.org.quartz.jobStore.clusterCheckinInterval=5000:设置节点之间检查其状态的时间间隔。spring.quartz.properties.org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool:定义Quartz线程池的类型。spring.quartz.properties.org.quartz.threadPool.threadCount=1:设置线程池中线程的数量。spring.quartz.properties.org.quartz.threadPool.threadPriority=5:设置线程的优先级。spring.quartz.properties.org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread=true:允许线程继承初始化线程的类加载器。

    job

    import cn.hutool.extra.spring.SpringUtil;import lombok.extern.slf4j.Slf4j;import org.quartz.DisallowConcurrentExecution;import org.quartz.Job;import org.quartz.JobExecutionContext;import org.quartz.PersistJobDataAfterExecution;import org.springframework.stereotype.Component;/** * @author Wang */@PersistJobDataAfterExecution@DisallowConcurrentExecution@Slf4j@Componentpublic class DealerJob implements Job {    @Override    public void execute(JobExecutionContext context) {        log.info("start Quartz job name: {}", context.getJobDetail().getKey().getName());        DealerImportFacade dealerImportFacade = SpringUtil.getBean(DealerImportFacade.class);        log.info(" start import US dealer data ");        RequestContext.current().set(RequestContextCons.REGION, DataSourceEnum.US.toString().toLowerCase());        try {//            dealerImportFacade.importUsDealerData();            log.info(" end import US dealer data ");        } catch (Exception e) {            log.error(e.getMessage(), e);        }    }}

    controller

    import jakarta.validation.Valid;import lombok.RequiredArgsConstructor;import lombok.extern.slf4j.Slf4j;import org.springframework.web.bind.annotation.*;/** * @author Wang */@RequiredArgsConstructor@Slf4j@RestController@RequestMapping("/schedule/job")public class ScheduleJobController {    final ScheduleJobService scheduleJobService;    final QuartzHelper quartzHelper;    @PostMapping    public AjaxRespData addJob(@Valid @RequestBody AddScheduleJobDTO scheduleJobDTO) {        ScheduleJobEntity scheduleJobEntity = BeanConvertUtils.convert(scheduleJobDTO, ScheduleJobEntity.class);        scheduleJobEntity.init();        scheduleJobEntity.setStatus(EnumScheduleJobStatus.RUN);        ScheduleJobData data = scheduleJobService.save(scheduleJobEntity);        quartzHelper.scheduleJob(data);        return AjaxRespData.success(BeanConvertUtils.convert(data, ScheduleJobVO.class));    }    @DeleteMapping("/{jobId}")    public AjaxRespData removeJob(@PathVariable("jobId") String jobId) {        ScheduleJobEntity scheduleJobEntity = scheduleJobService.checkExist(jobId, EnumError.E30001);        scheduleJobService.remove(jobId);        quartzHelper.remove(scheduleJobEntity);        return AjaxRespData.success();    }    @PutMapping("/{jobId}")    public AjaxRespData updateJob(@PathVariable String jobId, @Valid @RequestBody AddScheduleJobDTO scheduleJobDTO) {        ScheduleJobEntity scheduleJobEntity = BeanConvertUtils.convert(scheduleJobDTO, ScheduleJobEntity.class);        scheduleJobEntity.setId(jobId);        ScheduleJobData data = scheduleJobService.update(scheduleJobEntity);        quartzHelper.scheduleJob(data);        return AjaxRespData.success(BeanConvertUtils.convert(data, ScheduleJobVO.class));    }    @GetMapping("/{jobId}")    public AjaxRespData getJob(@PathVariable("jobId") String jobId) {        ScheduleJobEntity scheduleJobEntity = scheduleJobService.checkExist(jobId, EnumError.E30001);        return AjaxRespData.success(BeanConvertUtils.convert(scheduleJobEntity, ScheduleJobVO.class));    }    @PutMapping("/operate")    public void operateJob(@Valid @RequestBody AddScheduleJobDTO scheduleJobDTO) {        ScheduleJobEntity scheduleJobEntity = scheduleJobService.checkExist(scheduleJobDTO.getId(), EnumError.E30001);        scheduleJobEntity.setStatus(scheduleJobDTO.getStatus());        scheduleJobService.update(scheduleJobEntity);        quartzHelper.operateJob(scheduleJobDTO.getStatus(), scheduleJobEntity);    }}

    service

    import jakarta.annotation.PostConstruct;import lombok.RequiredArgsConstructor;import lombok.extern.slf4j.Slf4j;import org.springframework.stereotype.Service;import java.util.List;/** * @author Wang */@RequiredArgsConstructor@Slf4j@Servicepublic class ScheduleJobService extends BaseService {    final ScheduleJobRepository scheduleJobRepository;    final QuartzHelper quartzHelper;    @PostConstruct    public void init(){        log.info("init schedule job...");        List jobs = this.getRepository().findAll();        for (ScheduleJobEntity job : jobs) {            quartzHelper.scheduleJob(job);            quartzHelper.operateJob(EnumScheduleJobStatus.PAUSE, job);            if (job.getStatus().equals(EnumScheduleJobStatus.RUN)) {                quartzHelper.operateJob(EnumScheduleJobStatus.RUN, job);            }        }        log.info("init schedule job completed...");    }    @Override    public BaseRepository getRepository() {        return scheduleJobRepository;    }}

    helper

    import lombok.RequiredArgsConstructor;import lombok.extern.slf4j.Slf4j;import org.quartz.*;import org.springframework.stereotype.Component;import java.time.format.DateTimeFormatter;import java.util.Date;import java.util.Objects;/** * @author Wang */@RequiredArgsConstructor@Slf4j@Componentpublic class QuartzHelper {    final Scheduler scheduler;    public void scheduleJob(ScheduleJobEntity jobInfo) {        JobKey jobKey = JobKey.jobKey(jobInfo.getJobName(), jobInfo.getJobGroup());        try {            JobDetail jobDetail = scheduler.getJobDetail(jobKey);            if (Objects.nonNull(jobDetail)){                scheduler.deleteJob(jobKey);            }        } catch (SchedulerException e) {            e.printStackTrace();        }        JobDetail jobDetail = JobBuilder.newJob(getJobClass(jobInfo.getType()))                .withIdentity(jobKey)                .build();        Trigger trigger = TriggerBuilder.newTrigger()                .withIdentity(jobInfo.getTriggerName(), jobInfo.getTriggerGroup()).startNow()                .withSchedule(CronScheduleBuilder.cronSchedule(jobInfo.getCronExpression()))                .build();        try {            scheduler.scheduleJob(jobDetail, trigger);        } catch (SchedulerException e) {            log.error(e.getMessage(), e);        }    }    public void rescheduleJob(ScheduleJobEntity job) {        TriggerKey triggerKey = new TriggerKey(job.getTriggerName(), job.getTriggerGroup());        try {            CronTrigger cronTrigger = (CronTrigger) scheduler.getTrigger(triggerKey);            CronTrigger newCronTrigger = cronTrigger.getTriggerBuilder()                    .withIdentity(triggerKey)                    .withSchedule(CronScheduleBuilder.cronSchedule(job.getCronExpression()))                    .build();            scheduler.rescheduleJob(triggerKey, newCronTrigger);        } catch (SchedulerException e) {            throw new RuntimeException(e);        }    }    public void remove(ScheduleJobEntity job) {        TriggerKey triggerKey = new TriggerKey(job.getTriggerName(), job.getTriggerGroup());        try {            scheduler.pauseTrigger(triggerKey);            scheduler.unscheduleJob(triggerKey);            scheduler.deleteJob(JobKey.jobKey(job.getTriggerName(), job.getTriggerGroup()));        } catch (SchedulerException e) {            throw new RuntimeException(e);        }    }    public void unscheduleJob(ScheduleJobEntity job) {        TriggerKey triggerKey = new TriggerKey(job.getTriggerName(), job.getTriggerGroup());        try {            scheduler.unscheduleJob(triggerKey);        } catch (SchedulerException e) {            throw new RuntimeException(e);        }    }    public void operateJob(EnumScheduleJobStatus status, ScheduleJobEntity job) {        JobKey jobKey = JobKey.jobKey(job.getJobName(), job.getJobGroup());        try {            switch (status) {                case RUN:                    scheduler.resumeJob(jobKey);                    break;                case PAUSE:                    scheduler.pauseJob(jobKey);                    break;                default:                    throw new IllegalArgumentException();            }        } catch (SchedulerException e) {            throw new RuntimeException(e);        }    }    public String nextTime(ScheduleJobEntity job) {        TriggerKey triggerKey = new TriggerKey(job.getTriggerName(), job.getTriggerGroup());        try {            Trigger trigger = scheduler.getTrigger(triggerKey);            Date nextFireTime = trigger.getNextFireTime();            return DateUtil.format(nextFireTime, DateTimeFormatter.ISO_DATE_TIME);        } catch (SchedulerException e) {            throw new RuntimeException(e);        }    }    private Class

上一篇:Ourpia下载攻略,一键获取最新版本!

下一篇:搬瓦工宝塔面板安装教程,轻松上手,安装一步到位!