定时任务详细设计
定时任务设计" title="详细设计">详细设计
定时任务使用QuartZ实现,QuartZ文档参考 https://www.w3cschool.cn/quartz_doc/
QuartZ配置
- 在数据库新建QuartZ数据表,相应的建表sql在当前目录下的QuartZ.sql文件中
- 添加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}.
- 添加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();
}
}
- 在数据库新建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;
- 添加一个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
新建定时任务方法
- 在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执行结束。。。。");
}
}
}
- 在数据库中的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