springboot-定时任务一(Quartz)

定时任务(Quartz)

Quartz介绍

  1. Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,它可以与J2EE与J2SE应用程序相结合也可以单独使用。Quartz可以用来创建简单或为运行十个,百个,甚至是好几万个Jobs这样复杂的程序。Jobs可以做成标准的Java组件或EJBs

Quartz使用思路

主要围绕三个环节进行开发

  1. job - 任务 -你要做什么事
  2. Trigger -触发器 -你什么时候去做
  3. Scheduled -任务调度 -你什么时候要去做什么事

springboot 结合Quartz

实现简单的定时任务,首先导入依赖:

 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- scheduled所属资源为spring-context-support,在Spring中对Quartz的支持,是集成在spring-context-support包中。
           org.springframework.scheduling.quartz
        -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
        </dependency>
        <!--Quartz-->
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>2.3.0</version>
            <!-- Quartz默认需要slf4j支持。springboot中,提供了更高版本的slf4j -->
            <exclusions>
                <exclusion>
                    <artifactId>slf4j-api</artifactId>
                    <groupId>org.slf4j</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <!-- Spring tx 坐标,quartz可以提供分布式定时任务环境。多个分布点上的Quartz任务,是通过数据库实现任务信息传递的。
            通过数据库中的数据,保证一个时间点上,只有一个分布环境执行定时任务。
         -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
        </dependency>

启动器添加注解@EnableScheduling:

SpringBootApplication
@EnableScheduling //开启定时任务机制
public class ScheduleApplication {

    public static void main(String[] args) {
        SpringApplication.run(ScheduleApplication.class, args);
    }

}

定义JOB任务以及JOB任务调用的模拟业务对象:


**
 * 简单Job类
 */

public class QuartzDemo implements Job {

@Autowired
private UserService userService;

    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        System.out.println("定时任务"+new Date());
        this.userService.UserList();
    }
}
@Service
public class UserService {
    public void UserList(){
        System.out.println("查询User列表");
    }

}

定义配置类。主要围绕三个环节进行开发:

/**
 * Quartz配置类
 */
@Configuration
public class QuartzConfig {
    /**
     * 1.创建Job对象。
     * 在Spring环境中,创建一个类型的对象的时候,很多情况下,都是通过FactoryBean来间接创建的。
     * 如果有多个Job对象,定义多次方法。
     *
     * 在JobDetailFactoryBean类型中,用于创建JobDetail对象的方法,其底层使用的逻辑是:Class.newInstance()
     * 也就是说,JobDetail对象不是通过Spring容器管理的。
     * 因为Spring容器不管理JobDetail对象,那么Job中需要自动装配的属性,就无法实现自动状态。如JOB会报空指针异常。
     *
     * 解决方案是: 将JobDetail加入到Spring容器中,让Spring容器管理JobDetail对象。
     * 需要重写Factory相关代码。实现Spring容器管理JobDetail。
     * @return
     */
     @Bean
    public JobDetailFactoryBean jobDetailFactoryBean(){
         JobDetailFactoryBean factoryBean=new JobDetailFactoryBean();
         //关联我们自己的Job类
         factoryBean.setJobClass(QuartzDemo.class);

         return factoryBean;
     }


    /**
     * 2.创建Trigger对象
     * CronTrigger - 就是Trigger的一个实现类型。 其中用于定义周期时间的是CronSchedulerBuilder
     * 实际上,CronTrigger是用于管理一个Cron表达式的类型。
     * @param jobDetailFactoryBean - 上一个方法初始化的JobDetailFactoryBean
     * @return
     */
    @Bean
    public CronTriggerFactoryBean cronTriggerFactoryBean(JobDetailFactoryBean jobDetailFactoryBean){
        CronTriggerFactoryBean factoryBean=new CronTriggerFactoryBean();
        //关联jobDetail对象
        factoryBean.setJobDetail(jobDetailFactoryBean.getObject());
        //设置触发时间
        factoryBean.setCronExpression("0/2 * * * * ?");//两秒触发一次
        return factoryBean;
    }


    /**
     * 3.创建Scheduled对象
     * @param cronTriggerFactoryBean - 上一个方法初始化的CronTriggerFactoryBean
     */
     @Bean
    public SchedulerFactoryBean schedulerFactoryBean(MyJobFactory myJobFactory,CronTriggerFactoryBean[] cronTriggerFactoryBean){
        SchedulerFactoryBean factoryBean=new SchedulerFactoryBean();
        //关联Trigger对象,可能有多个对象
        CronTrigger[] triggers = new CronTrigger[cronTriggerFactoryBean.length];
        for(int i = 0; i < cronTriggerFactoryBean.length; i++){
            triggers[i] = cronTriggerFactoryBean[i].getObject();
        }
        factoryBean.setTriggers(triggers);

        // 为Scheduler设置JobDetail的工厂。可以覆盖掉SpringBoot提供的默认工厂,保证JobDetail中的自动装配有效。
        factoryBean.setJobFactory(myJobFactory);
        return factoryBean;
    }
}

重写Job工厂

@Component
public class MyJobFactory extends AdaptableJobFactory {
    /**
     * AutowireCapableBeanFactory : 简单理解为Spring容器,是Spring容器Context的一个Bean对象管理工程。
     * 可以实现自动装配逻辑,和对象创建逻辑。
     * 是SpringIoC容器的一个重要组成部件。
     */
    @Autowired
    private AutowireCapableBeanFactory autowireCapableBeanFactory;
    /**
     *  在JobDetailFactoryBean类型中,用于创建JobDetail对象的方法,其底层使用的逻辑是:Class.newInstance()
     * 也就是说,JobDetail对象不是通过Spring容器管理的,而是反射。
     * 因为Spring容器不管理JobDetail对象,那么Job中需要自动装配的属性,就无法实现自动状态。如JOB会报空指针异常。
     */
    @Override
    protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
        // 通过父类型中的方法,创建JobDetail对象。
        Object obj=super.createJobInstance(bundle);
         // 将JobDetail对象加入到Spring容器中,让Spring容器管理,并实现自动装配逻辑。
        this.autowireCapableBeanFactory.autowireBean(obj);
       return obj;
    }
}

注:如果不将job对象放入ioc容器中,就不会被spring管理,userService就无法自动注入,将会报:
解决就是在 第三步3.创建Scheduled对象 中 将JobDetail对象加入到Spring容器中,让Spring容器管理,并实现自动装配逻辑。
//factoryBean.setJobFactory(myJobFactory);

java.lang.NullPointerException: null
	at com.huang.schedule.quartz.QuartzDemo.execute(QuartzDemo.java:23) ~[classes/:na]
	at org.quartz.core.JobRunShell.run(JobRunShell.java:202) ~[quartz-2.3.0.jar:na]
	at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573) [quartz-2.3.0.jar:na]

运行:
定时任务运行

到此为止,我们的简单的使用Quartz执行定时任务就完成了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值