quartz定时任务框架搭建,以及解决service注入为空问题。

干货来咯

引入quartz依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-quartz</artifactId>
        </dependency>

定义QuartzConfig 配置文件

import org.quartz.Scheduler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;

import javax.sql.DataSource;
import java.util.Properties;

/**
 * @Version 1.0
 * @Description TODO
 */
@Configuration
public class QuartzConfig {
    
    

    /**
     * 重写AdaptableJobFactory,解决service注入为null的问题
     */
    @Autowired
    private SpringJobFactory springJobFactory;

    @Bean
    public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource) {
    
    
        SchedulerFactoryBean factory = new SchedulerFactoryBean();
        factory.setDataSource(dataSource);

        //quartz参数
        Properties prop = new Properties();
        prop.put("org.quartz.scheduler.instanceName", "safeScheduler");
        prop.put("org.quartz.scheduler.instanceId", "AUTO");
        //线程池配置
        prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");
        prop.put("org.quartz.threadPool.threadCount", "20");
        prop.put("org.quartz.threadPool.threadPriority", "5");
        //JobStore配置
        prop.put("org.quartz.jobStore.class", "org.springframework.scheduling.quartz.LocalDataSourceJobStore");
        //集群配置
        prop.put("org.quartz.jobStore.isClustered", "true");
        prop.put("org.quartz.jobStore.clusterCheckinInterval", "15000");
        prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "1");

        prop.put("org.quartz.jobStore.misfireThreshold", "12000");
        prop.put("org.quartz.jobStore.tablePrefix", "QRTZ_");
        prop.put("org.quartz.jobStore.selectWithLockSQL", "SELECT * FROM {0}LOCKS UPDLOCK WHERE LOCK_NAME = ?");

        //PostgreSQL数据库,需要打开此注释
        prop.put("org.quartz.jobStore.driverDelegateClass", "org.quartz.impl.jdbcjobstore.PostgreSQLDelegate");

        factory.setQuartzProperties(prop);

        factory.setSchedulerName("safeScheduler");
        //延时启动
        factory.setStartupDelay(30);
        factory.setApplicationContextSchedulerContextKey("applicationContextKey");
        //可选,QuartzScheduler 启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了
        factory.setOverwriteExistingJobs(true);
        //设置自动启动,默认为true
        factory.setAutoStartup(true);


        factory.setJobFactory(springJobFactory);
        return factory;
    }

    @Bean
    public Scheduler scheduler(DataSource dataSource) {
    
    
        return schedulerFactoryBean(dataSource).getScheduler();
    }

}

定义SpringJobFactory 用于解决job中service注入为空的问题。

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;

/**
 * @Version 1.0
 * @Description 解决job中service注入为空的问题。
 */
@Component
public class SpringJobFactory extends AdaptableJobFactory {
    
    

    @Autowired
    private AutowireCapableBeanFactory capableBeanFactory;

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

如果这个失效的话,就是job中注入的service还是为空,可以采用用spring bean的方式让spring容器来寻找service类。
代码如下:


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;

/**
 * @BelongsProject: springboot_mybatis
 * @Author: soncat
 * @Description: SpringUtil类
 * @Version: 1.0
 * @CreateTime: 2022-09-26  11:15:20
 */
@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);
    }

}


定义一个任务实体类

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import org.quartz.JobDataMap;

import java.util.Date;

/**
 * @Version 1.0
 * @Description 任务实体
 */
@TableName("quartz_bean")
@Data
public class QuartzBean {
    
    

    /** 任务id */
    @TableId(value = "jobId" ,type= IdType.AUTO)//很重要没有在实体类的自增主键上加自增主键的注解
    private String  jobId;

    /** 任务名称 */
    private String jobName;

    /** 任务组 */
    private String jobGroup;

    /** 任务执行类 */
    private String jobClass;

    /** 任务状态 启动0还是暂停1*/
    private Integer status;

    /**
     * 任务开始时间
     */
    private Date startTime;

    /**
     * 任务循环间隔-单位:分钟
     */
    private Integer loopInterval;

    /**
     * 任务结束时间
     */
    private Date endTime;

    /** 任务运行时间表达式 */
    private String cronExpression;

    /** 调用目标字符串 */
    private String invokeTarget;

    /** 是否并发执行(0允许 1禁止) */
    private String concurrent;

    private JobDataMap jobDataMap;

}

猜你喜欢

转载自blog.csdn.net/Soncat2000/article/details/127251074