文章目录

  • 前言
  • 一、@Scheduled
  • 二、Quartz



前言

定时任务是企业级开发中最常见的功能之一,如定时推送短信和邮件、数据库备份、定时统计收益、定时统计访客等,简单的定时任务可以直接通过Spring中的@Scheduled注解来实现,复杂的定时任务则可以通过集成Quartz来实现,下面分别介绍。


一、@Scheduled

@Scheduled是Spring提供的定时任务注解,使用方便,配置简单,可以解决工作中大部分的定时任务需求,使用方式如下:

  1. 首先创建一个普通的Spring Boot Web工程,添加Web依赖即可,代码如下:
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
</dependency>
  1. 然后在项目启动类上添加@EnableScheduling注解开启定时任务
  2. 定时任务主要通过@Scheduled注解进行配置,类上要加@Component,代码和注释如下:
@Component
public class TestSchedule {

    //其中fixedDelay = 1000表示在当前任务执行结束1秒后开启另一个任务
    @Scheduled(fixedDelay = 1000)
    public void testSchedule1(){
        System.out.println("fixedDelay执行啦......");
    }
    //fixedRate = 1000表示在当前任务开始执行1秒后开启另一个定时任务
    @Scheduled(fixedRate = 1000)
    public void testSchedule2(){
        System.out.println("fixedRate执行啦......");
    }
    //initialDelay = 1000则表示首次执行的延迟时间
    @Scheduled(initialDelay = 1000,fixedRate = 2000)
    public void testSchedule3(){
        System.out.println("initialDelay执行啦......");
    }
    //使用cron表达式, cron = "* * * * * *"表示该定时任务每秒钟执行一次
    @Scheduled(cron = "* * * * * *")
    public void testSchedule4(){
        System.out.println("cron执行啦......");
    }
}

配置完成后,接下来启动Spring Boot项目即可,定时任务部分打印日志如图:

Spring boot 定时任务 不执行 spring boot实现定时任务_idea

@Scheduled使用注意事项:如果是分布式架构,在每一台机器上都会在同时执行定时调度任务,可能产生很多重复数据或者导致系统出现其他的业务逻辑BUG,所以在使用@Scheduled进行任务调度时,一定要配合redis的分布式锁来使用,让定时调度任务只在一台机器上执行,避免BUG出现


二、Quartz

Quartz简介:
Quartz是一个功能丰富的开源作业调度库,它由Java写成,可以集成在任何Java应用程序中,包括Java SEJava EE等。使用Quartz可以创建简单或者复杂的执行计划,它支持数据库、集群、插件以及邮件,并且支持cron表达式,具有极高的灵活性。Spring Boot中集成Quartz和Spring中集成Quartz比较类似,主要提供三个Bean:JobDetailTrigger以及SchedulerFactory

Quartz整合Springboot

  1. 首先创建Spring Boot项目,添加Quartz依赖:
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
  1. 然后创建两个Job,代码如下:

Job可以是一个普通的JavaBean,如果是普通的JavaBean,那么可以先添加@Component注解将之注册到Spring容器中。

@Component
public class MyFirstJob {
    public void sayHello() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date now = new Date();
        System.out.println("MyFirstJob:sayHello: " + sdf.format(now));
    }
}

Job也可以继承抽象类QuartzJobBean,若继承自QuartzJobBean,则需要实现该类中的executeInternal方法,该方法在任务被调用时使用

public class MySecondJob extends QuartzJobBean {
    private String name;

    public void setName(String name) {
        this.name = name;
    }

    @Override
    protected void executeInternal(JobExecutionContext context) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date now = new Date();
        System.out.println("hello: " + name + " : " + sdf.format(now));
    }
}
  1. 接下来创建QuartzConfig对JobDetail和Trigger进行配置,代码如下:
@Configuration
public class QuartzConfig {

    @Bean
    MethodInvokingJobDetailFactoryBean jobDetail1() {
        MethodInvokingJobDetailFactoryBean bean = new MethodInvokingJobDetailFactoryBean();
        bean.setTargetBeanName("myFirstJob");
        bean.setTargetMethod("sayHello");
        return bean;
    }

    @Bean
    JobDetailFactoryBean jobDetail2() {
        JobDetailFactoryBean bean = new JobDetailFactoryBean();
        bean.setJobClass(MySecondJob.class);
        JobDataMap jobDataMap = new JobDataMap();
        jobDataMap.put("name", "sang");
        bean.setJobDataMap(jobDataMap);
        bean.setDurability(true);
        return bean;
    }

    @Bean
    SimpleTriggerFactoryBean simpleTrigger() {
        SimpleTriggerFactoryBean bean = new SimpleTriggerFactoryBean();
        bean.setJobDetail(jobDetail1().getObject());
        bean.setRepeatCount(3);
        bean.setStartDelay(1000);
        bean.setRepeatInterval(2000);
        return bean;
    }
    @Bean
    CronTriggerFactoryBean cronTrigger() {
        CronTriggerFactoryBean bean = new CronTriggerFactoryBean ();
        bean.setJobDetail(jobDetail2().getObject());
        bean.setCronExpression("* * * * * ?");
        return bean;
    }
    @Bean
    SchedulerFactoryBean schedulerFactory() {
        SchedulerFactoryBean bean = new SchedulerFactoryBean();
        SimpleTrigger simpleTrigger = simpleTrigger().getObject();
        CronTrigger cronTrigger = cronTrigger().getObject();
        bean.setTriggers(simpleTrigger, cronTrigger);
        return bean;
    }
}

代码解释:

  • JobDetail的配置有两种方式:第一种方式通过MethodInvokingJobDetailFactoryBean类配置JobDetail,只需要指定Job的实例名和要调用的方法即可,注册这种方式无法在创建JobDetail时传递参数;第二种方式是通过JobDetailFactoryBean来实现的,这种方式只需要指定JobClass即可,然后可以通过JobDataMap传递参数到Job中,Job中只需要提供属性名,并且提供一个相应的set方法即可接收到参数。
  • Trigger有多种不同实现,这里展示两种常用的Trigger:SimpleTriggerCronTrigger,这两种Trigger分别使用SimpleTriggerFactoryBeanCronTriggerFactoryBean进行创建。在SimpleTriggerFactoryBean对象中,首先设置JobDetail,然后通过setRepeatCount配置任务循环次数,setStartDelay配置任务启动延迟时间,setRepeatInterval配置任务的时间间隔。在CronTriggerFactoryBean对象中,则主要配置JobDetail和Cron表达式。
  • 最后通过SchedulerFactoryBean创建SchedulerFactory,然后配置Trigger即可。

经过这几步的配置,定时任务就配置成功了。接下来启动Spring Boot项目,控制台打印日志如图所示:

Spring boot 定时任务 不执行 spring boot实现定时任务_idea_02