史上最强读取数据库定时任务

本文介绍如何在SpringBoot项目中使用Quartz进行定时任务的开发,包括使用@Date注解减少代码量,以及通过MethodInvokingJobDetailFactoryBean、implementsJob和extendsQuartzJobBean三种方式实现定时任务。重点讲解了第一种方法的具体配置步骤,从任务类的创建到触发器和调度工厂的配置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先看一下lombok
这篇文件说的很详细
有了lambok这个就可以使用@Date减少我们需要开发的代码
我们使用Quartz来开发定时任务
有三种方法
MethodInvokingJobDetailFactoryBean
implements Job
extends QuartzJobBean

下面我们来看一下第一种(MethodInvokingJobDetailFactoryBean)

任务类

@Configuration
@Component
@EnableScheduling
public class ScheduledTask {

    public void sayHello(){
        System.out.println("hello");
    }

}

定时任务在配置类上添加@EnableScheduling开启对定时任务的支持
@Component作为bean注册到spring容器
@Configuration 配置到<beans>中

配置定时器类使用的是springboot,所有的都是通过spring来管理的,所以返回值通过@Bean来注册到spring容器


@Slf4j
@Configuration
public class QuartzConfig {

}

配置定时器类的方法

@Bean(name = "jobDetail")
    public MethodInvokingJobDetailFactoryBean detailFactoryBean(ScheduledTask task){
        MethodInvokingJobDetailFactoryBean jobDetail = new MethodInvokingJobDetailFactoryBean();
        /*
         * 是否并发执行
         * 例如每5s执行一次任务,但是当前任务还没有执行完,就已经过了5s了,
         * 如果此处为true,则下一个任务会执行,如果此处为false,则下一个任务会等待上一个任务执行完后,再开始执行
         */
        jobDetail.setConcurrent(false);
        //设置定时任务的名字
        jobDetail.setName("srd-demo");
        //设置任务的分组,这些属性都可以在数据库中,在多任务的时候使用
        jobDetail.setGroup("srd");

        //为需要执行的实体类对应的对象
        jobDetail.setTargetObject(task);

        /*
         * sayHello为需要执行的方法
         * 通过这几个配置,告诉JobDetailFactoryBean我们需要执行定时执行ScheduleTask类中的sayHello方法
         */
        jobDetail.setTargetMethod("sayHello");
        log.info("jobDetail 初始化成功!");
        return jobDetail;
    }

在MethodInvokingJobDetailFactoryBean属性初始化完后,通过MethodInvoker封装TargetObject的TargetMethod方法并在executeInternal中调用MethodInvoker.invoke()来生产job。

返回MethodInvokingJobDetailFactoryBean,将任务job通过@bean注册到spring容器中

@Bean(name = "jobTrigger")
    public CronTriggerFactoryBean cronTriggerFactoryBean(MethodInvokingJobDetailFactoryBean jobDetail){
        CronTriggerFactoryBean trigger = new CronTriggerFactoryBean();
        trigger.setJobDetail(jobDetail.getObject());
        //初始化的cron表达式(每天上午10:15触发)
        trigger.setCronExpression("0 15 10 * * ?");
        //trigger的name
        trigger.setName("srd-demo");
        log.info("jobTrigger 初始化成功!");
        return trigger;
    }

配置一个触发器

 /**
     * 方法名:
     * 功能:定义quartz调度工厂
     * 描述:
     * 创建人:typ
     * 创建时间:2018/10/10 14:06
     * 修改人:
     * 修改描述:
     * 修改时间:
     */
    @Bean(name = "scheduler")
    public SchedulerFactoryBean schedulerFactoryBean(Trigger trigger){
        SchedulerFactoryBean factoryBean = new SchedulerFactoryBean();
        //用于quartz集群,QuartzScheduler启动时更新已存在的job
        factoryBean.setOverwriteExistingJobs(true);
        //延时启动,应用启动1秒后
        factoryBean.setStartupDelay(1);
        //注册触发器
        factoryBean.setTriggers(trigger);
        log.info("scheduler 初始化成功!");
        return factoryBean;
    }

public class SchedulerFactoryBean extends SchedulerAccessor implements FactoryBean<Scheduler>,
		BeanNameAware, ApplicationContextAware, InitializingBean, DisposableBean, SmartLifecycle {
}

实现了initializingBean接口,重写了afterPropertiesSet()方法,在这个方法里面
a. 创建了SchedulerFactory
b. 创建Scheduler
c. 如果有jobFactory属性,那么set
d. 注册Scheduler、Job、Trigger的监听器listener(如果有定义的话)
e. 注册Job和Trigger

此外,我们对于Quartz Job的参数设定,也是通过SchedulerFactoryBean类来实现的
[]public static final int DEFAULT_THREAD_COUNT = 10; 默认线程数为10。
[
]private String schedulerName; Scheduler的名字,若没有定义则默认用bean的名称(name)。
[]private Resource configLocation; Quartz的配置如quartz.properties的存放位置,若是在xml中配置,则可以写成<property name=“configLocation” value=“classpath:quartz.properties”/>。
[
]private Properties quartzProperties; 若是使用Annotation来定义bean,那么初始化quartz.properties可以用bean.setQuartzProperties(Properties)。
[*]private JobFactory jobFactory; 注入一个JobFactory对象。

/**
     * 方法名:
     * 功能:每隔10s查库,并根据查询结果决定是否重新设置定时任务
     * 描述:
     * 创建人:typ
     * 创建时间:2018/10/10 14:19
     * 修改人:
     * 修改描述:
     * 修改时间:
     */
    @Scheduled(fixedRate = 10000)
    public void scheduleUpdateCronTrigger() throws SchedulerException {
        CronTrigger trigger = (CronTrigger) scheduler.getTrigger(cronTrigger.getKey());
        //当前Trigger使用的
        String currentCron = trigger.getCronExpression();
        log.info("currentCron Trigger:{}", currentCron);
        //从数据库查询出来的
        String searchCron = repository.findAll().get(0).getCron();
        log.info("searchCron  Trigger:{}", searchCron);

        if (currentCron.equals(searchCron)) {
            // 如果当前使用的cron表达式和从数据库中查询出来的cron表达式一致,则不刷新任务
        } else {
            //表达式调度构建器
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(searchCron);
            //按新的cronExpression表达式重新构建trigger
//            trigger = (CronTrigger) scheduler.getTrigger(cronTrigger.getKey());
//            trigger.getTriggerBuilder()获取静态的TriggerBuilder
            trigger = trigger.getTriggerBuilder().withIdentity(cronTrigger.getKey()).withSchedule(scheduleBuilder).build();
            // 按新的trigger重新设置job执行
            scheduler.rescheduleJob(cronTrigger.getKey(), trigger);
//            currentCron = searchCron;
        }
    }

重新配置trigger

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值