当前位置: 首页 > 工具软件 > Quartz EX > 使用案例 >

quartz mysql例子_springBoot整合quartz数据库管理定时任务样例demo

东方森
2023-12-01

样例介绍

采用quartz,并使用数据库来动态管理定时任务。

步骤

(1)导入依赖

org.quartz-scheduler

quartz

2.3.0

org.springframework

spring-context-support

mysql

mysql-connector-java

runtime

com.baomidou

mybatis-plus-boot-starter

3.0.5

com.alibaba

druid-spring-boot-starter

1.1.10

(2)添加配置

数据库配置:

spring.datasource.druid.url=jdbc:mysql://*.*.*.*(这里使用自己服务器的ip):3306/(自己的数据库)?reWriteBatchedInserts=true

spring.datasource.druid.username=root

spring.datasource.druid.password=123456

spring.datasource.druid.driver-class-name=com.mysql.jdbc.Driver

quartz配置:

#--------------------------------------------------------------

#调度器属性

#--------------------------------------------------------------

# 调度器实例名:可以随意命名

org.quartz.scheduler.instanceName=quartz-demo

# 实例ID: 允许随意命名,但必须保持唯一,集群可以让quartz来帮你命名,设置为AUTO

org.quartz.scheduler.instanceId=AUTO

#只有org.quartz.scheduler.instanceId设置为“AUTO”才使用。

# 默认为“org.quartz.simpl.SimpleInstanceIdGenerator”,它是主机名和时间戳生成实例Id的。

# 其它的IntanceIdGenerator实现包括SystemPropertyInstanceIdGenerator(它从系统属性“org.quartz.scheduler.instanceId”获取实例Id),

# 和HostnameInstanceIdGenerator(它使用本地主机名InetAddress.getLocalHost().getHostName()生成实例Id)。

# 你也实现你自己的InstanceIdGenerator

org.quartz.scheduler.instanceIdGenerator.class=com.yw.quartzdemo.support.QuartzInstanceIdGenerator

#--------------------------------------------------------------

# 线程池属性

#--------------------------------------------------------------

# org.quartz.threadPool.class这个值是一个实现了 org.quartz.spi.ThreadPool 接口的类的全限名称。

# Quartz 自带的线程池实现类是 org.quartz.smpl.SimpleThreadPool,

# 它能够满足大多数用户的需求。这个线程池实现具备简单的行为,并经很好的测试过。

# 它在调度器的生命周期中提供固定大小的线程池。

# 你能根据需求创建自己的线程池实现,如果你想要一个随需可伸缩的线程池时也许需要这么做。

# 这个属性没有默认值,你必须为其指定值。

org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool

# threadCount 属性控制了多少个工作者线程被创建用来处理 Job。

# 原则上是,要处理的 Job 越多,那么需要的工作者线程也就越多。

# threadCount 的数值至少为 1。

# Quartz 没有限定你设置工作者线程的最大值,但是在多数机器上设置该值超过100的话就会显得相当不实用了,

# 特别是在你的 Job 执行时间较长的情况下。

# 这项没有默认值,所以你必须为这个属性设定一个值

org.quartz.threadPool.threadCount=10

# 优先级:可以是Thread.MIN_PRIORITY (1)和Thread.MAX_PRIORITY (10)之间的任意整数。默认为Thread.NORM_PRIORITY (5).

org.quartz.threadPool.threadPriority=5

# 继承初始化线程的上下文类加载器线程

org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread=true

#--------------------------------------------------------------

#作业存储设置:作业存储部分的设置描述了在调度器实例的生命周期中,Job 和 Trigger 信息是如何被存储的。

# 把调度器信息存储在内存中非常的快也易于配置。

# 当调度器进程一旦被终止,所有的 Job 和 Trigger 的状态就丢失了。

# 要使 Job 存储在内存中需通过设置 org.quartz.jobStrore.class 属性为 org.quartz.simpl.RAMJobStore,

# 在Cron Trigger 和“作业存储和持久化”会用到的不同类型的作业存储实现。

#--------------------------------------------------------------

# trigger被认为失败之前,scheduler能够承受的下一次触发时间(单位毫秒)。默认值为60秒。

org.quartz.jobStore.misfireThreshold=60000

# 用于将调度信息(job、trigger和calendar)存储到关系数据库中。

org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX

# 设置当前数据库Driver代理的数据库系统的方言

org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate

#org.quartz.jobStore.driverDelegateClass:org.quartz.impl.jdbcjobstore.PostgreSQLDelegate

# 表前缀

org.quartz.jobStore.tablePrefix=QRTZ_

# JobStore处理失败trigger的最大等待时间。

# 同时处理多个trigger(多于几个)回引发数据表长时间锁定,触发其它的trigger(还没有失败)的性能就会受到限制

org.quartz.jobStore.maxMisfiresToHandleAtATime=10

# 使用集群特性,这个属性必须为true。

# 如果你有多个Quartz实例使用相同的数据库表,这个属性必须为true,否则你会体验一把大破坏。参见集群配置。

org.quartz.jobStore.isClustered=true

# 设置当前实例check in集群中其它实例的频率。影响检测到故障实例的速度

org.quartz.jobStore.clusterCheckinInterval=20000

# “org.quartz.jobStore.useProperties”配置参数可以被设置为true(默认为false),

# 这样可以指导JDBCJobStore,JobDataMaps中的值都是字符串,因此这样可以以名字-值对存储,

# 而不是存储更加复杂的对象(序列化形式BLOB)。

# 从长远来看,这是很安全的,因为避免了将非字符串类序列化为BLOB的类版本问题

org.quartz.jobStore.useProperties=true

(3)添加定时任务表的PO,mapper,dao

po:

import com.baomidou.mybatisplus.annotation.TableName;

import lombok.AllArgsConstructor;

import lombok.Builder;

import lombok.Data;

import lombok.NoArgsConstructor;

@Data

@AllArgsConstructor

@NoArgsConstructor

@TableName("JOB_DEF")

@Builder

public class JobDefPO {

/**

* 任务名称-类全名

*/

private String jobName;

/**

* 任务分组

*/

private String jobGroup;

/**

* 任务执行表达式

*/

private String cron;

/**

* 任务状态

*/

private Integer status;

}

mapper:

import com.baomidou.mybatisplus.core.mapper.BaseMapper;

import com.yw.quartzdemo.po.JobDefPO;

import org.apache.ibatis.annotations.Mapper;

@Mapper

public interface JobDefMapper extends BaseMapper {

}

dao

import com.yw.quartzdemo.po.JobDefPO;

import java.util.List;

/**

* 任务定义接口

*/

public interface JobDefDAO {

/***

* @Description 查询所有任务

* @author yuanwei

* @param

* @return java.util.List

* @time 2021/1/6 16:35

*/

List listAll();

}

dao.impl:

import com.baomidou.mybatisplus.core.conditions.Condition;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.yw.quartzdemo.dao.JobDefDAO;

import com.yw.quartzdemo.mapper.JobDefMapper;

import com.yw.quartzdemo.po.JobDefPO;

import lombok.extern.slf4j.Slf4j;

import org.springframework.stereotype.Service;

import java.util.List;

/**

* 任务定义实现

*/

@Service

@Slf4j

public class JobDefDAOImpl extends ServiceImpl implements JobDefDAO {

@Override

public List listAll() {

List result = null;

final QueryWrapper wrapper = Condition.create();

try {

result = this.list(wrapper);

} catch (final Exception e) {

log.error("查询定时任务定义异常:{},{}", e.getMessage(), e);

throw new RuntimeException("查询定时任务定义失败");

}

return result;

}

}

(4)添加配置:

config包下

quartzConfig.java

import lombok.extern.slf4j.Slf4j;

import org.quartz.Scheduler;

import org.quartz.spi.TriggerFiredBundle;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.beans.factory.annotation.Qualifier;

import org.springframework.beans.factory.config.AutowireCapableBeanFactory;

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.quartz.AdaptableJobFactory;

import org.springframework.scheduling.quartz.SchedulerFactoryBean;

import javax.sql.DataSource;

import java.io.IOException;

import java.util.Properties;

@Configuration

@Slf4j

public class QuartzConfig {

@Autowired

private AutowireCapableBeanFactory capableBeanFactory;

@Autowired

private DataSource dataSource;

public Properties quartzProperties() throws IOException {

final PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();

propertiesFactoryBean.setLocation(new ClassPathResource("quartz.properties"));

propertiesFactoryBean.afterPropertiesSet();

return propertiesFactoryBean.getObject();

}

@Bean(name = "quartzJobFactory")

public AdaptableJobFactory quartzJobFactory() {

return new AdaptableJobFactory() {

@Override

protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception {

final Object jobInstance = super.createJobInstance(bundle);

capableBeanFactory.autowireBean(jobInstance);

return jobInstance;

}

};

}

@Bean(name = "schedulerFactoryBean")

public SchedulerFactoryBean schedulerFactoryBean(@Qualifier("quartzJobFactory") final AdaptableJobFactory quartzJobFactory) {

final SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();

try {

schedulerFactoryBean.setQuartzProperties(quartzProperties());

schedulerFactoryBean.setDataSource(dataSource);

schedulerFactoryBean.setJobFactory(quartzJobFactory);

schedulerFactoryBean.setStartupDelay(5);

schedulerFactoryBean.setOverwriteExistingJobs(true);

} catch (final IOException ex) {

log.error(ex.getMessage(), ex);

throw new RuntimeException("定时任务调度实体构建异常");

}

return schedulerFactoryBean;

}

@Bean(name = "scheduler")

public Scheduler scheduler(@Qualifier("schedulerFactoryBean") final SchedulerFactoryBean schedulerFactoryBean) {

return schedulerFactoryBean.getScheduler();

}

}

supper包下:

JobRefresh.java 用于设置定时刷新频率。

import com.yw.quartzdemo.dao.JobDefDAO;

import com.yw.quartzdemo.po.JobDefPO;

import lombok.extern.slf4j.Slf4j;

import org.quartz.CronScheduleBuilder;

import org.quartz.CronTrigger;

import org.quartz.Job;

import org.quartz.JobBuilder;

import org.quartz.JobDetail;

import org.quartz.JobKey;

import org.quartz.Scheduler;

import org.quartz.SchedulerException;

import org.quartz.TriggerBuilder;

import org.quartz.TriggerKey;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.scheduling.annotation.Scheduled;

import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

import java.util.List;

/**

* @description

* @author yuanwei

* @date 2021/1/6 11:17

*/

@Component

@Slf4j

public class JobRefresh {

@Autowired

private JobDefDAO jobDefDAO;

@Autowired

private Scheduler scheduler;

@SuppressWarnings("unchecked")

@Scheduled(cron = "0 0 1 * * ?") // 每天凌晨1点刷新一次

@PostConstruct // 应用启动时刷新一次,方便测试,后续可以去掉

public void refreshTrigger() throws SchedulerException {

final List jobDefs = jobDefDAO.listAll();

for (final JobDefPO jobDef : jobDefs) {

final TriggerKey triggerKey = TriggerKey.triggerKey(jobDef.getJobName(), jobDef.getJobGroup());

CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);

if (null == trigger) {

// 状态(0:正常,1:禁用)

if (jobDef.getStatus().intValue() == 1) {

continue;

}

JobDetail jobDetail = null;

try {

jobDetail = JobBuilder.newJob((Class extends Job>) Class.forName(jobDef.getJobName()))

.withIdentity(jobDef.getJobName(), jobDef.getJobGroup()).build();

} catch (final ClassNotFoundException ex) {

log.error(ex.getMessage(), ex);

throw new RuntimeException("刷新任务异常");

}

final CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(jobDef.getCron());

trigger = TriggerBuilder.newTrigger().withIdentity(jobDef.getJobName(), jobDef.getJobGroup())

.withSchedule(scheduleBuilder).build();

scheduler.scheduleJob(jobDetail, trigger);

} else {

if (jobDef.getStatus().intValue() == 1) {

final JobKey jobKey = JobKey.jobKey(jobDef.getJobName(), jobDef.getJobGroup());

scheduler.deleteJob(jobKey);

continue;

}

final String selectedCron = jobDef.getCron();

final String currentCron = trigger.getCronExpression();

if (!selectedCron.equals(currentCron)) {

final CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(selectedCron);

trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder)

.build();

scheduler.rescheduleJob(triggerKey, trigger);

}

}

}

}

}

(5)添加定时任务

import lombok.extern.slf4j.Slf4j;

import org.quartz.Job;

import org.quartz.JobExecutionContext;

import org.quartz.JobExecutionException;

import java.util.Date;

/**

* @description

* @author yuanwei

* @date 2021/1/6 16:38

*/

@Slf4j

public class DemoJobHandler implements Job {

@Override

public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {

Date time = new Date();

log.info("时间:{},打印",time);

}

}

(6)在数据库中添加(5)中任务的触发时间

其中status中0为开启,1为关闭。

INSERT INTO `fund`.`JOB_DEF`(`JOB_NAME`, `JOB_GROUP`, `CRON`, `STATUS`) VALUES ('com.yw.quartzdemo.handler.DemoJobHandler', 'demo', '* * * * * ?', 0);

 类似资料: