导入jar包
<!-- 分布式任务 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
<version>2.6.14</version>
</dependency>
QuartzJobFactory
/** * 注册 Quartz 任务工厂 * 解决job中service注入为空的问题 */ @Component public class QuartzJobFactory extends AdaptableJobFactory { @Resource private AutowireCapableBeanFactory capableBeanFactory; @Override protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception { //调用父类的方法 Object jobInstance = super.createJobInstance(bundle); //进行注入 capableBeanFactory.autowireBean(jobInstance); return jobInstance; } }
QuartzConfig
/** * 注册调度工厂, 使用spring默认的数据源, 只需将SchedulerFactoryBean注入就可 */ @Configuration public class QuartzConfig { @Resource private QuartzJobFactory quartzJobFactory; @Bean public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource) { SchedulerFactoryBean factory = new SchedulerFactoryBean(); factory.setDataSource(dataSource); // quartz 参数 Properties prop = new Properties(); prop.put("org.quartz.scheduler.instanceName", "SsmScheduler"); prop.put("org.quartz.scheduler.instanceId", "AUTO"); prop.put("org.quartz.scheduler.wrapJobExecutionInUserTransaction", "false"); //是否在Quartz执行一个job前使用UserTransaction // 线程池的配置 prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool"); prop.put("org.quartz.threadPool.threadCount", "20"); prop.put("org.quartz.threadPool.threadPriority", "5"); prop.put("org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread", "true"); // 配置是否启动自动加载数据库内的定时任务,默认true prop.put("org.quartz.threadPool.makeThreadsDaemons", "true"); //是否设置为守护线程,设置后任务将不会执行 // JobStore配置 prop.put("org.quartz.jobStore.class", "org.springframework.scheduling.quartz.LocalDataSourceJobStore"); // 集群配置 prop.put("org.quartz.jobStore.isClustered", "true"); prop.put("org.quartz.jobStore.clusterCheckinInterval", "15000"); //调度实例失效的检查时间间隔,单位毫秒 prop.put("org.quartz.jobStore.misfireThreshold", "12000"); prop.put("org.quartz.jobStore.tablePrefix", "QRTZ_"); prop.put("org.quartz.jobStore.selectWithLockSQL", "SELECT * FROM {0}LOCKS UPDLOCK WHERE LOCK_NAME = ?"); //mysql 数据库 prop.put("org.quartz.jobStore.driverDelegateClass", "org.quartz.impl.jdbcjobstore.StdJDBCDelegate"); factory.setQuartzProperties(prop); // 延时启动 factory.setStartupDelay(10); factory.setApplicationContextSchedulerContextKey("applicationContextKey"); factory.setJobFactory(quartzJobFactory); // 这样当spring关闭时,会等待所有已经启动的quartz job结束后spring才能完全shutdown factory.setWaitForJobsToCompleteOnShutdown(true); // 是否覆盖己存在的Job factory.setOverwriteExistingJobs(false); return factory; } @Bean public Scheduler scheduler(DataSource dataSource) { return schedulerFactoryBean(dataSource).getScheduler(); } }
表结构如下(常用表)
SELECT * from t_sox_schedule_log
SELECT * from qrtz_job_details
SELECT * from qrtz_triggers
SELECT * from qrtz_scheduler_state
开始/关闭任务方法
@Slf4j
@RestController
@RequestMapping("/sox-schedule-log")
@Api(tags = "定时任务查询控制器")
public class TSoxScheduleLogController {@Resource
private TSoxScheduleLogService tSoxScheduleLogService;
/**
* 开启一个分布式任务
* @return
*/
@ApiOperation(value = "开启一个分布式任务", notes = "开启一个分布式任务", httpMethod = "GET")
@GetMapping("/on/{id}")
public ReturnStruct on(@PathVariable String id) {
tSoxScheduleLogService.on(id);
return ReturnStruct.success();
}@ApiOperation(value = "关闭一个分布式任务", notes = "关闭一个分布式任务", httpMethod = "GET")
@GetMapping("/off/{id}")
public ReturnStruct off(@PathVariable String id) {
tSoxScheduleLogService.off(id);
return ReturnStruct.success();
}}
/**
* <p>
* 任务创建和执行信息 服务实现类
* </p>
*/
@Service
public class TSoxScheduleLogServiceImpl extends ServiceImpl<TSoxScheduleLogMapper, TSoxScheduleLog> implements TSoxScheduleLogService {@Resource
private QuartzJobService quartzJobService;@Override
public boolean on(String id) {
TSoxScheduleLog scheduleLog = this.baseMapper.selectById(id);
if(null == scheduleLog) {
throw new ResultEnumException("data_is_no_exist", new String[]{ id });
}
scheduleLog.setDelFlag(Constant.STR_0);
scheduleLog.setUpdateBy(ThreadLocalParams.LOGIN_MANAGER.get().getNo());
scheduleLog.setUpdateTime(LocalDateTime.now());
this.baseMapper.updateById(scheduleLog);
// 创建任务
QuartzConfigDTO quartzConfigDTO = new QuartzConfigDTO();
quartzConfigDTO.setJobName(scheduleLog.getTaskId());
quartzConfigDTO.setJobClass(scheduleLog.getExecBody()); // 实现类
if(StrUtil.isNotBlank(scheduleLog.getExecCron())) {
quartzConfigDTO.setCronExpression(scheduleLog.getExecCron());
quartzJobService.addCronJob(quartzConfigDTO);
}else if(null != scheduleLog.getExecTime()) {
quartzConfigDTO.setStartTime(new DateTime(scheduleLog.getExecTime()));
if(null != scheduleLog.getExecInterval()) {
quartzConfigDTO.setInterval(scheduleLog.getExecInterval());
}
quartzJobService.addSimpleJob(quartzConfigDTO);
}
return true;
}@Override
public boolean off(String id) {
TSoxScheduleLog scheduleLog = this.baseMapper.selectById(id);
if(null == scheduleLog) {
throw new ResultEnumException("data_is_no_exist", new String[]{ id });
}
scheduleLog.setDelFlag(Constant.STR_1);
scheduleLog.setUpdateBy(ThreadLocalParams.LOGIN_MANAGER.get().getNo());
scheduleLog.setUpdateTime(LocalDateTime.now());
this.baseMapper.updateById(scheduleLog);
// 删除任务
quartzJobService.deleteJob(scheduleLog.getTaskId(), null);
return true;
}
}
定时任务demo
import lombok.extern.slf4j.Slf4j; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.scheduling.quartz.QuartzJobBean; import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.List; /** * 测试定时任务 */ @Slf4j @Component public class TSoxTestJob extends QuartzJobBean { @Autowired private MailService mailService; @Override protected void executeInternal(JobExecutionContext context) throws JobExecutionException { log.info("====================================== 测试任务开始"); log.info("====================================== 测试任务结束"); } }