pom.xml配置
引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
数据库配置
application.properties
#oracle
oracle.spring.datasource.jdbcUrl=jdbc:oracle:thin:@//172.18.1.210:1523/cdsdh
oracle.spring.datasource.username=admin
oracle.spring.datasource.password=123
oracle.spring.datasource.driverClassName=oracle.jdbc.driver.OracleDriver
#multiple Setting none
spring.jpa.hibernate.ddl-auto=none
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
spring.jpa.show-sql=true
spring.main.allow-bean-definition-overriding=true
pojo类
package com.example.entity.oracle;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="SPRING_JOB")
public class JobEntity {
@Id
@Column(name="ID")
private long id;
@Column(name="NAME")
private String name;//任务名
@Column(name="CLASSNAME")
private String className;//任务类
@Column(name="CRON")
private String cron;//cron时间
@Column(name="STATUS")
private String status;//状态
@Column(name="GROUPNAME")
private String groupName;//任务组
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public String getCron() {
return cron;
}
public void setCron(String cron) {
this.cron = cron;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getGroupName() {
return groupName;
}
public void setGroupName(String groupName) {
this.groupName = groupName;
}
}
dao类
package com.example.dao.oracle;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import com.example.entity.oracle.JobEntity;
@Repository
public interface JobDao extends JpaRepository<JobEntity,Integer>{
@Query(name = "findAllActivity", value = "SELECT A FROM JobEntity A WHERE A.status=1")
List<JobEntity> findAllActivity();//查询所有需要启动的任务
@Query(name = "findById", value = "SELECT A FROM JobEntity A WHERE A.id=:ID")
JobEntity findById(@Param("ID") long id);
}
Configuration类
package com.example.config;
import java.util.Date;
import java.util.List;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
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.context.annotation.Configuration;
import com.example.entity.oracle.JobEntity;
import com.example.service.JobService;
@Configuration
public class QuartzSchedulerUtil {
@Autowired
private Scheduler scheduler;
@Autowired
private JobService service;
/**
* 开始执行所有任务
* @throws ClassNotFoundException
*/
public void startJob() throws SchedulerException, ClassNotFoundException {
//启动时进行查库将任务添加至job
List<JobEntity> netaskList = service.findAllActivity();
//添加任务至调度器scheduler
startJobList(scheduler,netaskList);
scheduler.start();
}
private void startJobList(Scheduler scheduler2, List<JobEntity> List) throws SchedulerException, ClassNotFoundException{
for(JobEntity task : List){
//不同的业务,增加不同的.class
@SuppressWarnings("unchecked")
JobDetail jobDetail = JobBuilder.newJob((Class<? extends Job>) Class.forName(task.getClassName()))
.withIdentity(Long.toString(task.getId()), task.getGroupName())
.build();
jobDetail.getJobDataMap().put(Long.toString(task.getId()),task);
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(task.getCron());
// CronTrigger表达式触发器 继承于Trigger
// TriggerBuilder 用于构建触发器实例
CronTrigger cronTrigger = TriggerBuilder.newTrigger()
//若一个jobdetail有多个trigger,则需要注意命名规则,便于后面修改任务
.forJob(jobDetail)
.withIdentity(Long.toString(task.getId()), task.getGroupName())
.withSchedule(cronScheduleBuilder).build();
// scheduleJob该接口的作用是在将任务加入Quartz的同时绑定一个Trigger,Quartz会在加入该任务后自动设置Trigger的JobName与JobGroup为该JobDetail的name与group
scheduler2.scheduleJob(jobDetail, cronTrigger);//必须有jobdetail
}
}
/**
* 恢复某个任务
*
* @param name
* @param group
* @throws SchedulerException
*/
public void resumeJob(String name, String group) throws SchedulerException {
JobKey jobKey = new JobKey(name, group);
JobDetail jobDetail = scheduler.getJobDetail(jobKey);
if (jobDetail == null){
return;
}
scheduler.resumeJob(jobKey);
}
/**
* 暂停某个任务
*
* @param name
* @param group
* @throws SchedulerException
*/
public void pauseJob(String name, String group) throws SchedulerException {
JobKey jobKey = new JobKey(name, group);
JobDetail jobDetail = scheduler.getJobDetail(jobKey);
if (jobDetail == null){
return;
}
scheduler.pauseJob(jobKey);
}
/**
* 修改某个任务的执行时间
* (修改的是具体的trigger,不是jobdetail)
* @param name
* @param group
* @param time
* @return
* @throws SchedulerException
*/
public boolean modifyJob(String name, String group, String time) throws SchedulerException {
Date date = null;
TriggerKey triggerKey = new TriggerKey(name, group);
CronTrigger cronTrigger = (CronTrigger) scheduler.getTrigger(triggerKey);
String oldTime = cronTrigger.getCronExpression();
if (!oldTime.equalsIgnoreCase(time)) {
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(time);
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(name, group)
.withSchedule(cronScheduleBuilder).build();
date = scheduler.rescheduleJob(triggerKey, trigger);
}
return date != null;
}
/**
* 获取JobCron信息
*
* @param name
* @param group
* @return
* @throws SchedulerException
*/
public String getJobCron(String name, String group) throws SchedulerException {
TriggerKey triggerKey = new TriggerKey(name, group);
CronTrigger cronTrigger = (CronTrigger) scheduler.getTrigger(triggerKey);
if(cronTrigger==null)
return null;
return cronTrigger.getCronExpression();
}
//获取任务状态
public String getJobStatus(String name, String group) throws SchedulerException {
TriggerKey triggerKey = new TriggerKey(name, group);
CronTrigger cronTrigger = (CronTrigger) scheduler.getTrigger(triggerKey);
if(cronTrigger==null)
return null;
return scheduler.getTriggerState(triggerKey).name();
}
}
上面的基本的配置是参考的https://blog.csdn.net/a510750/article/details/90241004
这片博客,具体的还有删除任务之类的可自行查看。
MyJobFactory
这个类是为了解决无法自动注入Bean
package com.example.config;
import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.scheduling.quartz.SpringBeanJobFactory;
public class MyJobFactory extends SpringBeanJobFactory {
@Autowired
private AutowireCapableBeanFactory capableBeanFactory;
@Override
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
//调用父类的方法
Object jobInstance = super.createJobInstance(bundle);
//进行注入
capableBeanFactory.autowireBean(jobInstance);
return jobInstance;
}
}
ScheduleRefreshDatabase
实现根据数据库中的记录修改任务属性,减少项目的重启次数
package com.example.config;
import java.util.List;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import com.example.entity.oracle.JobEntity;
import com.example.service.JobService;
@Configuration
@EnableScheduling
@Component
public class ScheduleRefreshDatabase {
@Autowired
private JobService service;
@Autowired
private QuartzSchedulerUtil schedulerTest;
@Scheduled(fixedRate = 60*1000) // 每隔一分钟查库,并根据查询结果决定是否重新设置定时任务
public void scheduleUpdateCronTrigger() throws SchedulerException {
System.out.println("开始检查时间");
List<JobEntity> list = service.findAllJob();
for (JobEntity jobEntity : list) {
String cruCron = schedulerTest.getJobCron(Long.toString(jobEntity.getId()), jobEntity.getGroupName());
String cruStatus = schedulerTest.getJobStatus(Long.toString(jobEntity.getId()), jobEntity.getGroupName());
//如果获取到当前任务的执行时间与数据库不相等,修改任务时间
if(cruCron!=null&&!cruCron.equals(jobEntity.getCron())) {
schedulerTest.modifyJob(Long.toString(jobEntity.getId()), jobEntity.getGroupName(), jobEntity.getCron());
}
//暂停任务
if(cruStatus!=null&&"NORMAL".equals(cruStatus)&&!jobEntity.getStatus().equals("1")) {
System.out.println("暂停任务"+jobEntity.getName());
schedulerTest.pauseJob(Long.toString(jobEntity.getId()), jobEntity.getGroupName());
}else if(cruStatus!=null&&!"NORMAL".equals(cruStatus)&&jobEntity.getStatus().equals("1")){//恢复任务
System.out.println("重启任务"+jobEntity.getName());
schedulerTest.resumeJob(Long.toString(jobEntity.getId()), jobEntity.getGroupName());
}
}
}
}
MyQuartzListener
启动任务
package com.example.listener;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Component;
import com.example.config.MyJobFactory;
import com.example.config.QuartzSchedulerUtil;
@Component
public class MyQuartzListener implements ApplicationListener<ApplicationEvent> {
private static boolean loaded = false;
@Autowired
private QuartzSchedulerUtil quartzScheduler;
@Override
public void onApplicationEvent(ApplicationEvent e) {
if (e instanceof ContextRefreshedEvent) {
if (!loaded) {// 避免多次执行
loaded = true;
// 定时任务启动
try {
quartzScheduler.startJob();
//System.out.println("任务已经启动...");
} catch (Exception se) {
se.printStackTrace();
}
}
}
}
@Bean
public MyJobFactory jobFactory() {
return new MyJobFactory();
}
@Bean
public SchedulerFactoryBean schedulerFactoryBean(MyJobFactory jobFactory) {
SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
schedulerFactoryBean.setJobFactory(jobFactory);
return schedulerFactoryBean;
}
/**
* 初始注入scheduler
*
* @return
* @throws SchedulerException
*/
@Bean
public Scheduler scheduler(SchedulerFactoryBean schedulerFactoryBean) throws SchedulerException {
return schedulerFactoryBean.getScheduler();
}
}
两个简单任务
写两个简单的任务类
package com.example.task;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;
import com.example.service.MySqlAffairService;
public class SimpleQuartzTask1 extends QuartzJobBean {
/**
* 实现QuartzJobBean的executeInternal()方法,即可定义工作内容
*/
private static final Logger log = LoggerFactory.getLogger(SimpleQuartzTask1.class);
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
@Autowired
private MySqlAffairService service;
private boolean isSuccess = true;
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
if(isSuccess==false) {
log.info("上次未执行完毕");
}
System.out.println("-同步ORCLE数据库任务1开始---" + dateFormat.format(new Date()));
try {
isSuccess = false;
service.dealInfo();
} catch (Exception e) {
log.info("1-线程1失败。" + e);
e.printStackTrace();
}finally {
isSuccess = true;
}
log.info("1-同步ORCLE数据库任务结束---" + dateFormat.format(new Date()));
}
}
package com.example.task;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;
import com.example.service.OracleAffairService;
public class SimpleQuartzTask2 extends QuartzJobBean {
/**
* 实现QuartzJobBean的executeInternal()方法,即可定义工作内容
*/
private static final Logger log = LoggerFactory.getLogger(SimpleQuartzTask2.class);
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
@Autowired
private OracleAffairService service;
private boolean isSuccess = true;
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
if(isSuccess==false) {
log.info("上次未执行完毕");
}
System.out.println("2-同步MYSQL任务开始---" + dateFormat.format(new Date()));
try {
isSuccess = false;
service.dealInfo();
} catch (Exception e) {
e.printStackTrace();
log.info("1-线程1阻塞失败。" + e);
}finally {
isSuccess = true;
}
log.info("2-同步MYSQL任务2结束---" + dateFormat.format(new Date()));
}
}
sql文件
CREATE TABLE SPRING_JOB
(
ID NUMBER(19, 0) NOT NULL
, CLASSNAME VARCHAR2(255 CHAR)
, CRON VARCHAR2(255 CHAR)
, GROUPNAME VARCHAR2(255 CHAR)
, NAME VARCHAR2(255 CHAR)
, STATUS VARCHAR2(255 CHAR)
);
Insert into SPRING_JOB (ID,CLASSNAME,CRON,GROUPNAME,NAME,STATUS) values (1,'com.example.task.SimpleQuartzTask1','*/30 * * * * ?','Test','mysql-oracle','1');
Insert into SPRING_JOB (ID,CLASSNAME,CRON,GROUPNAME,NAME,STATUS) values (2,'com.example.task.SimpleQuartzTask2','*/30 * * * * ?','Test','oarlce-mysql','1');
commit;