Pom-xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
Quartz调度所需要的依赖 quartz-jobs+c3p0,其他的可在创建SpringBoot项目时勾选jdbc、mysql、quartz、mybatis等
application.properties
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.url=jdbc:mysql://localhost:3306/cn?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
项目所需要连接的数据库,cn是MySQL的库 。com.mysql.cj.jdbc.Driver,新版连接
scheduletrigger
-- ----------------------------
-- Table structure for `scheduletrigger`
-- ----------------------------
DROP TABLE IF EXISTS `scheduletrigger`;
CREATE TABLE `scheduletrigger` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`cron` varchar(255) DEFAULT NULL,
`status` varchar(255) DEFAULT NULL,
`jobName` varchar(255) DEFAULT NULL,
`jobGroup` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of scheduletrigger
-- ----------------------------
INSERT INTO `scheduletrigger` VALUES ('1', '*/3 * * * * ?', '1', 'com.hc.quartzboot.quartz.MyJob', 'hc');
INSERT INTO `scheduletrigger` VALUES ('2', '*/10 * * * * ?', '1', 'com.hc.quartzboot.quartz.MyJobs', 'hc');
MySQL中的任务表 ,cron是表达式,jobname是任务的路径,com.hc.quartzboot.quartz.MyJobs
quartz提供的表官方Quartz--MySQL版的表共11张 表
quartz.properties
org.quartz.scheduler.instanceName: DefaultQuartzScheduler
org.quartz.scheduler.instanceId = AUTO
org.quartz.scheduler.rmi.export: false
org.quartz.scheduler.rmi.proxy: false
org.quartz.scheduler.wrapJobExecutionInUserTransaction: false
org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount: 10
org.quartz.threadPool.threadPriority: 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true
org.quartz.jobStore.misfireThreshold: 60000
org.quartz.jobStore.class:org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass:org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.useProperties:true
org.quartz.jobStore.tablePrefix:qrtz_
org.quartz.jobStore.dataSource:qzDS
org.quartz.jobStore.isClustered = true
org.quartz.dataSource.qzDS.driver:com.mysql.cj.jdbc.Driver
org.quartz.dataSource.qzDS.URL:jdbc:mysql://localhost:3306/cn?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false
org.quartz.dataSource.qzDS.user:root
org.quartz.dataSource.qzDS.password:root
org.quartz.dataSource.qzDS.maxConnections:10
ScheduleTrigger
package com.hc.quartzboot.model;
public class ScheduleTrigger {
private Integer id;
private String cron;
private String status;
private String jobName;
private String jobGroup;
public ScheduleTrigger(Integer id, String cron, String status, String jobName, String jobGroup) {
this.id = id;
this.cron = cron;
this.status = status;
this.jobName = jobName;
this.jobGroup = jobGroup;
}
public ScheduleTrigger() {
super();
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getCron() {
return cron;
}
public void setCron(String cron) {
this.cron = cron;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getJobName() {
return jobName;
}
public void setJobName(String jobName) {
this.jobName = jobName;
}
public String getJobGroup() {
return jobGroup;
}
public void setJobGroup(String jobGroup) {
this.jobGroup = jobGroup;
}
}
ScheduleTriggerMapper
package com.hc.quartzboot.mapper;
import com.hc.quartzboot.model.ScheduleTrigger;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public interface ScheduleTriggerMapper {
@Select(" select * from ScheduleTrigger")
List<ScheduleTrigger> queryAll();
}
MyJob
package com.hc.quartzboot.quartz;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.Date;
@Component
public class MyJob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
System.out.println("任务执行中..." + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS").format(new Date()));
}
}
MyJobFactory
package com.hc.quartzboot.quartz;
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 MyJobFactory extends AdaptableJobFactory {
@Autowired
private AutowireCapableBeanFactory capableBeanFactory;
@Override
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
//通过quartz框架中的创建作业的方法创建一个作业对象
Object jobInstance = super.createJobInstance(bundle);
capableBeanFactory.autowireBean(jobInstance); //这一步解决不能spring注入bean的问题
return jobInstance;
}
}
MyJobs
package com.hc.quartzboot.quartz;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.Date;
@Component
public class MyJobs implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
System.out.println("任务222执行中..." + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS").format(new Date()));
}
}
QuartzConfiguration
package com.hc.quartzboot.quartz;
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 QuartzConfiguration {
@Autowired
private MyJobFactory myJobFactory; //自定义的factory
//获取工厂bean(获取任务调度器工厂)
@Bean
public SchedulerFactoryBean schedulerFactoryBean() {
SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
try {
schedulerFactoryBean.setQuartzProperties(quartzProperties());
schedulerFactoryBean.setJobFactory(myJobFactory);
return schedulerFactoryBean;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
//指定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();
}
}
ScheduleTriggerServiceImpl
package com.hc.quartzboot.service.impl;
import com.hc.quartzboot.mapper.ScheduleTriggerMapper;
import com.hc.quartzboot.model.ScheduleTrigger;
import com.hc.quartzboot.service.ScheduleTriggerService;
import org.quartz.*;
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 ScheduleTriggerServiceImpl implements ScheduleTriggerService {
@Autowired
private Scheduler scheduler;
@Autowired
private ScheduleTriggerMapper scheduleTriggerMapper;
@Override
//@Scheduled(cron = "0 0 23:00 * * ?") //每天晚上11点调用这个方法来更新quartz中的任务
@Scheduled(cron = "*/10 * * * * ?") //每隔30秒执行一次更新quartz中的任务,调小一点好测试
public void refreshTrigger() {
try {
System.out.println("ScheduleTriggerService.refreshTrigger");
//查询出数据库中所有的定时任务
List<ScheduleTrigger> jobList = scheduleTriggerMapper.queryAll();
if (jobList != null) {
for (ScheduleTrigger scheduleJob : jobList) {
String status = scheduleJob.getStatus(); //该任务触发器目前的状态
TriggerKey triggerKey = TriggerKey.triggerKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
//说明本条任务还没有添加到quartz中
if (null == trigger) {
if (status.equals("0")) { //如果是禁用,则不用创建触发器
continue;
}
JobDetail jobDetail = null;
try {
//创建JobDetail(数据库中job_name存的任务全路径,这里就可以动态的把任务注入到JobDetail中)
jobDetail = JobBuilder.newJob((Class<? extends Job>) Class.forName(scheduleJob.getJobName()))
.withIdentity(scheduleJob.getJobName(), scheduleJob.getJobGroup()).build();
////TO//DO
// 可以添加一些额外的参数到任务的上下文中
//获取当前执行的任务id
// Integer id=scheduleJob.getId();
// //通过任务id获取参数表中的参数信息
// List<ScheduleTriggerParam> scheduleTriggerParams=scheduleTriggerParamMapper.findParamByJobId(id);
// JobDataMap jobDataMap=jobDetail.getJobDataMap();
// for (ScheduleTriggerParam param : scheduleTriggerParams) {
// jobDataMap.put(param.getName(),param.getValue());
// }
//表达式调度构建器
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob
.getCron());
//按新的cronExpression表达式构建一个新的trigger
trigger = TriggerBuilder.newTrigger().withIdentity(scheduleJob.getJobName(), scheduleJob.getJobGroup()).withSchedule(scheduleBuilder).build();
//把trigger和jobDetail注入到调度器
scheduler.scheduleJob(jobDetail, trigger);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} else { //说明查出来的这条任务,已经设置到quartz中了
// Trigger已存在,先判断是否需要删除,如果不需要,再判定是否时间有变化
if (status.equals("0")) { //如果是禁用,从quartz中删除这条任务
JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
scheduler.deleteJob(jobKey);
continue;
}
String searchCron = scheduleJob.getCron(); //获取数据库的
String currentCron = trigger.getCronExpression();
if (!searchCron.equals(currentCron)) { //说明该任务有变化,需要更新quartz中的对应的记录
//表达式调度构建器
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(searchCron);
//按新的cronExpression表达式重新构建trigger
trigger = trigger.getTriggerBuilder().withIdentity(triggerKey)
.withSchedule(scheduleBuilder).build();
//按新的trigger重新设置job执行
scheduler.rescheduleJob(triggerKey, trigger);
}
}
}
}
} catch (Exception e) {
System.out.println("定时任务每日刷新触发器任务异常,在ScheduleTriggerServiceImpl的方法refreshTrigger中,异常信息:"+e);
throw new RuntimeException(e);
}
}
}
QuartzbootApplication
package com.hc.quartzboot;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@SpringBootApplication
@EnableScheduling
@EnableTransactionManagement
@MapperScan("com.hc.quartzboot.mapper")
public class QuartzbootApplication {
public static void main(String[] args) {
SpringApplication.run(QuartzbootApplication.class, args);
}
}
启动即可