Springboot+Quarz的基本使用(创建,删除,调用)教程(2.3.0)

最近项目中使用到了Quarz框架,本来考虑使用Springboot自带的Timer,但是貌似并不支持动态、灵活的cron表达式,所以三思之后还是使用了Quarz,话不多说,直接上手。

Quartz的maven依赖,这里推荐使用2.3.0的版本。 

<dependency>
   <groupId>org.quartz-scheduler</groupId>
   <artifactId>quartz</artifactId>
   <version>2.3.0</version>
</dependency>

依赖加进之后,这里需要配置一下,创建一个quarz.properties,配置中可以把quarz.properties持久化到数据库中,也可以直接储存在内存中,这里无所谓,我是直接存储在内存中的。如果想开启持久化到数据库中,把注释打开就行。记得配置数据库的连接账号密码。

# 固定前缀org.quartz
# 主要分为scheduler、threadPool、jobStore、plugin等部分

org.quartz.scheduler.instanceName = DefaultQuartzScheduler
org.quartz.scheduler.rmi.export = false
org.quartz.scheduler.rmi.proxy = false
org.quartz.scheduler.wrapJobExecutionInUserTransaction = false

# 实例化ThreadPool时,使用的线程类为SimpleThreadPool
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool

# threadCount和threadPriority将以setter的形式注入ThreadPool实例
# 并发个数
org.quartz.threadPool.threadCount = 2
# 优先级
org.quartz.threadPool.threadPriority = 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true

org.quartz.jobStore.misfireThreshold = 5000

# 默认存储在内存中
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore

#持久化
#org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
#
#org.quartz.jobStore.tablePrefix = QRTZ_
#
#org.quartz.jobStore.dataSource = qzDS
#
#org.quartz.dataSource.qzDS.driver = com.mysql.jdbc.Driver
#
#org.quartz.dataSource.qzDS.URL = jdbc:mysql://192.***.**.**:3306/database?
#useUnicode=true&characterEncoding=UTF-8
#
#org.quartz.dataSource.qzDS.user = root
#
#org.quartz.dataSource.qzDS.password =root
#
#org.quartz.dataSource.qzDS.maxConnections = 10

如果持久化到数据库。这里需要再依赖一个jar包,因为quarz是采用qzDS的方式去连接数据库

<dependency>
   <groupId>c3p0</groupId>
   <artifactId>c3p0</artifactId>
   <version>0.9.0.2</version>
</dependency>

 依赖配置都完成之后,开始写代码,首先创建一个SchedulerConfig的类用来注册bean,将Quarz的配置注册到容器中。

SchedulerConfig.java:

import org.quartz.Scheduler;
import org.quartz.ee.servlet.QuartzInitializerListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;

import java.io.IOException;
import java.util.Properties;

@Configuration
public class SchedulerConfig {
    @Autowired
    private MyJobFactory myJobFactory;

    @Bean(name="SchedulerFactory")
    public SchedulerFactoryBean schedulerFactoryBean() throws IOException {
        SchedulerFactoryBean factory = new SchedulerFactoryBean();
        factory.setJobFactory(myJobFactory);
        factory.setQuartzProperties(quartzProperties());
        return factory;
    }
    @Bean
    public Properties quartzProperties() throws IOException {
        PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
        propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties"));
        //在quartz.properties中的属性被读取并注入后再初始化对象
        propertiesFactoryBean.afterPropertiesSet();
        return propertiesFactoryBean.getObject();
    }
    /*
     * quartz初始化监听器
     */
    @Bean
    public QuartzInitializerListener executorListener() {
        return new QuartzInitializerListener();
    }

    /*
     * 通过SchedulerFactoryBean获取Scheduler的实例
     */
    @Bean(name="Scheduler")
    public Scheduler scheduler() throws IOException {
        return schedulerFactoryBean().getScheduler();
    }

}

MyJobFactory.java:

这个类需要继承org.springframework.scheduling.quartzAdaptableJobFactory类,实现createJobInstance()方法。这个方法主要是实现注入,创建一个Job实例。返回给SchedulerConfig.java中的setJobFactory()

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 MyJobFactory extends AdaptableJobFactory {
    @Autowired
    private AutowireCapableBeanFactory capableBeanFactory;

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

Controller,这里的参数不是传统的传递参数,需要创建JobDataMap,  .put()方法实现值和参数的传递。

Quaz.class代表你的实现quarz调度方法的类。

withIdentity的两个参数一个代表实例名,和实例名

CronScheduleBuilder.cronSchedule("0/5 * *  * * ?")这里要用到cron表达式,5秒执行一次。

在线Cron表达式生成器

@RequestMapping("/quartzRun")
    public void quartzRun(@RequestParam("name")String name, @RequestParam("msg") String msg) throws SchedulerException {
        SchedulerFactory sf = new StdSchedulerFactory();
        JobDataMap jobDataMap = new JobDataMap();
        jobDataMap.put("name",name);
        jobDataMap.put("msg",msg);
        Scheduler sched = sf.getScheduler();
        JobDetail job = newJob(Quaz.class).withIdentity("HelloJob", "group1").setJobData(jobDataMap).build();
        CronTrigger trigger = newTrigger().withIdentity("HelloJob", "group1").withSchedule(CronScheduleBuilder.cronSchedule("0/5 * *  * * ?")).build();
        sched.scheduleJob(job, trigger);
        scheduler.start();
    }

servicesImpl:

需要实现package org.quartz Job接口下的execute()方法。

package com.jd.db.mydemodb.controller;
import com.jd.db.mydemodb.Entity.TestEntity;
import com.jd.db.mydemodb.service.BaseJob;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.stereotype.Service;
@Service
public class Quaz implements Job{

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        System.out.println(new Date());
        JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
        System.out.println(jobDataMap.getString("name"));
        System.out.println(jobDataMap.getString("msg"));
        System.out.println(new Date());
    }
}

 

然后通过context.getJobDetail().getJobDataMap()去获取Controller传过来的值,基本上所有类型就有。

注意:这里不知道是不是坑,我查了很多资料还是没有解决。比如你的Controller层使用@Autowired自动匹配查找某个实现类(@Service),然后你将这个自动匹配的这个类通过jobDataMap.put将值丢进去,那么你的impl会返回空指针异常,只能再Controller通过 service service = new ServicesImpl()的方式将其put进去比如:

但是如果你@Autowried Dao层,则可以直接put

最后一步,拿postman测试一下,看看结果如何

 

 如果想要停止这个定时任务呢?只需要三句核心代码:

这里先停止,再删除,如果没有执行sched.deletejob,再次启动则需要更换之前的实例名组名

所以在这里,我们直接删除,之后还可以继续重新启动。

@RequestMapping("/pause")
    public void pause(){
        SchedulerFactory sf = new StdSchedulerFactory();
        try {
            Scheduler sched = sf.getScheduler();
            sched.pauseJob(JobKey.jobKey("HelloJob", "group1"));
            sched.deleteJob(JobKey.jobKey("HelloJob", "group1"));
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
        System.out.println("ok");
    }

试试看:

有不够好的还希望多指教,感谢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值