title: quartz扫描数据库启动多个定时任务
date: 2020-03-05 23:20:37
tags:
- quartz
categories: - 后端
数据库里存放了多个定时任务,通过扫描数据库,来进行定时任务的启动。
在上一篇博客中讲了quartz的依赖与application.properties的配置,这里就不介绍了。
配置文件
注册一个SchedulerFactoryBean
import lombok.AllArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
@Configuration //1.主要用于标记配置类,兼备Component的效果。
@AllArgsConstructor
@EnableScheduling
public class QuartzTask {
@Bean
SchedulerFactoryBean schedulerFactoryBean() {
SchedulerFactoryBean bean = new SchedulerFactoryBean();
return bean;
}
}
配置QuartzJob工厂
import java.lang.reflect.Method;
import com.swust.crawler.entity.SysCron;
import com.swust.utils.SpringContextHolder;
import com.swust.utils.StringUtils;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.PersistJobDataAfterExecution;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ReflectionUtils;
/**
* QuartzJob工厂
* @author xuchangcheng
* 2018年8月24日
*
*/
@PersistJobDataAfterExecution
public class QuartzJobFactory implements Job {
private static final Logger logger = LoggerFactory.getLogger(QuartzJobFactory.class);
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
// ScheduleJob scheduleJob = (ScheduleJob) context.getMergedJobDataMap().get("scheduleJob");
SysCron sysCron = (SysCron) context.getMergedJobDataMap().get("sysCron");
Class<?> clazz;
try {
clazz = Class.forName(sysCron.getClasspath());
String className = StringUtils.firstToLower(clazz.getSimpleName());
Object bean = (Object) SpringContextHolder.getBean(className);
Method method = ReflectionUtils.findMethod(bean.getClass(), sysCron.getMethod());
ReflectionUtils.invokeMethod(method, bean);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
logger.info("----------定时开始----------");
}
}
通过数据库扫描并启动任务
/**
* 开启定时任务
* @param id
*/
public void startQurtaz(int id){
//定时任务调度
Scheduler scheduler = (Scheduler)SpringContextHolder.getBean("schedulerFactoryBean");
SysCron cron = cronService.getById(id);
TriggerKey triggerKey = TriggerKey.triggerKey(cron.getName());
CronTrigger trigger;
try {
trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
} catch (SchedulerException e1) {
e1.printStackTrace();
}
JobDetail jobDetail = JobBuilder.newJob(QuartzJobFactory.class)
.withIdentity(cron.getName()).build();
jobDetail.getJobDataMap().put("sysCron", cron);//注意和QuartzJobFactory里面一样
//表达式调度构建器
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cron.getCron());
//按新的cronExpression表达式构建一个新的trigger
trigger = TriggerBuilder.newTrigger().withIdentity(cron.getName()).withSchedule(scheduleBuilder).build();
try {
scheduler.scheduleJob(jobDetail, trigger);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
工具栏 utils
这里使用了两个工具类,一个大小写转化,一个查找bean
public class StringUtils {
/**
* 首字母变小写
*
* @param str
* @return
*/
public static String firstToLower(String str) {
char firstChar = str.charAt(0);
if (firstChar >= 'A' && firstChar <= 'Z') {
char[] arr = str.toCharArray();
arr[0] += ('a' - 'A');
return new String(arr);
}
return str;
}
/**
* 首字母变大写
*
* @param str
* @return
*/
public static String firstToUpper(String str) {
char firstChar = str.charAt(0);
if (firstChar >= 'a' && firstChar <= 'z') {
char[] arr = str.toCharArray();
arr[0] -= ('a' - 'A');
return new String(arr);
}
return str;
}
}
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
/**
* @author lengleng
* @date 2018/6/27
* Spring 工具类
*/
@Slf4j
@Service
@Lazy(false)
public class SpringContextHolder implements ApplicationContextAware, DisposableBean {
private static ApplicationContext applicationContext = null;
/**
* 取得存储在静态变量中的ApplicationContext.
*/
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
/**
* 实现ApplicationContextAware接口, 注入Context到静态变量中.
*/
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
SpringContextHolder.applicationContext = applicationContext;
}
/**
* 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
*/
@SuppressWarnings("unchecked")
public static <T> T getBean(String name) {
return (T) applicationContext.getBean(name);
}
/**
* 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
*/
public static <T> T getBean(Class<T> requiredType) {
return applicationContext.getBean(requiredType);
}
/**
* 清除SpringContextHolder中的ApplicationContext为Null.
*/
public static void clearHolder() {
if (log.isDebugEnabled()) {
log.debug("清除SpringContextHolder中的ApplicationContext:" + applicationContext);
}
applicationContext = null;
}
/**
* 发布事件
*
* @param event
*/
public static void publishEvent(ApplicationEvent event) {
if (applicationContext == null) {
return;
}
applicationContext.publishEvent(event);
}
/**
* 实现DisposableBean接口, 在Context关闭时清理静态变量.
*/
@Override
public void destroy() {
SpringContextHolder.clearHolder();
}
}
数据库展示
quartzService是我的定时任务的方法存储地方。