SpringBoot整合quartz(自启动 job -- 数据库可配置版本)

首先导入配置类(项目启动预加载)

  • 背景:项目启动后,SpringBoot 通过数据库配置实现可配置job任务工作,目前的功能算个半自动,更改数据库配置信息的话 就需要重新重启服务了。

      SpringBoot整合quartz(支持多任务和job,支持spring管理)
      框架:SpringBoot + quartz
      
      所需要的依赖:
         <!--quartz-->
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-quartz</artifactId>
          </dependency>
    
  • 1.导入配置类
package xxx;

import xxx.entity.ScheduleJob;
import xxx.repository.ScheduleJobRepository;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;

import java.util.List;

@Configuration
public class SchedulerListener implements ApplicationListener<ContextRefreshedEvent> {

    @Autowired
    Scheduler Scheduler;

    @Autowired
    JobFactory JobFactory;

    @Autowired
    ScheduleJobRepository ScheduleJobRepository;

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
    	//数据库查询配置信息  换你自己的逻辑
        List<ScheduleJob> ScheduleJobAll = ScheduleJobRepository.findAll(); 
        try {
            Scheduler.schedulerJob(ScheduleJobAll);
            System.out.println("SynchronizedData job  start...");
        } catch (SchedulerException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    @Bean(name ="mySchedulerFactoryBean")
    public SchedulerFactoryBean mySchedulerFactory() {
        SchedulerFactoryBean bean = new SchedulerFactoryBean();
        bean.setOverwriteExistingJobs(true);
        bean.setStartupDelay(1);
        bean.setJobFactory(JobFactory);
        return bean;
    }
}

  • 2.导入应用程序启动时自动扫描并加载的组件1
package xxx.conf.quartz;

import xxx.entity.ScheduleJob;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.quartz.impl.StdScheduler;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import java.util.List;

@Slf4j
@Component
public class Scheduler {

    public static JobKey getJobKey(String jobId, String jobGroup) {
        return JobKey.jobKey(jobId, jobGroup);
    }

    public void schedulerJob(List<ScheduleJob> scheduleJobList) throws SchedulerException, ClassNotFoundException {
        ApplicationContext annotationContext = SpringUtil.getApplicationContext();
        StdScheduler stdScheduler = (StdScheduler) annotationContext.getBean("mySchedulerFactoryBean");//获得上面创建的bean
        org.quartz.Scheduler myScheduler =stdScheduler;
        dataCheck(myScheduler,scheduleJobList);
        myScheduler.start();
    }

    public void dataCheck(org.quartz.Scheduler scheduler, List<ScheduleJob> scheduleJobList) throws SchedulerException, ClassNotFoundException {
        //只有首次启动才会进入此函数
        //scheduleJobList这个东西是我在数据库添加的配置类,我会在结尾添加具体数据库配置截图
        a:for (ScheduleJob info :scheduleJobList) {
        	//添加了一个状态,如果是已关闭的状态,先杀掉已运行的任务
            if(info.getStartOrNot().equals("N")){
                checkExistsDelete(scheduler, info);
                continue a;
            }
            //检查你的程序是否正在运行,如果正在运行,那么先杀掉,避免重复调用
            checkExistsDelete(scheduler, info);
            //即将开始你的自动化JOB逻辑
            startScheduler(scheduler, info);
          /*  if(info.getCurrentState().equals(JobType.STARTUP.jobType)){
                //开启状态 -- 先检查是否存在,存在关闭再开
                checkExistsDelete(scheduler, info);
                startScheduler(scheduler, info);
            }else if(info.getCurrentState().equals(JobType.SUSPEND.jobType)){
                //暂停状态,
                if (scheduler.checkExists(getJobKey(info.getId(), info.getTaskName()))) {
                    pauseJobScheduler(scheduler, info);
                }
            }else if(info.getCurrentState().equals(JobType.RESTORE.jobType)){
                if (scheduler.checkExists(getJobKey(info.getId(), info.getTaskName()))) {
                    resumeJobScheduler(scheduler,info);
                }else{
                    startScheduler(scheduler, info);
                }
            }else if(info.getCurrentState().equals(JobType.CLOSE.jobType)){
                if (scheduler.checkExists(getJobKey(info.getId(), info.getTaskName()))) {
                    deleteJobScheduler(scheduler, info);
                }
            }*/
        }
    }

    public void startScheduler(org.quartz.Scheduler scheduler, ScheduleJob jobInfo) throws SchedulerException, ClassNotFoundException {
        log.info(jobInfo.toString());
        /**
        	这些参数都配置在数据库里(后面我会贴图)
        	jobInfo.getInvokeTarget()  //你要运行的Class 位置
        	jobInfo.getTaskName()	   //任务名称
        	jobInfo.getCronExpression()//你的运行时间 例如:0 0 19-23 * * ?
        	jobInfo.getId()			   //任务的id
        **/
        JobDetail jobDetail = JobBuilder.newJob((Class<? extends Job>) Class.forName(jobInfo.getInvokeTarget())).withIdentity("job_"+jobInfo.getTaskName(), "jobGroup_"+jobInfo.getTaskName()).build();
        CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(jobInfo.getCronExpression());
        CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger_"+jobInfo.getId(), "triggerGroup_"+jobInfo.getTaskName())
                .withSchedule(cronScheduleBuilder).build();
        scheduler.scheduleJob(jobDetail, trigger);
        scheduler.start();
    }

    public void checkExistsDelete(org.quartz.Scheduler scheduler, ScheduleJob info) throws  SchedulerException{
        if (scheduler.checkExists(getJobKey(info.getId(), info.getTaskName()))) {
            scheduler.deleteJob(getJobKey(info.getId(), info.getTaskName()));
        }
    }

    public void deleteJobScheduler(org.quartz.Scheduler scheduler, ScheduleJob jobInfo) throws  SchedulerException{
        scheduler.deleteJob(getJobKey(jobInfo.getId(), jobInfo.getTaskName()));
    }

    public void pauseJobScheduler(org.quartz.Scheduler scheduler, ScheduleJob jobInfo) throws  SchedulerException{
        scheduler.pauseJob(getJobKey(jobInfo.getId(), jobInfo.getTaskName()));
    }

    public void resumeJobScheduler(org.quartz.Scheduler scheduler, ScheduleJob jobInfo) throws  SchedulerException{
        scheduler.resumeJob(getJobKey(jobInfo.getId(), jobInfo.getTaskName()));
    }

}

  • 3.导入应用程序启动时自动扫描并加载的组件2
package xxx.conf.quartz;

import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.scheduling.quartz.AdaptableJobFactory;
import org.springframework.stereotype.Component;

@Component
public class JobFactory extends AdaptableJobFactory {

    @Autowired
    private AutowireCapableBeanFactory capableBeanFactory;

    @Override
    protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
        // 调用父类的方法
        Object jobInstance = super.createJobInstance(bundle);
        // 进行注入
        capableBeanFactory.autowireBean(jobInstance);
        return jobInstance;
    }
}

  • 4.导入util 初始化类
package xxx.conf.quartz;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component
public class SpringUtil implements ApplicationContextAware {

    private static final Logger logger = LoggerFactory.getLogger(SpringUtil.class);

    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if (SpringUtil.applicationContext == null) {
            SpringUtil.applicationContext = applicationContext;
        }
    }

    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    // 通过name获取 Bean.
    @SuppressWarnings("unchecked")
    public static <T> T getBean(String name) {
        return (T) getApplicationContext().getBean(name);
    }

    // 通过class获取Bean.
    public static <T> T getBean(Class<T> clazz) {
        return getApplicationContext().getBean(clazz);
    }

    // 通过name,以及Clazz返回指定的Bean
    public static <T> T getBean(String name, Class<T> clazz) {
        return getApplicationContext().getBean(name, clazz);
    }
}

  • 5.你要运行的 Class 任务1
package com.xxx.job;

import com.xxx.service.NationalFaceToFaceService;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;

public class MySchedulerJob implements Job {

	//这里就可以成功注入Server了
    @Autowired
    private xxxService xxxService;

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        System.out.println("SchedulerJob 111111 event number: ********************************************************" );
    }
}

  • 6.你要运行的 Class 任务2
package com.xxx.job;

import com.xxx.entity.ScheduleJob;
import com.alibaba.fastjson.JSONObject;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Date;

@Component
@Slf4j
@DisallowConcurrentExecution
public class xxx  implements Job {

    @Autowired
    private OtherService otherService;

    @SneakyThrows
    @Override
    public void execute(JobExecutionContext jobExecutionContext){
        log.info("SchedulerJob 222222 event number: ************************* SubmitDataCleansing *******************************");
        //打印开始时间 
        String invokeTarget = SubmitDataCleansing.class.getName();
        //获取数据库资源配置
        ScheduleJob scheduleJob = otherService.findByInvokeTarget(invokeTarget);
        if(scheduleJob != null){
            //获取数据库配置信息(固定)
            JSONObject parameter = JSONObject.parseObject(scheduleJob.getParameter());
     		//业务逻辑开始


        }else{
            //状态回库 这个可以不需要
            otherService.updateCurrentState(JobType.FAIL.jobType,"Error -- Class configuration not found",scheduleJob.getId());
            log.error("xxx : Error -- Class configuration not found");
        }
    }

}
  • 7.实体类 (获取数据库配置信息的) 你可以用你自己的也可以
package com.xxx.data.entity;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "ScheduleJob")
public class ScheduleJob{

	@Id
	private String Id;
	private String TaskName;
	private String InvokeTarget;
	private String StartOrNot;
	private String CronExpression;
	private String CurrentState;
	private String Parameter;
	private String CreateBy;
	private String CreateTime;
	private String UpdateBy;
	private String UpdateTime;
	private String Remarks;


	public String getId() {
		return Id;
	}

	public void setId(String id) {
		Id = id;
	}

	public String getTaskName() {
		return TaskName;
	}

	public void setTaskName(String taskName) {
		TaskName = taskName;
	}

	public String getInvokeTarget() {
		return InvokeTarget;
	}

	public void setInvokeTarget(String invokeTarget) {
		InvokeTarget = invokeTarget;
	}

	public String getStartOrNot() {
		return StartOrNot;
	}

	public void setStartOrNot(String startOrNot) {
		StartOrNot = startOrNot;
	}

	public String getCronExpression() {
		return CronExpression;
	}

	public void setCronExpression(String cronExpression) {
		CronExpression = cronExpression;
	}

	public String getCurrentState() {
		return CurrentState;
	}

	public void setCurrentState(String currentState) {
		CurrentState = currentState;
	}

	public String getParameter() {
		return Parameter;
	}

	public void setParameter(String parameter) {
		Parameter = parameter;
	}

	public String getCreateBy() {
		return CreateBy;
	}

	public void setCreateBy(String createBy) {
		CreateBy = createBy;
	}

	public String getCreateTime() {
		return CreateTime;
	}

	public void setCreateTime(String createTime) {
		CreateTime = createTime;
	}

	public String getUpdateBy() {
		return UpdateBy;
	}

	public void setUpdateBy(String updateBy) {
		UpdateBy = updateBy;
	}

	public String getUpdateTime() {
		return UpdateTime;
	}

	public void setUpdateTime(String updateTime) {
		UpdateTime = updateTime;
	}

	public String getRemarks() {
		return Remarks;
	}

	public void setRemarks(String remarks) {
		Remarks = remarks;
	}

	public String toString() {
		return "ScheduleJob [CreateBy=" + CreateBy + ", CreateTime="
				+ CreateTime + ", CronExpression=" + CronExpression
				+ ", CurrentState=" + CurrentState + ", Id=" + Id
				+ ", InvokeTarget=" + InvokeTarget + ", Parameter=" + Parameter
				+ ", Remarks=" + Remarks + ", StartOrNot=" + StartOrNot + ", TaskName=" + TaskName
				+ ", UpdateBy=" + UpdateBy + ", UpdateTime=" + UpdateTime + "]";
	}

}

  • 8.数据库字段配置信息
图解1:

第三列是 你要运行class的位置(第5步和第6步)
第四列是 是否开启的一个开关选项,可以没有这个字段
第五列是 你要运行的具体时间 (Cron表达式)

在这里插入图片描述

图解2:

第二列是 程序正在运行状态,记录一下类似日志(也可以不要)
第三列是 配置的请求参数,我写的是JSON, 你也可以写List,set.... 后期在代码里连接数库取值 能解析出来就行
最后几列我也是为了记录,也可以没有 

在这里插入图片描述

  • 9.到这里你的配置都完成了,直接启动项目就行了,然后等待自动化程序运行,就可以了
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值