定时任务详细设计

编程

定时任务设计" title="详细设计">详细设计

定时任务使用QuartZ实现,QuartZ文档参考 https://www.w3cschool.cn/quartz_doc/

QuartZ配置

  1. 在数据库新建QuartZ数据表,相应的建表sql在当前目录下的QuartZ.sql文件中
  2. 添加quartz.properties文件,内部提供了QuartZ的相关配置

# 固定前缀org.quartz

# 主要分为scheduler、threadPool、jobStore、plugin等部分

org.quartz.scheduler.instanceName = DefaultQuartzScheduler

org.quartz.scheduler.rmi.export = false

org.quartz.scheduler.rmi.proxy = false

org.quartz.scheduler.wrapJobExecutionInUserTransaction = false

# 实例化ThreadPool时,使用的线程类为SimpleThreadPool

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

# threadCount和threadPriority将以setter的形式注入ThreadPool实例

# 并发个数

org.quartz.threadPool.threadCount = 5

# 优先级

org.quartz.threadPool.threadPriority = 5

org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true

org.quartz.jobStore.misfireThreshold = 60000

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

#持久化

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

org.quartz.jobStore.tablePrefix = QRTZ_

org.quartz.jobStore.dataSource = shop_mrg_admin_new

org.quartz.dataSource.shop_mrg_admin_new.driver = @datasource.driver@

org.quartz.dataSource.shop_mrg_admin_new.URL = @datasource.url@

org.quartz.dataSource.shop_mrg_admin_new.user = @datasource.username@

org.quartz.dataSource.shop_mrg_admin_new.password = @datasource.password@

org.quartz.dataSource.shop_mrg_admin_new.maxConnections = 10

# trigger执行日志显示

org.quartz.plugin.triggHistory.class =org.quartz.plugins.history.LoggingTriggerHistoryPlugin

org.quartz.plugin.triggHistory.triggerFiredMessage =Trigger {1}.{0} fired job {6}.{5} at: {4, date, HH:mm:ss MM/dd/yyyy}

org.quartz.plugin.triggHistory.triggerCompleteMessage =Trigger {1}.{0} completed firing job {6}.{5} at {4, date, HH:mm:ss MM/dd/yyyy}.

  1. 添加QuartZ配置 JobFactory、QuartzConfigration

import org.quartz.spi.TriggerFiredBundle;

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

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

import org.springframework.scheduling.quartz.AdaptableJobFactory;

import org.springframework.stereotype.Component;

@Component

public class JobFactory extends AdaptableJobFactory {

@Autowired

private AutowireCapableBeanFactory capableBeanFactory;

protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception{

Object jobInstance = super.createJobInstance(bundle);

capableBeanFactory.autowireBean(jobInstance);

return jobInstance;

}

}

import org.quartz.Scheduler;

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

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.SchedulerFactoryBean;

import java.io.IOException;

import java.util.Properties;

@Configuration

public class QuartzConfigration {

@Autowired

private JobFactory jobFactory;

//获取工厂bean

@Bean

public SchedulerFactoryBean schedulerFactoryBean() {

SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();

try {

schedulerFactoryBean.setQuartzProperties(quartzProperties());

//启动时更新已存在的job

schedulerFactoryBean.setOverwriteExistingJobs(true);

//自动启动

schedulerFactoryBean.setAutoStartup(true);

schedulerFactoryBean.setJobFactory(jobFactory);

} catch (IOException e) {

e.printStackTrace();

}

return schedulerFactoryBean;

}

//指定quartz.properties

@Bean

public Properties quartzProperties() throws IOException {

PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();

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

propertiesFactoryBean.afterPropertiesSet();

return propertiesFactoryBean.getObject();

}

//创建schedule

@Bean(name = "scheduler")

public Scheduler scheduler() {

return schedulerFactoryBean().getScheduler();

}

}

  1. 在数据库新建job信息表t_job_triggers,并提供对该表的基本增删改查操作(在下一步操作中需要用到对t_job_triggers表的查询操作),t_job_triggers的sql如下:

CREATE TABLE `t_job_triggers` (

`job_id` int(11) NOT NULL AUTO_INCREMENT COMMENT "主键",

`cron` varchar(100) COLLATE utf8_bin NOT NULL COMMENT "cron表达式",

`status` int(11) NOT NULL COMMENT "job状态 0=不启用,1=启用",

`job_name` varchar(100) COLLATE utf8_bin NOT NULL COMMENT "定时任务类名",

`job_group` varchar(100) COLLATE utf8_bin DEFAULT NULL COMMENT "用于和job_name一起确定解job的唯一性",

`job_decs` varchar(100) COLLATE utf8_bin DEFAULT NULL COMMENT "任务描述",

`job_param` varchar(300) COLLATE utf8_bin DEFAULT NULL COMMENT "可自定义的额外参数",

PRIMARY KEY (`job_id`) USING BTREE

) ENGINE=InnoDB AUTO_INCREMENT=110 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

  1. 添加一个spring Scheduled用于获取t_job_triggers中的job数据,示例如下:

import com.gkcx.fls.dao.TJobTriggers;

import com.gkcx.fls.mappers.TJobTriggersMapper;

import org.quartz.*;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

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

import org.springframework.scheduling.annotation.Scheduled;

import org.springframework.stereotype.Service;

import java.util.List;

@Service

public class ScheduleTriggerService {

private static final Logger logger = LoggerFactory.getLogger(ScheduleTriggerService.class);

@Autowired

private Scheduler scheduler;

@Autowired

private TJobTriggersMapper jobTriggersMapper;//t_job_triggers表Mapper

//定时更新quartz中的任务 每隔一分钟更新

@Scheduled(cron = "${scheduler.cron.trigger}")

public void refreshTrigger() {

try {

//查询出数据库中所有的定时任务

List<TJobTriggers> jobList = jobTriggersMapper.selectAll();

if (jobList != null) {

for (TJobTriggers jobTrigger : jobList) {

TriggerKey triggerKey = TriggerKey.triggerKey(jobTrigger.getJobName(), jobTrigger.getJobGroup());

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

//本条任务还没有添加到quartz中

if (cronTrigger == null) {

if (jobTrigger.getStatus() == 0) { //任务处于不启用的状态

continue;

}

//创建JobDetail(数据库中job_name存的任务全路径,这里就可以动态的把任务注入到JobDetail中)

JobDetail jobDetail = JobBuilder.newJob((Class<? extends Job>) Class.forName(jobTrigger.getJobName()))

.withIdentity(jobTrigger.getJobName(), jobTrigger.getJobGroup()).requestRecovery(true).build();

//表达式调度构建器

CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(jobTrigger

.getCron());

//按新的cronExpression表达式构建一个新的trigger

cronTrigger = TriggerBuilder.newTrigger().withIdentity(jobTrigger.getJobName(), jobTrigger.getJobGroup()).withSchedule(scheduleBuilder).build();

//把trigger和jobDetail注入到调度器

scheduler.scheduleJob(jobDetail, cronTrigger);

} else { //本条任务已经在quartz中了

//cronTrigger已存在,先判断是否需要删除,如果不需要,在判断时间是否又变化

if (jobTrigger.getStatus() == 0) { //如果是禁用,从quartz中删除这条任务

JobKey jobKey = JobKey.jobKey(jobTrigger.getJobName(), jobTrigger.getJobGroup());

scheduler.deleteJob(jobKey);

continue;

}

String searchCron = jobTrigger.getCron(); //获取数据库中的cron表达式

String currentCron = cronTrigger.getCronExpression();

if (!searchCron.equals(currentCron)) { //说明该任务有变化,需要更新quartz中的对应的记录

//表达式调度构建器

CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(searchCron);

//按新的cronExpression表达式重新构建trigger

cronTrigger = cronTrigger.getTriggerBuilder().withIdentity(triggerKey)

.withSchedule(scheduleBuilder).build();

//按新的trigger重新设置job执行

scheduler.rescheduleJob(triggerKey, cronTrigger);

}

}

}

}

} catch (Exception e) {

logger.info("定时任务刷新Quartz中job异常!");

e.printStackTrace();

}

}

}

开发人员文档

定时任务源码文件位置:可新建schedule包,例如:com.gkcx.fls.schedule

新建定时任务方法

  1. 在com.gkcx.fls.schedule.job中新建一个class,并实现org.quartz.Job接口。参考以下示例(TestTask.java):

import org.quartz.CronTrigger;

import org.quartz.Job;

import org.quartz.JobExecutionContext;

import org.quartz.JobExecutionException;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.stereotype.Component;

@Component

public class TestTask implements Job {

private static final Logger logger = LoggerFactory.getLogger(TestTask.class);

@Override

public void execute(JobExecutionContext context) throws JobExecutionException {

logger.info("TestTask开始执行。。。。");

try{

CronTrigger trigger = (CronTrigger) context.getTrigger();

logger.info("cron:{}", trigger.getCronExpression());

logger.info("jobName:{}", trigger.getKey().getName());

logger.info("jobGroup:{}", trigger.getKey().getGroup());

}catch (Exception e){

e.printStackTrace();

}finally {

logger.info("TestTask执行结束。。。。");

}

}

}

  1. 在数据库中的t_job_triggers中添加新建class信息。注意cron表达式和job_name的正确,否则会影响该定时任务的运行。 参考以下示例:

INSERT INTO t_job_triggers (job_id, cron, status, job_name, job_group, job_decs, job_param) VALUES(100, "0 21 10 * * ?", 0, "com.gkcx.fls.schedule.job.TestTask", "test", "测试用", NULL);

注意:

数据库中以QRTZ开头的表为QUARTZ持久化所需要的表,请不要修改。将定时任务功能迁移至生产环境时,同时需要将以QRTZ开头的表添加在生产数据库。

以上是 定时任务详细设计 的全部内容, 来源链接: utcz.com/z/515708.html

回到顶部