Skip to content

Commit

Permalink
add spring boot quartz
Browse files Browse the repository at this point in the history
  • Loading branch information
527515025 committed Feb 1, 2019
1 parent 8dd2d28 commit ceb9a46
Show file tree
Hide file tree
Showing 8 changed files with 486 additions and 0 deletions.
72 changes: 72 additions & 0 deletions springboot-Quartz/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.abel.quartz</groupId>
<artifactId>springboot-Quartz</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

<!--quartz-->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.1</version>
</dependency>
<!--因为quartz 需要有Spring context 所有引入mail包-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>

<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>3.2.0</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.18.1</version>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
</plugins>
</build>
</project>
18 changes: 18 additions & 0 deletions springboot-Quartz/src/main/java/com/abel/quartz/Application.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.abel.quartz;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;

/**
* Created by yangyibo on 2019/2/1.
*/
@SpringBootApplication
@ImportResource("classpath*:META-INF/spring/*.xml")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package com.abel.quartz.config;

import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.quartz.QuartzJobBean;
import java.lang.reflect.Method;


/**
* Created by yangyibo on 2019/2/1.
*/
public class InvokingJobDetailFactory extends QuartzJobBean {

/**
* 计划任务所在类
*/
private String targetObject;

/**
* 具体需要执行的计划任务
*/
private String targetMethod;

private ApplicationContext ctx;

@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
try {
Object obj = ctx.getBean(targetObject);
Method m = null;
try {
m = obj.getClass().getMethod(targetMethod);
//调用被代理对象的方法
m.invoke(obj);
} 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;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
package com.abel.quartz.config;

import java.beans.PropertyVetoException;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import com.zaxxer.hikari.HikariDataSource;
import org.quartz.Job;
import org.quartz.JobDetail;
import org.quartz.Trigger;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
import org.springframework.scheduling.quartz.JobDetailFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;

/**
* Created by yangyibo on 2019/1/16.
*/
@Configuration
public class QuartzConfig {

/**
* 1.通过name+group获取唯一的jobKey;2.通过groupname来获取其下的所有jobkey
*/
final static String GROUP_NAME = "QuartzJobGroups";

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

@Value("${spring.datasource.driverClassName}")
private String myDSDriver;

@Value("${spring.datasource.url}")
private String myDSUrl;

@Value("${spring.datasource.username}")
private String myDSUser;

@Value("${spring.datasource.password}")
private String myDSPassword;

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

/**
* 设置属性
*
* @return
* @throws IOException
*/
private Properties quartzProperties() throws IOException {
Properties prop = new Properties();
// 调度标识名 集群中每一个实例都必须使用相同的名称
prop.put("quartz.scheduler.instanceName", quartzInstanceName);
// ID设置为自动获取 每一个必须不同
prop.put("org.quartz.scheduler.instanceId", "AUTO");
// 禁用quartz软件更新
prop.put("org.quartz.scheduler.skipUpdateCheck", "true");
prop.put("org.quartz.scheduler.jmx.export", "true");


// 数据库代理类,一般org.quartz.impl.jdbcjobstore.StdJDBCDelegate可以满足大部分数据库
prop.put("org.quartz.jobStore.driverDelegateClass", "org.quartz.impl.jdbcjobstore.StdJDBCDelegate");
// 数据保存方式为数据库持久化
prop.put("org.quartz.jobStore.class", "org.quartz.impl.jdbcjobstore.JobStoreTX");
// 数据库别名 随便取
prop.put("org.quartz.jobStore.dataSource", "quartzDataSource");
//prop.put("org.quartz.jobStore.dataSource", "myDS");
// 表的前缀,默认QRTZ_
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.maxMisfiresToHandleAtATime", "1");
// 信息保存时间 ms 默认值60秒
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");

// 程池的实现类(一般使用SimpleThreadPool即可满足几乎所有用户的需求)
prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");
// 定线程数,至少为1(无默认值)(一般设置为1-100之间的整数合适)
prop.put("org.quartz.threadPool.threadCount", "10");
// 设置线程的优先级(最大为java.lang.Thread.MAX_PRIORITY 10,最小为Thread.MIN_PRIORITY 1,默认为5)
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");

//#自定义连接池
//org.quartz.dataSource.myDS.connectionProvider.class=com.poly.pay.schedule.DruidConnectionProvider

return prop;
}

/**
* 数据源
*
* @return
* @throws PropertyVetoException
*/
@Bean
public HikariDataSource createDataSource() throws PropertyVetoException {
HikariDataSource dataSource = new HikariDataSource();
dataSource.setJdbcUrl(myDSUrl);
dataSource.setDriverClassName(myDSDriver);
dataSource.setUsername(myDSUser);
dataSource.setPassword(myDSPassword);
dataSource.setMaximumPoolSize(myDSMaxConnections);
return dataSource;
}


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


/****************************************************以下配置需要注意******************************************************/


/**
* 调度工厂
* 此处配置需要调度的触发器 例如 executeJobTrigger
*
* @param executeJobTrigger
* @return
* @throws IOException
* @throws PropertyVetoException
*/
@Bean
public SchedulerFactoryBean schedulerFactoryBean(@Qualifier("executeJobTrigger") Trigger executeJobTrigger) 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.setAutoStartup(true);
factory.setQuartzProperties(quartzProperties());
factory.setApplicationContextSchedulerContextKey("applicationContext");
factory.setDataSource(createDataSource());
//注册触发器
Trigger[] triggers = {executeJobTrigger};
factory.setTriggers(triggers);

return factory;
}


/**
* 加载触发器
*
* 新建触发器进行job 的调度 例如 executeJobDetail
* @param jobDetail
* @return
*/
@Bean(name = "executeJobTrigger")
public CronTriggerFactoryBean executeJobTrigger(@Qualifier("executeJobDetail") JobDetail jobDetail) {
//每天凌晨3点执行
return cronTriggerFactoryBean(jobDetail, "0 1 0 * * ? ");
}


/**
* 加载job
*
* 新建job 类用来代理
*
*
* @return
*/
@Bean
public JobDetailFactoryBean executeJobDetail() {
return createJobDetail(InvokingJobDetailFactory.class, GROUP_NAME, "executeJob");
}


/**
* 执行规则job工厂
*
* 配置job 类中需要定时执行的 方法 execute
* @param jobClass
* @param groupName
* @param targetObject
* @return
*/
private static JobDetailFactoryBean createJobDetail(Class<? extends Job> 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("targetMethod", "execute");
map.put("targetObject", targetObject);
factoryBean.setJobDataAsMap(map);
return factoryBean;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.abel.quartz.job;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

/**
* Created by yangyibo on 2019/2/1.
*/
@Service
public class ExecuteJob {
private static final Logger logger = LoggerFactory.getLogger(ExecuteJob.class);

/**
* 方法名在quartz定义
*/
public void execute() {
System.out.println("定时任务执行了。。。。。");

}
}
Loading

0 comments on commit ceb9a46

Please sign in to comment.