SpringBoot+Quartz实现定时任务(可自动修改任务属性)

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;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值