/**
* @Author: rhb
* @Date: 2020/9/29 19:22
* @Description: quartz核心配置类
*/
@Configuration
public class QuartzConfig {
@Value("${quartz.driverClassName}")
private String driverClassName;
@Value("${quartz.url}")
private String url;
@Value("${quartz.username}")
private String username;
@Value("${quartz.password}")
private String password;
@Value("${quartz.maxConnections}")
private String maxConnections;
@Value("${quartz.publickey}")
private String publicKey;
@Bean
public Properties quartzProperties() throws Exception {
password = ConfigTools.decrypt(publicKey, password);
PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
Properties prop = new Properties();
// scheduler配置
prop.put("org.quartz.scheduler.instanceName", "DouYinQuartzScheduler"); // 调度器的实例名
prop.put("org.quartz.scheduler.instanceId", "AUTO"); // 自动生成id
prop.put("org.quartz.scheduler.skipUpdateCheck", "true"); // 跳过更新
// JobStore配置
prop.put("org.quartz.jobStore.isClustered", "true"); //启用集群
prop.put("org.quartz.jobStore.tablePrefix", "QRTZ_"); // 表名前缀
prop.put("org.quartz.jobStore.dataSource", "quartzDataSource"); // 定义datasource名称
prop.put("org.quartz.jobStore.class", "org.quartz.impl.jdbcjobstore.JobStoreTX"); // 持久化
prop.put("org.quartz.jobStore.driverDelegateClass", "org.quartz.impl.jdbcjobstore.StdJDBCDelegate"); // JDBC的驱动程序
prop.put("org.quartz.jobStore.selectWithLockSQL", "SELECT * FROM {0}LOCKS WHERE LOCK_NAME = ? FOR UPDATE");
prop.put("org.quartz.jobStore.txIsolationLevelSerializable","true"); // 防止数据库在高负载下锁定超时以及“持久”事务
// ThreadPool配置
prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool"); // 线程池的名字
prop.put("org.quartz.threadPool.threadCount", "5"); // 指定线程数量
prop.put("org.quartz.threadPool.threadPriority", "5"); // 线程优先级(1-10)默认为5
prop.put("org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread", "true");
// mysql数据源配置
prop.put("org.quartz.dataSource.quartzDataSource.driver", driverClassName);
prop.put("org.quartz.dataSource.quartzDataSource.URL", url);
prop.put("org.quartz.dataSource.quartzDataSource.user", username);
prop.put("org.quartz.dataSource.quartzDataSource.password", password);
prop.put("org.quartz.dataSource.quartzDataSource.maxConnections", maxConnections);
prop.put("org.quartz.dataSource.quartzDataSource.provider","hikaricp");
prop.put("org.quartz.dataSource.quartzDataSource.maximumPoolSize","10");
prop.put("org.quartz.dataSource.quartzDataSource.connectionTestQuery","SELECT 1");
prop.put("org.quartz.dataSource.quartzDataSource.validationTimeout","5000");
prop.put("org.quartz.dataSource.quartzDataSource.idleTimeout","0");
//在quartz.properties中的属性被读取并注入后再初始化对象
propertiesFactoryBean.setProperties(prop);
propertiesFactoryBean.afterPropertiesSet();
return propertiesFactoryBean.getObject();
}
@Bean
public JobFactory jobFactory(ApplicationContext applicationContext){
AutowiredSpringBeanJobFactory jobFactory = new AutowiredSpringBeanJobFactory();
jobFactory.setApplicationContext(applicationContext);
return jobFactory;
}
@Bean
public SchedulerFactoryBean schedulerFactoryBean(JobFactory jobFactory){
SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
//可选,QuartzScheduler启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录
schedulerFactoryBean.setOverwriteExistingJobs(true);
//设置自动启动
schedulerFactoryBean.setAutoStartup(true);
schedulerFactoryBean.setJobFactory(jobFactory);
try {
schedulerFactoryBean.setQuartzProperties(quartzProperties());
} catch (Exception e) {
e.printStackTrace();
}
return schedulerFactoryBean;
}
/**
* 初始注入scheduler
*/
@Bean(name = "Scheduler")
public Scheduler scheduler(SchedulerFactoryBean schedulerFactoryBean) throws SchedulerException {
return schedulerFactoryBean.getScheduler();
}
/**
* quartz初始化监听器 : 这个监听器可以监听到工程的启动,在工程停止再启动时可以让已有的定时任务继续进行。
*/
@Bean
public QuartzInitializerListener executorListener() {
return new QuartzInitializerListener();
}
/**
* 解决:Job的创建是有Quartz通过反射创建的,并未交由Spring容器创建。故原则上来说,是无法在Job实例中使用依赖注入的。
*/
public final class AutowiredSpringBeanJobFactory extends SpringBeanJobFactory implements ApplicationContextAware {
/**
* AutowireCapableBeanFactory: 是在BeanFactory的基础上实现对已存在实例的管理。
* 可以使用这个接口集成其他框架,捆绑并填充并不由Spring管理生命周期并已存在的实例。
* 参考: https://www.jianshu.com/p/14dd69b5c516
*/
private AutowireCapableBeanFactory beanFactory;
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
this.beanFactory = applicationContext.getAutowireCapableBeanFactory();
}
@Override
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
Object jobInstance = super.createJobInstance(bundle);
beanFactory.autowireBean(jobInstance);
return jobInstance;
}
}
}
/**
* @Author: rhb
* @Date: 2020/9/30 15:11
* @Description: Job基础服务
*/
@Slf4j
@Service
@Transactional
public class JobBaseServiceImpl implements JobBaseService {
@Autowired
SchedulerFactoryBean schedulerFactoryBean;
private Scheduler scheduler;
@PostConstruct
public void init(){
this.scheduler = schedulerFactoryBean.getScheduler();
}
@Override
public Result addJob(JobDTO jobDTO) {
try {
Class cla = Class.forName(jobDTO.getClassJobPath());
JobDetail jobDetail = JobBuilder.newJob(cla)
.withIdentity(jobDTO.getClassJobName(),jobDTO.getClassJobGroup())
.withDescription(jobDTO.getClassJobDescription())
.storeDurably(true)
.build();
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(jobDTO.getClassJobCron());
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity(jobDTO.getClassJobName(),jobDTO.getClassJobGroup())
.withDescription(jobDTO.getClassJobDescription())
.withSchedule(cronScheduleBuilder)
.build();
scheduler.scheduleJob(jobDetail,trigger);
} catch (ClassNotFoundException e) {
log.info("Job基础服务 | 添加失败 | 类路径错误");
Assert.isTrue(false,"类路径错误");
} catch (SchedulerException e) {
log.info("Job基础服务 | 添加失败 | cron表达式错误");
Assert.isTrue(false,"cron表达式错误");
}
return ResultUtils.success("添加成功");
}
@Override
public Result deleteJob(JobDTO jobDTO) {
try {
TriggerKey triggerKey = TriggerKey.triggerKey(jobDTO.getClassJobName(), jobDTO.getClassJobGroup());
JobKey jobKey = JobKey.jobKey(jobDTO.getClassJobName(),jobDTO.getClassJobGroup());
scheduler.pauseTrigger(triggerKey);
scheduler.unscheduleJob(triggerKey);
scheduler.deleteJob(jobKey);
} catch (SchedulerException e) {
log.info("Job基础服务 | 删除失败 | "+e.getMessage());
Assert.isTrue(false,e.getMessage());
}
return ResultUtils.success("删除成功");
}
@Override
public Result rescheduleJob(JobDTO jobDTO) {
TriggerKey triggerKey = TriggerKey.triggerKey(jobDTO.getClassJobName(),jobDTO.getClassJobGroup());
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(jobDTO.getClassJobCron());
try {
CronTrigger cronTrigger = (CronTrigger) scheduler.getTrigger(triggerKey);
cronTrigger.getTriggerBuilder().withSchedule(cronScheduleBuilder).build();
scheduler.rescheduleJob(triggerKey,cronTrigger);
} catch (SchedulerException e) {
log.info("Job基础服务 | 重启失败 | "+e.getMessage());
Assert.isTrue(false,e.getMessage());
}
return ResultUtils.success("重启成功");
}
@Override
public Result pauseJob(JobDTO jobDTO) {
JobKey jobKey = JobKey.jobKey(jobDTO.getClassJobName(),jobDTO.getClassJobGroup());
try {
scheduler.pauseJob(jobKey);
} catch (SchedulerException e) {
log.info("Job基础服务 | 暂停失败 | "+e.getMessage());
Assert.isTrue(false,e.getMessage());
}
return ResultUtils.success("暂停成功");
}
@Override
public Result resumeJob(JobDTO jobDTO) {
JobKey jobKey = JobKey.jobKey(jobDTO.getClassJobName(),jobDTO.getClassJobGroup());
try {
scheduler.resumeJob(jobKey);
} catch (SchedulerException e) {
log.info("Job基础服务 | 恢复失败 | "+e.getMessage());
Assert.isTrue(false,e.getMessage());
}
return ResultUtils.success("恢复成功");
}
}
<!--quartz依赖-->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<exclusions>
<exclusion>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP-java7</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>3.3.1</version>
</dependency>