本篇设计到的注解
1@Scheduled()
里面四种参数:
+fixedDelay:任务执行完成多久之后,下个任务开始执行
+ fixedRate:任务执行开始多久之后,下个任务开始执行
+initialDelay:默认情况下,项目启动之后,定时任务就开始执行了,可以通过这个属性来配置第一次延迟多久执行。
+自定义的cron表达式:如何使用cron表达式去搜索cron表达式生成器
一.Spring中自带的注解
注意:
1.注解方式实现的定时任务不方便,启动之后不更改代码是无法停止的,也没办法在启动后去加定时任务或者修改之前定义的定时任务是没办法做到的。
2.注解@Scheduled()
里面四种参数:
+fixedDelay:任务执行完成多久之后,下个任务开始执行
+ fixedRate:任务执行开始多久之后,下个任务开始执行
+initialDelay:默认情况下,项目启动之后,定时任务就开始执行了,可以通过这个属性来配置第一次延迟多久执行。
+自定义的cron表达式:如何使用cron表达式去搜索cron表达式生成器
/**
* fixedDelay:任务执行完成多久之后,下个任务开始执行
* fixedRate:任务执行开始多久之后,下个任务开始执行
* initialDelay:默认情况下,项目启动之后,定时任务就开始执行了,可以通过这个属性来配置第一次延迟多久执行。
*
* https://cron.qqe2.com/
* https://www.bejson.com/othertools/cron/
*/
// @Scheduled(fixedRate = 1000,initialDelay = )
//注意,con表达式直接去百度搜索cron表达式生成器
@Scheduled(cron = "0/5 * * * * ?")
public void heihei() {
logger.info("hello");
}
二.Quartz
定时任务被拆分成为两块:
A:作业:时间到了要做的事情
B: 触发器: 什么情况下执行
2.1导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
2.2 两种作业定义方式
2.2.1第一种作业定义方式
注意:
1.第一种作业定义方式,定义一个任意名称的类,方法的定义也是任意的,
这意味着在配置接口文档的时候要明确告诉前端仔,这个接口的作用和调用的方法
//将作业注册到 Spring 容器中即可
@Component
package com.huang.springboot9.Quartz;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.quartz.QuartzJobBean;
/**
* 第二种作业定义方式,需要继承自 QuartzJobBean,实现这个里边的抽象方法executeInternal
* 差别1.用这种方法去定义作业,不管定义多少种作业,最终实现的都是executeInternal,
* 他的方法名是不会变的,所以用这种方法去配置,等下就不用去指定方法名
*
* 差别1:和第一种作业定义方式相比,这种作业定义方式可以传参数进来
*/
public class TwistQuartz extends QuartzJobBean {
//第二步,加载入logger
private static final Logger logger = LoggerFactory.getLogger(FirstQuartz.class);
//第三步,定义要传入的参数
private String name;
public void setName(String name) {
this.name = name;
}
//第一步:实现这个QuartzJobBean的实现类
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
//写法的形式要注意:
logger.info("executeInternal,{}", name);
}
}
2.2.2第二种作业定义方式
第二种作业定义方式,需要继承自 QuartzJobBean,实现这个里边的抽象方法executeInternal
差别1.用这种方法去定义作业,不管定义多少种作业,最终实现的都是executeInternal,
他的方法名是不会变的,所以用这种方法去配置,等下就不用去指定方法名
差别2:和第一种作业定义方式相比,这种作业定义方式可以传参数进来
package com.huang.springboot9.Quartz;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.quartz.QuartzJobBean;
/**
* 第二种作业定义方式,需要继承自 QuartzJobBean,实现这个里边的抽象方法executeInternal
* 差别1.用这种方法去定义作业,不管定义多少种作业,最终实现的都是executeInternal,
* 他的方法名是不会变的,所以用这种方法去配置,等下就不用去指定方法名
*
* 差别1:和第一种作业定义方式相比,这种作业定义方式可以传参数进来
*/
public class TwistQuartz extends QuartzJobBean {
//第二步,加载入logger
private static final Logger logger = LoggerFactory.getLogger(FirstQuartz.class);
//第三步,定义要传入的参数
private String name;
public void setName(String name) {
this.name = name;
}
//第一步:实现这个QuartzJobBean的实现类
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
/* 写法的形式要注意:springBoot中使用的slf4j的日志处理器,用的字符串拼接的方法
这个使用的十分方便,重点看黄黄后面的日志小总结*/
logger.info("executeInternal,{}", name);
}
}
2.3定义触发器(仔细看)
package com.huang.springboot9.Quartz.config;
import com.huang.springboot9.Quartz.TwistQuartz;
import org.quartz.JobDataMap;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.*;
import java.util.Date;
/**
* 1. 首先对作业重新包装,将作业包装成一个 JobDetail
* 第二种方式因为JobDetail是一个接口
* 2. 定义触发器
* 3. 启动定时任务
*/
@Configuration
public class QuartzConfig {
/**
* 作业是一个自定义的类,并且注册到Spring容器中去了,那么就用这个去处理job,
* 在这里就是我们例子中的firstQuartz方法
* @return
*/
@Bean
MethodInvokingJobDetailFactoryBean methodInvokingJobDetailFactoryBean(){
MethodInvokingJobDetailFactoryBean bean = new MethodInvokingJobDetailFactoryBean();
//设置目标bean的名称
bean.setTargetBeanName("firstQuartz");
//设置要执行的方法名称
bean.setTargetMethod("hello");
return bean;
}
/**
* 如果是通过继承类的方式定义的作业,那么通过这个方式来进行二次处理,
* 对应的我们的TwistQuartz方法
*
* @return
*/
@Bean
JobDetailFactoryBean jobDetailFactoryBean() {
JobDetailFactoryBean bean = new JobDetailFactoryBean();
bean.setJobClass(TwistQuartz.class);
JobDataMap data = new JobDataMap();
data.put("name", "张三");
//传参
bean.setJobDataMap(data);
return bean;
}
/**
* 构建一个简单触发器,返回我们自定义的类的methodInvokingJobDetailFactoryBean对象,
* 也就是对应的我们对象FirstQuartz我们这里的方法
* @return
*/
@Bean
SimpleTriggerFactoryBean simpleTriggerFactoryBean() {
SimpleTriggerFactoryBean bean = new SimpleTriggerFactoryBean();
//定时任务的启动时间
bean.setStartTime(new Date());
//定时任务重复的时间间隔
bean.setRepeatInterval(2000);
//定时任务重复的次数
bean.setRepeatCount(3);
//jobdetail对应的是哪一个作业,
bean.setJobDetail(methodInvokingJobDetailFactoryBean().getObject());
return bean;
}
/**
* 这是一个支持 cron 表达式的触发器,返回我们的第二种方法
* @return
*/
@Bean
CronTriggerFactoryBean cronTriggerFactoryBean() {
CronTriggerFactoryBean factoryBean = new CronTriggerFactoryBean();
factoryBean.setCronExpression("0/3 * * * * ?");
factoryBean.setJobDetail(jobDetailFactoryBean().getObject());
return factoryBean;
}
/**
* 定时任务启动器,返回两种触发器的对象
* @return
*/
@Bean
SchedulerFactoryBean schedulerFactoryBean() {
SchedulerFactoryBean bean = new SchedulerFactoryBean();
bean.setTriggers(simpleTriggerFactoryBean().getObject(),cronTriggerFactoryBean().getObject());
return bean;
}
}
三.Elastic-Job
四.xxl-job: 支持分布式的、可以动态配置的定时任务
可以让某个定时任务暂停,甚至是停止