spring boot 集成quartz集群

一:首先引入quartz集群所需要的jar包,官网上下载quartz,里面有sql for mysql的数据库创建语句,创建11张表。


二:配置工厂

@Configuration
public class QuartzConfig {

@Value("${quartz.scheduler.instanceName}")
private String quartzInstanceName;

@Value("${org.quartz.dataSource.myDS.driver}")
private String myDSDriver;

@Value("${org.quartz.dataSource.myDS.URL}")
private String myDSURL;

@Value("${org.quartz.dataSource.myDS.user}")
private String myDSUser;

@Value("${org.quartz.dataSource.myDS.password}")
private String myDSPassword;

@Value("${org.quartz.dataSource.myDS.maxConnections}")
private String myDSMaxConnections;


/**
* 设置属性
* @return
* @throws IOException
*/
private Properties quartzProperties() throws IOException {
Properties prop = new Properties();
prop.put("quartz.scheduler.instanceName", quartzInstanceName);
prop.put("org.quartz.scheduler.instanceId", "AUTO");
prop.put("org.quartz.scheduler.skipUpdateCheck", "true");
prop.put("org.quartz.scheduler.jmx.export", "true");

prop.put("org.quartz.jobStore.class", "org.quartz.impl.jdbcjobstore.JobStoreTX");
prop.put("org.quartz.jobStore.driverDelegateClass", "org.quartz.impl.jdbcjobstore.StdJDBCDelegate");
prop.put("org.quartz.jobStore.dataSource", "quartzDataSource");
prop.put("org.quartz.jobStore.tablePrefix", "QRTZ_");
prop.put("org.quartz.jobStore.isClustered", "true");

prop.put("org.quartz.jobStore.clusterCheckinInterval", "20000");
prop.put("org.quartz.jobStore.dataSource", "myDS");
prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "1");
prop.put("org.quartz.jobStore.misfireThreshold", "120000");
prop.put("org.quartz.jobStore.txIsolationLevelSerializable", "true");
prop.put("org.quartz.jobStore.selectWithLockSQL", "SELECT * FROM {0}LOCKS WHERE LOCK_NAME = ? FOR UPDATE");

prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");
prop.put("org.quartz.threadPool.threadCount", "10");
prop.put("org.quartz.threadPool.threadPriority", "5");
prop.put("org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread", "true");


prop.put("org.quartz.plugin.triggHistory.class", "org.quartz.plugins.history.LoggingJobHistoryPlugin");
prop.put("org.quartz.plugin.shutdownhook.class", "org.quartz.plugins.management.ShutdownHookPlugin");
prop.put("org.quartz.plugin.shutdownhook.cleanShutdown", "true");
return prop;
}

@Bean
public SchedulerFactoryBean schedulerFactoryBean(@Qualifier("dialogJobTrigger") Trigger cronJobTrigger) throws IOException, PropertyVetoException {
SchedulerFactoryBean factory = new SchedulerFactoryBean();
// this allows to update triggers in DB when updating settings in config file:
//用于quartz集群,QuartzScheduler 启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了
factory.setOverwriteExistingJobs(true);
//用于quartz集群,加载quartz数据源
//factory.setDataSource(dataSource);
//QuartzScheduler 延时启动,应用启动完10秒后 QuartzScheduler 再启动
factory.setStartupDelay(10);
//用于quartz集群,加载quartz数据源配置
factory.setQuartzProperties(quartzProperties());
factory.setAutoStartup(true);
factory.setApplicationContextSchedulerContextKey("applicationContext");
factory.setDataSource(createDataSource());
//注册触发器
factory.setTriggers(cronJobTrigger);//直接使用配置文件
// factory.setConfigLocation(new FileSystemResource(this.getClass().getResource("/quartz.properties").getPath()));
return factory;
}


/**
* 加载job
* @return
*/
@Bean()
public JobDetailFactoryBean updateDialogStatusJobDetail() {
return createJobDetail(InvokingJobDetailDetailFactory.class, "updateDialogStatusGroup", "dialogJob");
}

/**
* 加载触发器
* @param jobDetail
* @return
*/
@Bean(name = "dialogJobTrigger")
public CronTriggerFactoryBean dialogStatusJobTrigger(@Qualifier("updateDialogStatusJobDetail") JobDetail jobDetail) {
return dialogStatusTrigger(jobDetail, "0 0/1 * * * ?");
}



@Bean
public ComboPooledDataSource createDataSource() throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setDriverClass(myDSDriver);
dataSource.setJdbcUrl(myDSURL);
dataSource.setUser(myDSUser);
dataSource.setPassword(myDSPassword);
return dataSource;
}
/**
* 创建job工厂
* @param jobClass
* @param groupName
* @param targetObject
* @return
*/
private static JobDetailFactoryBean createJobDetail(Class<?> jobClass, String groupName, String targetObject) {
JobDetailFactoryBean factoryBean = new JobDetailFactoryBean();
factoryBean.setJobClass(jobClass);
factoryBean.setDurability(true);
factoryBean.setRequestsRecovery(true);
factoryBean.setGroup(groupName);
Map<String, String> map = new HashMap<>();
map.put("targetObject", targetObject);
map.put("targetMethod", "loadHisByProdHis");
map.put("targetMethod2", "loadHisByCtProdHis");
factoryBean.setJobDataAsMap(map);
return factoryBean;
}

/**
* 创建触发器工厂
* @param jobDetail
* @param cronExpression
* @return
*/
private static CronTriggerFactoryBean dialogStatusTrigger(JobDetail jobDetail, String cronExpression) {
CronTriggerFactoryBean factoryBean = new CronTriggerFactoryBean();
factoryBean.setJobDetail(jobDetail);
factoryBean.setCronExpression (cronExpression);
return factoryBean;
}

}

三:任务执行器

public class InvokingJobDetailDetailFactory extends QuartzJobBean { // 计划任务所在类 private String targetObject; // 具体需要执行的计划任务 private String targetMethod; private String targetMethod2; private ApplicationContext ctx; @Override protected void executeInternal(JobExecutionContext context) throws JobExecutionException { try { Object otargetObject = ctx.getBean(targetObject); Method m = null; Method m2 = null; try { m = otargetObject.getClass().getMethod(targetMethod); m2 = otargetObject.getClass().getMethod(targetMethod2); m2.invoke(otargetObject); m.invoke(otargetObject); } catch (SecurityException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } } catch (Exception e) { throw new JobExecutionException(e); } } public void setApplicationContext(ApplicationContext applicationContext) { this.ctx = applicationContext; } public void setTargetObject(String targetObject) { this.targetObject = targetObject; } public void setTargetMethod(String targetMethod) { this.targetMethod = targetMethod; } public void setTargetMethod2(String targetMethod2) { this.targetMethod2 = targetMethod2; } }