SpringBoot集成Quartz(解决@Autowired空指针Null问题即依赖注入的属性为null)

使用spring-boot作为基础框架,其理念为零配置文件,所有的配置都是基于注解和暴露bean的方式。

Quartz的4个核心概念:

 

1、Job
表示一个工作,要执行的具体内容。此接口中只有一个方法
void execute(JobExecutionContext context)

2、JobDetail
JobDetail表示一个具体的可执行的调度程序,Job是这个可执行程调度程序所要执行的内容,另外JobDetail还包含了这个任务调度的方案和策略。

3、Trigger代表一个调度参数的配置,什么时候去调。

4、Scheduler代表一个调度容器,一个调度容器中可以注册多个JobDetail和Trigger。当Trigger与JobDetail组合,就可以被Scheduler容器调度了。

 

 

集成Quartz的步骤如下:

1、POM中引入依赖

            <!-- quartz -->
            <dependency>
                <groupId>org.quartz-scheduler</groupId>
                <artifactId>quartz</artifactId>
                <version>${quartz.version}</version>
            </dependency>
            <dependency>
                <groupId>org.quartz-scheduler</groupId>
                <artifactId>quartz-jobs</artifactId>
                <version>${quartz.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context-support</artifactId>
                <version>${spring-context-support.version}</version>
            </dependency>

注意版本号

<spring-context-support.version>4.1.6.RELEASE</spring-context-support.version>
<quartz.version>2.2.3</quartz.version>

 

2、修改quartz.properties文件(可以存放在resources下,也可以存放未固定路径)

我们这里将使用基于DB的作业存储

# Default Properties file for use by StdSchedulerFactory
# to create a Quartz Scheduler Instance, if a different
# properties file is not explicitly specified.
#
# StdSchedulerFactory使用quartz.properties 创建一个Quartz Scheduler实例
# 参数请参考:http://www.quartz-scheduler.org/documentation/quartz-2.x/configuration/
#
# Quartz提供两种基本作业存储类型
# --->第一种类型叫做RAMJobStore:
#     最佳的性能,因为内存中数据访问最快
#     不足之处是缺乏数据的持久性,当程序路途停止或系统崩溃时,所有运行的信息都会丢失
# --->第二种类型叫做JDBC作业存储:
#     通过调整其quartz.properties属性文件,持久化任务调度信息
#     使用数据库保存任务调度信息后,即使系统崩溃后重新启动,任务的调度信息将得到恢复
#


#============================================================================
# 基础配置
#============================================================================

# 设置调度器的实例名(instanceName) 和实例ID (instanceId)
org.quartz.scheduler.instanceName: DefaultQuartzScheduler
#如果使用集群,instanceId必须唯一,设置成AUTO
org.quartz.scheduler.instanceId = AUTO

org.quartz.scheduler.rmi.export: false
org.quartz.scheduler.rmi.proxy: false
org.quartz.scheduler.wrapJobExecutionInUserTransaction: false

#============================================================================
# 调度器线程池配置
#============================================================================

org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
# 指定多少个工作者线程被创建用来处理 Job
org.quartz.threadPool.threadCount: 10
# 设置工作者线程的优先级(最大值10,最小值1,常用值5)
org.quartz.threadPool.threadPriority: 5
# 加载任务代码的ClassLoader是否从外部继承
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true

org.quartz.jobStore.misfireThreshold: 60000

#============================================================================
# Configure JobStore 作业存储配置
#============================================================================

# 默认配置,数据保存到内存(调度程序信息是存储在被分配给JVM的内存里面,运行速度快)
#org.quartz.jobStore.class: org.quartz.simpl.RAMJobStore

# 持久化配置(存储方式使用JobStoreTX,也就是数据库)
org.quartz.jobStore.class:org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass:org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#使用自己的配置文件
org.quartz.jobStore.useProperties:true

#数据库中quartz表的表名前缀
org.quartz.jobStore.tablePrefix:qrtz_
org.quartz.jobStore.dataSource:qzDS

#是否使用集群(如果项目只部署到 一台服务器,就不用了)
org.quartz.jobStore.isClustered = true

#============================================================================
# Configure Datasources 配置数据源
#============================================================================

org.quartz.dataSource.qzDS.driver:oracle.jdbc.OracleDriver
org.quartz.dataSource.qzDS.URL:jdbc:oracle:thin:@10.132.81.134:1521:dsdb1
org.quartz.dataSource.qzDS.user:masmf
org.quartz.dataSource.qzDS.password:masmf
org.quartz.dataSource.qzDS.maxConnections:10

 注意:如果项目中同时运行了基于内存的任务调度(RAMJobStore)和基于数据库的任务调度(JobStoreTX)且属性文件中配置org.quartz.scheduler.instanceName=DefaultQuartzScheduler时,任务永远不会被写入到数据库,因为数据库的schedualer已被内存的schedualer覆盖

原因参考:

 

QUARTZ任务不写入数据库分析

3、自定义JobFactory

首先解释一个常见的困境:Spring容器可以管理Bean,但是Quartz的job是自己管理的,如果在Job中注入Spring管理的Bean,需要先把Quartz的Job也让Spring管理起来,因此,我们需要重写JobFactory,详细的源码分析,请参考:

 

Quartz与Spring集成 Job如何自动注入Spring容器托管的对象

Quartz入门实例14-让Quartz的Job使用Spring注入的Bean

 

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;

/**
 * Description: 自定义JobFactory,使用Spring容器管理的Quartz的Bean(Job)
 * <p/>
 * AdaptableJobFactory是Spring提供的SchedulerFactoryBean的默认实例化工厂,将由直接实例化Job,没有被Spring管理
 * User: lishaohua
 * Date: 2017/11/15  13:54
 */
@Component
public class MyJobFactory extends AdaptableJobFactory {

    /**
     * AutowireCapableBeanFactory接口是BeanFactory的子类
     * 可以连接和填充那些生命周期不被Spring管理的已存在的bean实例
     * 具体请参考:http://blog.csdn.net/iycynna_123/article/details/52993542
     */
    @Autowired
    private AutowireCapableBeanFactory capableBeanFactory;

    /**
     * 创建Job实例
     *
     * @param bundle
     * @return
     * @throws Exception
     */
    @Override
    protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
        // 实例化对象
        Object jobInstance = super.createJobInstance(bundle);
        // 进行注入(Spring管理该Bean)
        capableBeanFactory.autowireBean(jobInstance);
        //返回对象
        return jobInstance;
    }
}

 

4、配置schedulerFactoryBean

Spring为了能集成Quartz,特意提供了管理Quartz的schedulerFactoryBean,必须配置,具体代码如下:

 

import org.quartz.ee.servlet.QuartzInitializerListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.FileSystemResource;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;

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

/**
 * Description: Quartz调度配置
 * <p/>
 * User: lishaohua
 * Date: 2017/11/14  10:27
 */
@Configuration //类似xml中的<beans>标签,一般和@bean注解一起使用来配置一个Bean,让Spring来管理它的生命周期
@ConfigurationProperties(prefix = "quartz.config")//把配置文件的信息自动装配到Bean上(以quartz.config前缀的)
public class SchedulerConfig {
    /**
     * 配置文件路径
     */
    private String propertiesPath;//quartz.config.propertiesPath

    @Autowired
    private MyJobFactory myJobFactory;

    /**
     * 配置SchedulerFactoryBean
     *
     * @param dataSource 数据源
     * @return
     * @throws IOException
     */
    @Bean //将一个方法产生为Bean并交给Spring容器管理(@Bean只能用在方法上)
    public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource) throws IOException {
        //Spring提供SchedulerFactoryBean为Scheduler提供配置信息,并被Spring容器管理其生命周期
        SchedulerFactoryBean factory = new SchedulerFactoryBean();
        //启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了
        factory.setOverwriteExistingJobs(true);
        // 延时启动(秒)
        factory.setStartupDelay(20);
        //设置quartz的配置文件
        factory.setQuartzProperties(quartzProperties());
        //设置自定义Job Factory,用于Spring管理Job bean
        factory.setJobFactory(myJobFactory);
        return factory;
    }

    /**
     * 加载Quartz配置
     *
     * @return
     * @throws IOException
     */
    @Bean
    public Properties quartzProperties() throws IOException {
        //使用Spring的PropertiesFactoryBean对属性配置文件进行管理
        PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
        //注意:quartz的配置文件从指定系统目录中获取,而不是从classpath中获取
        //propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties"));
        propertiesFactoryBean.setLocation(new FileSystemResource(propertiesPath));
        //重要:保证其初始化
        propertiesFactoryBean.afterPropertiesSet();
return propertiesFactoryBean.getObject();
    }

    /**
     * 初始化Quartz监听器,让Spring boot启动时初始化Quartz
     * --web工程中,一般在web.xml中设置如下:
     * <listener>
     * <listener-class>org.quartz.ee.servlet.QuartzInitializerListener</listener-class>
     * </listener>
     * Quartz就会随着web容器启动,加载调度任务
     *
     * @return
     */
    @Bean
    public QuartzInitializerListener executorListener() {
        return new QuartzInitializerListener();
    }

    //========get/set method============================
    public String getPropertiesPath() {
        return propertiesPath;
    }

    public void setPropertiesPath(String propertiesPath) {
        this.propertiesPath = propertiesPath;
    }
}

 

 

注意两点:

a、加载quartz.properties使用的是Spring的PropertiesFactoryBean,我将该文件存放在固定磁盘目录,因此使用了

new FileSystemResource(propertiesPath)

如果你的文件存放在resources下,请从classpath下加载:new ClassPathResource("/quartz.properties")

b、我将quartz.properties路径配置在SpringBoot的yml中,因此使用了@ConfigurationProperties,不需要请移除,如果使用请注意get/set方法不能少

c、注意,一定要先执行propertiesFactoryBean.afterPropertiesSet();然后propertiesFactoryBean.getObject();

 

5、初始化DB

不解释,直接从quartz官网下载并初始化到你的DB中

6、编写定时任务

直接上代码:

@Component
public class UpdateCEBKeyJob extends QuartzJobBean {
    //日志记录
    private static Logger logger = LoggerFactory.getLogger(UpdateCEBKeyJob.class);

    //ECB密钥更新
    @Autowired
    private KeyOperationService keyOperationService;


    /**
     * 执行Job
     *
     * @param jobExecutionContext
     * @throws JobExecutionException
     */
    @Override
    protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        boolean updateFlag = false;
        logger.info("-------------------update ECB key job begin:{} ----------------",
                DateTimeUtil.getCurrentDateTime());
        //===============01.正常执行任务======================
        try {
           /* KeyOperationService keyOperationService = ContextWrapper
                    .getBean("keyOperationService", KeyOperationService.class);*/
            updateFlag = keyOperationService.updateCEBKey();
        } catch (Exception e) {
            logger.error("更新光大密钥失败!", e);
        }

        //===============02.执行结果判定======================
        if (!updateFlag) {//如果更新失败,创建一次性任务再次执行(Job仍然是当前class)
            createJob(2);
        }
        logger.info("-------------------update ECB key job end:{} ----------------",
                DateTimeUtil.getCurrentDateTime());
    }

 

7、单元测试 或  手工添加任务的Controller

单元测试不解释,如果使用了界面,编写的Controller如下

 

 

import com.shengpay.mf.constant.ServerErrorEnum;
import com.shengpay.mf.exception.ServerException;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.quartz.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

/**
 * Description: 定时任务 管理
 * <p/>
 * User: lishaohua
 * Date: 2017/11/14  13:22
 */
@Controller
@Api("定时任务管理")//描述类的作用(Swagger注解)
public class JobController {
    private static Logger logger = LoggerFactory.getLogger(JobController.class);

    /*@Autowired
    private SchedulerFactoryBean schedulerFactoryBean;*/

    @Autowired
    private Scheduler scheduler;


    /**
     * 添加定时任务
     *
     * @param request
     * @param jobClassName
     * @param jobGroupName
     * @param cronExpression
     * @return
     */
    @ApiOperation("添加定时任务")//描述方法的作用(Swagger注解)
    @RequestMapping(value = "/addJob", method = {RequestMethod.POST})
    @ResponseBody
    public Map<String, String> addJob(HttpServletRequest request,
                                      @RequestParam(value = "jobClassName") String jobClassName,
                                      @RequestParam(value = "jobGroupName") String jobGroupName,
                                      @RequestParam(value = "cronExpression") String cronExpression) {
        Map<String, String> returnData = new HashMap<String, String>();
        try {
            /**
             * 构建JobDetail(表示一个具体的可执行的调度程序,Job是这个可执行程调度程序所要执行的内容)
             */
            JobDetail jobDetail = JobBuilder.newJob(getClass(jobClassName).getClass())//工作项1:Job类
                    .withIdentity(jobClassName, jobGroupName)//工作项2:job名以及所属组
                    .build();//构建

            /**
             * 构建触发器Trigger(调度参数的配置,代表何时触发该任务)
             */
            //通过cron表达式构建CronScheduleBuilder
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);
            //构建CronTrigger触发器
            CronTrigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity(jobClassName, jobGroupName) //工作项1:job名以及所属组
                    .withSchedule(scheduleBuilder) //工作项2:指定调度参数
                    .build();//构建

            /**
             *构建调度容器(当Trigger与JobDetail组合,就可以被Scheduler容器调度了)
             * 一个调度容器中可以注册多个JobDetail和Trigger。
             */
            //获得调度容器
            //Scheduler scheduler = getCurrentScheduler();
            //注册调度任务
            scheduler.scheduleJob(jobDetail, trigger);
            //启动任务
            scheduler.start();

            returnData.put("msg", "添加调度任务成功");
        } catch (SchedulerException e) {
            logger.error("构建调度任务异常", e);
            returnData.put("msg", "添加调度任务异常:" + e.getMessage());
        } catch (ServerException e) {
            logger.error("内部异常", e);
            returnData.put("msg", "添加调度任务异常:" + e.getMessage());
        } catch (Exception e) {
            logger.error("添加调度任务异常", e);
            returnData.put("msg", "添加调度任务异常:" + e.getMessage());
        }

        return returnData;
    }

    @ApiOperation("暂停定时任务")//描述方法的作用(Swagger注解)
    @RequestMapping(value = "/pauseJob", method = {RequestMethod.POST})
    @ResponseBody
    public Map<String, String> pauseJob(HttpServletRequest request,
                                        @RequestParam(value = "jobClassName") String jobClassName,
                                        @RequestParam(value = "jobGroupName") String jobGroupName) {
        Map<String, String> returnData = new HashMap<String, String>();
        try {
            //获得调度容器
            //Scheduler scheduler = getCurrentScheduler();
            //JobKey定义了job的名称和组别
            JobKey jobKey = JobKey.jobKey(jobClassName, jobGroupName);
            //暂停任务
            scheduler.pauseJob(jobKey);

            returnData.put("msg", "暂停调度任务成功");
        } catch (SchedulerException e) {
            logger.error("暂停调度任务异常", e);
            returnData.put("msg", "暂停调度任务异常:" + e.getMessage());
        } catch (Exception e) {
            logger.error("暂停调度任务异常", e);
            returnData.put("msg", "暂停调度任务异常:" + e.getMessage());
        }

        return returnData;
    }

    @ApiOperation("继续定时任务")//描述方法的作用(Swagger注解)
    @RequestMapping(value = "/resumeJob", method = {RequestMethod.POST})
    @ResponseBody
    public Map<String, String> resumeJob(HttpServletRequest request,
                                         @RequestParam(value = "jobClassName") String jobClassName,
                                         @RequestParam(value = "jobGroupName") String jobGroupName) {
        Map<String, String> returnData = new HashMap<String, String>();
        try {
            //获得调度容器
            //Scheduler scheduler = getCurrentScheduler();
            //JobKey定义了job的名称和组别
            JobKey jobKey = JobKey.jobKey(jobClassName, jobGroupName);
            //继续任务
            scheduler.resumeJob(jobKey);

            returnData.put("msg", "继续调度任务成功");
        } catch (SchedulerException e) {
            logger.error("继续调度任务异常", e);
            returnData.put("msg", "继续调度任务异常:" + e.getMessage());
        } catch (Exception e) {
            logger.error("继续调度任务异常", e);
            returnData.put("msg", "继续调度任务异常:" + e.getMessage());
        }

        return returnData;
    }

    /**
     * 更新定时任务:
     * --传入的triggerKey有与之匹配的
     * --旧触发器的触发时间没有完成
     *
     * @param request
     * @param jobClassName
     * @param jobGroupName
     * @param cronExpression
     * @return
     */
    @ApiOperation("更新定时任务")//描述方法的作用(Swagger注解)
    @RequestMapping(value = "/rescheduleJob", method = {RequestMethod.POST})
    @ResponseBody
    public Map<String, String> rescheduleJob(HttpServletRequest request,
                                             @RequestParam(value = "jobClassName") String jobClassName,
                                             @RequestParam(value = "jobGroupName") String jobGroupName,
                                             @RequestParam(value = "cronExpression") String cronExpression) {
        Map<String, String> returnData = new HashMap<String, String>();
        try {
            //获得调度容器
            //Scheduler scheduler = getCurrentScheduler();

            //构建旧的TriggerKey
            TriggerKey triggerKey = TriggerKey.triggerKey(jobClassName, jobGroupName);
            //通过cron表达式构建CronScheduleBuilder
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);
            //从调度容器中获取旧的CronTrigger
            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
            //更新CronTrigger
            trigger = trigger.getTriggerBuilder()
                    .withIdentity(triggerKey) //工作项1:job名以及所属组
                    .withSchedule(scheduleBuilder) //工作项2:指定调度参数
                    .build();//构建

            //更新调度任务
            scheduler.rescheduleJob(triggerKey, trigger);

            returnData.put("msg", "更新调度任务成功");
        } catch (SchedulerException e) {
            logger.error("更新调度任务异常", e);
            returnData.put("msg", "更新调度任务异常:" + e.getMessage());
        } catch (ServerException e) {
            logger.error("内部异常", e);
            returnData.put("msg", "更新调度任务异常:" + e.getMessage());
        } catch (Exception e) {
            logger.error("更新调度任务异常", e);
            returnData.put("msg", "更新调度任务异常:" + e.getMessage());
        }

        return returnData;
    }


    @ApiOperation("删除定时任务")//描述方法的作用(Swagger注解)
    @RequestMapping(value = "/removeJob", method = {RequestMethod.POST})
    @ResponseBody
    public Map<String, String> removeJob(HttpServletRequest request,
                                         @RequestParam(value = "jobClassName") String jobClassName,
                                         @RequestParam(value = "jobGroupName") String jobGroupName) {
        Map<String, String> returnData = new HashMap<String, String>();
        try {
            //获得调度容器
            //Scheduler scheduler = getCurrentScheduler();
            //TriggerKey定义了trigger的名称和组别
            TriggerKey triggerKey = TriggerKey.triggerKey(jobClassName, jobGroupName);

            //暂停触发器
            scheduler.resumeTrigger(triggerKey);
            //暂停触发器
            scheduler.unscheduleJob(triggerKey);
            //移除任务
            scheduler.deleteJob(JobKey.jobKey(jobClassName, jobGroupName));

            returnData.put("msg", "删除调度任务成功");
        } catch (SchedulerException e) {
            logger.error("删除调度任务异常", e);
            returnData.put("msg", "删除调度任务异常:" + e.getMessage());
        } catch (Exception e) {
            logger.error("删除调度任务异常", e);
            returnData.put("msg", "删除调度任务异常:" + e.getMessage());
        }

        return returnData;
    }

    /**
     * 获得调度容器Scheduler
     *
     * @return
     * @throws SchedulerException
     */
    /*private Scheduler getCurrentScheduler() throws SchedulerException {
        // 实例化Quartz默认的调度器工厂SchedulerFactory
        //SchedulerFactory sf = new StdSchedulerFactory();
        // 获得调度容器
        //Scheduler sched = sf.getScheduler();
        //return sched;
        //Scheduler sched = schedulerFactoryBean.getScheduler();
        //return sched;
    }*/


    /**
     * 获得指定的类实例
     *
     * @param classname
     * @return
     * @throws ServerException
     */
    private Job getClass(String classname) throws ServerException {
        Job baseJob = null;
        try {
            //加载参数指定的类
            Class<?> classTmp = Class.forName(classname);
            //实例化
            baseJob = (Job) classTmp.newInstance();
        } catch (ClassNotFoundException e) {
            logger.error("找不到指定的类", e);
            throw new ServerException(ServerErrorEnum.INTERNAL_ERROR);
        } catch (InstantiationException e) {
            logger.error("实例化类失败", e);
            throw new ServerException(ServerErrorEnum.INTERNAL_ERROR);
        } catch (IllegalAccessException e) {
            logger.error("实例化类失败", e);
            throw new ServerException(ServerErrorEnum.INTERNAL_ERROR);
        }

        return baseJob;
    }
}

注意:

在controller层直接注入Scheduler即可,如下:

 @Autowired
 private Scheduler scheduler;

然后方法中直接调用

            //注册调度任务
            scheduler.scheduleJob(jobDetail, trigger);
            //启动任务
            scheduler.start();

 

或者注入声明的

@Autowired
private SchedulerFactoryBean schedulerFactoryBean;

然后方法中先执行schedulerFactoryBean.getScheduler()获得scheduler

            //获得调度容器
            Scheduler scheduler = schedulerFactoryBean.getScheduler();
            //注册调度任务
            scheduler.scheduleJob(jobDetail, trigger);
            //启动任务
            scheduler.start();

但是,一定要注意,千万不要自己直接去new StdSchedulerFactory(),默认的schedulerFactoryBean或注入的scheduler都是被StdScheduler,

new StdSchedulerFactory()获得的Scheduler将无法被Spring管理,如下代码:
        // 实例化Quartz默认的调度器工厂SchedulerFactory
        SchedulerFactory sf = new StdSchedulerFactory();
        // 获得调度容器
        Scheduler sched = sf.getScheduler();

 创建的任务区别如下:

===================================华丽的分割线======================================

如果不需要让Spring管理quartz生成的job,则每个job作为普通的Bean对象,可以直接通过applicationContext对象直接getBean

代码如下

 

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

/**
 * Description: applicationContext工具类
 * <p/>
 * User: lishaohua
 * Date: 2017/11/16  13:48
 */
@Component
public class ApplicationContextUtil implements ApplicationContextAware {
    /**
     * 上下文对象实例
     */
    private static ApplicationContext appContext;

    /**
     * Spring自动注入applicationContext对象
     * -- 因此该Bean必须@Component被Spring scan发现
     *
     * @param applicationContext
     * @throws BeansException
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        appContext = applicationContext;
    }

    /**
     * 获得applicationContext
     * @return
     */
    public static ApplicationContext getAppContext() {
        return appContext;
    }

    /**
     * 根据name获取Bean
     *
     * @param name
     * @return
     */
    public static Object getBean(String name) {
        return getAppContext().getBean(name);
    }

    /**
     * 根据class获取Bean
     *
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> T getBean(Class<T> clazz) {
        return getAppContext().getBean(clazz);
    }

    /**
     * 根据name、class获得Bean
     *
     * @param name
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> T getBean(String name, Class<T> clazz) {
        return getAppContext().getBean(name, clazz);
    }
}

 

 通过DB查询已添加的任务,查询SQL如下:

select TO_CHAR(t.next_fire_time / (1000 * 60 * 60 * 24) +  
       TO_DATE('1970-01-01 08:00:00', 'YYYY-MM-DD HH24:MI:SS'), 'YYYY-MM-DD HH24:MI:SS')  next_fire_datetime,
       t.*
from qrtz_triggers t;

查询效果如图

 

参考:

如何获取SpringBoot项目的applicationContext对象

 

参考文章:

https://www.cnblogs.com/javanoob/p/springboot_schedule.html

https://www.cnblogs.com/softidea/p/6073495.html

http://blog.csdn.net/magic_best/article/details/50158125

http://blog.csdn.net/iycynna_123/article/details/52993542

 http://www.jianshu.com/p/b460171c57ea

posted @ 2017-11-15 17:02  花花牛  阅读(15445)  评论(1编辑  收藏  举报