/** * 任务执行器 */ public interface BaseJob extends Job { void execute(JobExecutionContext context) throws JobExecutionException; }
加入spring
@Component public class MyJobFactory extends AdaptableJobFactory { //这个对象Spring会帮我们自动注入进来,也属于Spring技术范畴. @Autowired private AutowireCapableBeanFactory capableBeanFactory; @Override protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception { //调用父类的方法 Object jobInstance = super.createJobInstance(bundle); //进行注入,这属于Spring的技术,不清楚的可以查看Spring的API. capableBeanFactory.autowireBean(jobInstance); return jobInstance; } }
配置
@Configuration public class SchedulerConfig { @Autowired private MyJobFactory jobFactory; /** * 配置实例 * @return * @throws IOException */ @Bean(name = "SchedulerFactory") public SchedulerFactoryBean schedulerFactoryBean() throws IOException { SchedulerFactoryBean factory = new SchedulerFactoryBean(); factory.setQuartzProperties(quartzProperties()); factory.setJobFactory(jobFactory); return factory; } /** * 配置信息 * @return * @throws IOException */ @Bean public Properties quartzProperties() throws IOException { PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean(); propertiesFactoryBean.setLocation(new ClassPathResource("quartz.properties")); //在quartz.properties中的属性被读取并注入后再初始化对象 propertiesFactoryBean.afterPropertiesSet(); return propertiesFactoryBean.getObject(); } /** * 通过SchedulerFactoryBean获取Scheduler的实例 * 注意在实例化的时候需@Qualifier指定一下。 * @return * @throws IOException */ @Bean(name = "Scheduler") public Scheduler scheduler() throws IOException { return schedulerFactoryBean().getScheduler(); } }
/**
* 任务调度工具类
*/
@Slf4j
@Service
public class SchedulerUtils {
@Autowired
@Qualifier("Scheduler")
private Scheduler scheduler;
/**
* 重新配置任务调度。
* @param jobClassName 任务类名
* @param jobGroupName 组名
* @param cronExpression crontab表达式
*/
public void rescheduleJob(String jobClassName, String jobGroupName,String cronExpression){
try {
TriggerKey triggerKey = TriggerKey.triggerKey(jobClassName, jobGroupName);
// 表达式调度构建器
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
// 按新的cronExpression表达式重新构建trigger
trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
// 按新的trigger重新设置job执行
scheduler.rescheduleJob(triggerKey, trigger);
}
catch (Exception e){
log.error("rescheduleJob:"+e);
}
}
/**
* 暂停调度
* @param jobClassName 任务执行器类名
* @param jobGroupName 任务组名
*/
public void pauseJob(String jobClassName, String jobGroupName) {
try{
scheduler.pauseJob(JobKey.jobKey(jobClassName, jobGroupName));
}
catch (SchedulerException e) {
log.error("pauseJob:"+e);
}
}
/**
* 删除调度
* @param jobClassName 任务执行器类名
* @param jobGroupName 任务组名
*/
public void deleteJob(String jobClassName, String jobGroupName) {
try{
scheduler.deleteJob(JobKey.jobKey(jobClassName, jobGroupName));
}
catch (SchedulerException e) {
log.error("pauseJob:"+e);
}
}
/**
* 新增任务调度。jobClassName + jobGroupName,唯一标识一个任务
* 当用同一个jobclass,有多个定时执行策略时,通过修改groupname进行区分任务。
* @param jobClassName 任务执行器类名
* @param jobGroupName 任务组名
* @param cronExpression crontab表达式
*/
public void addJob(String jobClassName, String jobGroupName, String cronExpression){
try{
// 启动调度器
scheduler.start();
//构建job信息
JobDetail jobDetail = JobBuilder.newJob(getClass(jobClassName).getClass()).withIdentity(jobClassName, jobGroupName).build();
//表达式调度构建器(即任务执行的时间)
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);
//按新的cronExpression表达式构建一个新的trigger
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(jobClassName, jobGroupName).withSchedule(scheduleBuilder).build();
scheduler.scheduleJob(jobDetail, trigger);
}
catch (Exception e) {
log.error("addJob fail:" + e);
}
}
/**
*
* @param jobClassName 任务执行器类名
* @param jobGroupName 任务组名
*/
public void resumeJob(String jobClassName, String jobGroupName){
try{
scheduler.resumeJob(JobKey.jobKey(jobClassName, jobGroupName));
}
catch (SchedulerException e){
log.error("rescheduleJob:"+e);
}
}
/**
* 通过反射机制实例化 Job
* @param classname 任务执行器的类名
* @return
* @throws Exception
*/
public static BaseJob getClass(String classname) throws Exception {
Class<?> class1 = Class.forName(classname);
return (BaseJob) class1.newInstance();
}
}
quartz.properties
#============================================================================ # Configure Main Scheduler Properties #============================================================================ #实例名称 org.quartz.scheduler.instanceName=TestScheduler #建议就自动,需保证有唯一性,自动有自己机制保证。 org.quartz.scheduler.instanceId=AUTO #============================================================================ # Configure ThreadPool #============================================================================ #线程池方法,一般固定 org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool #线程个数,一般线程数=2*CPU核数,配置原则是需要并行执行的任务的个数。 #要保证任务阻塞后有新的线程执行新的任务。成本主要是开线程成本,不知道怎么配置的就64。 org.quartz.threadPool.threadCount=2 #优先级,不用动。 org.quartz.threadPool.threadPriority=5 #============================================================================ # Configure JobStore #============================================================================ #通过数据库方式分配集群调度。 org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX #集群方式执行 org.quartz.jobStore.isClustered=true #检查集群检测频率,默认15s。单位ms。 org.quartz.jobStore.clusterCheckinInterval = 3000 #任务失效时长,任务点+失效时长,超过改时长,就不会再执行改任务。 org.quartz.jobStore.misfireThreshold=60000 org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.PostgreSQLDelegate org.quartz.jobStore.useProperties=false org.quartz.jobStore.dataSource=myDS org.quartz.jobStore.tablePrefix=QRTZ_ #============================================================================ # Configure Datasources #============================================================================ #数据库连接配置,主要是对应的表连接所在位置,无特殊原因单独一个db存放。 org.quartz.dataSource.myDS.driver=org.postgresql.Driver org.quartz.dataSource.myDS.URL=jdbc:postgresql://***:5432/quartz?stringtype=unspecified org.quartz.dataSource.myDS.user=postgres org.quartz.dataSource.myDS.password=postgres org.quartz.dataSource.myDS.maxConnections=5 org.quartz.dataSource.myDS.validationQuery=select 0 #连接池 org.quartz.dataSource.myDS.provider=hikaricp
添加
package net.alphawind.common.jobUtil.service.impl; import java.util.Iterator; import java.util.List; import java.util.Map; import org.quartz.CronScheduleBuilder; import org.quartz.Job; import org.quartz.JobBuilder; import org.quartz.JobDetail; import org.quartz.JobKey; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.TriggerBuilder; import org.quartz.TriggerKey; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import lombok.extern.slf4j.Slf4j; import net.alphawind.common.jobUtil.dao.TimeJobDao; import net.alphawind.common.jobUtil.entity.JobSchedulerInfo; import net.alphawind.common.jobUtil.service.TimeJobService; @Slf4j @Service public class TimeJobServiceImpl implements TimeJobService { @Autowired private Scheduler scheduler; @Autowired private TimeJobDao dao; @Override public List<Map<String, Object>> queryJob() { List<Map<String, Object>> list = dao.queryJob(); return list.size()>0?list:null; } @Override public String addJob(JobSchedulerInfo job) { int r = dao.addJob(job); return r==0?"success":"fail"; } @Override public String updateJob(JobSchedulerInfo job) { int r = dao.updateJob(job); return r==0?"success":"fail"; } @Override public String deleteJob(JobSchedulerInfo job) { int r = dao.deleteJob(job); return r==0?"success":"fail"; } @Override public String startJob(JobSchedulerInfo job) throws Exception { String result =""; String jobClassName = job.getJobClassName(); String cronExpression = job.getCronExpression(); String parameter = job.getParameters(); try { // 启动调度器 scheduler.start(); // 构建job信息 JobDetail jobDetail = JobBuilder.newJob(getClass(jobClassName).getClass()).withIdentity(jobClassName).usingJobData("parameter", parameter).build(); // 表达式调度构建器(即任务执行的时间) CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression); // 按新的cronExpression表达式构建一个新的trigger org.quartz.CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(jobClassName).withSchedule(scheduleBuilder).build(); scheduler.scheduleJob(jobDetail, trigger); result = "定时任务 "+jobClassName+" 开启成功"; } catch (SchedulerException e) { e.printStackTrace(); result = "创建定时任务失败"; } catch (RuntimeException e) { e.printStackTrace(); result = e.getMessage(); }catch (Exception e) { e.printStackTrace(); result = "后台找不到该类名:" + jobClassName; } System.out.println(result); return result; } @Override public String stopJob(JobSchedulerInfo job) { String result = ""; try { scheduler.pauseTrigger(TriggerKey.triggerKey(job.getJobClassName())); scheduler.unscheduleJob(TriggerKey.triggerKey(job.getJobClassName())); scheduler.deleteJob(JobKey.jobKey(job.getJobClassName())); } catch (Exception e) { log.error(e.getMessage(), e); result = "删除定时任务失败"; } return result; } private static Job getClass(String classname) throws ClassNotFoundException, InstantiationException, IllegalAccessException { Class<?> class1 = Class.forName(classname); return (Job) class1.newInstance(); } public void initTimeJob() throws Exception { List<Map<String, Object>> list = dao.queryJob(); for (Iterator<Map<String, Object>> iterator = list.iterator(); iterator.hasNext();) { Map<String, Object> map = iterator.next(); // 0:项目启动时开启定时任务,1不开启 if(map.get("job_state").toString().equals("0")) { JobSchedulerInfo job = new JobSchedulerInfo(); job.setId(map.get("job_id").toString()); job.setCronExpression(map.get("job_cron").toString()); job.setJobClassName(map.get("job_class_name").toString()); job.setParameters(map.get("job_parameter").toString()); startJob(job); } } System.out.println("定时任务加载完毕!"); } }