定时任务的两种实现方式
@Scheduled
使用@Scheduled非常容易,直接创建一个SpringBoot项目,并且添加web依赖spring-boot-starter-web,项目创建成功后,添加@EnableScheduling注解,开启定时任务:
@SpringBootApplication
@EnableScheduling
public class SpringbootQuartzScheduledApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootQuartzScheduledApplication.class, args);
}
}
然后配置定时任务:
@Scheduled(fixedRate = 2000)
/*fixedRate表示两次任务开始时间的间隔*/
public void fixedRate(){
System.out.println("fixRate>>> " +new Date());
}
@Scheduled(fixedDelay = 2000)
/*fixedDelay表示第一次任务结束到第二次任务开始之间的间隔*/
public void fixeDelay(){
System.out.println("fixedDelay>>>" +new Date());
}
@Scheduled(initialDelay = 2000,fixedDelay = 2000)
/*initialDelay表示任务首次启动的延迟时间*/
public void initialDelay( ){
System.out.println("initialDelay>>>"+ new Date( ));
}
其次@Scheduled也支持cron表达式,它的格式如下:
[秒][分][小时][日][月][周][年]
序号 | 说明 | 是否必填 | 允许填写的值 | 允许的通配符 |
---|---|---|---|---|
1 | 秒 | 是 | 0-59 | - * / |
2 | 分 | 是 | 0-59 | - * / |
3 | 时 | 是 | 0-23 | - * / |
4 | 日 | 是 | 1-31 | - * / ? L W |
5 | 月 | 是 | 1-12 or JAN-DEC | - * / |
6 | 周 | 是 | 1-7 or sun-SAT | - * / ? L ## |
7 | 年 | 否 | 1970-2099 | - * / |
通配符含义
? 表示不指定值,即不关心某个字段的取值使用,月份中的日期和星期可能产生冲突,在配置时最好一个为?
* 表示所有值,在秒字段上设置*,表示每一秒都会触发
, 用来分开多个值,在周字段上设置"MON,WED,FRI"表示周一,周三,周五触发
- 表示区间,秒上设置"10-12"表示10,11,12秒会触发
/ 表示递增触发,秒上设置"5/15"表示从5秒开始,每隔15秒触发一次
## 序号,例如周字段上设置"6##3"表示在每月的第三个周六,且可以使用英文(不区分大小写)
L 表示最后的意思,在日字段上设置表示当月的最后一天。在周字段上设置"6L"表示"本月最后一个星期五"
W 表示离指定日期的最近工作日(周一至周五),例如在日字段上设置"15W"表示距离每月15号最近的工作日触发,例如设置员工发工资的日期。
L和W一起组合使用,如果在日字段上设置"LW",则表示在本月的最后一个工作日触发。
@Scheduled(cron = "0/5 * * * * *")
//表示该方法每5秒执行一次
public voud cron(){
System.out.println("date:"+new Date());
}
接下来我们看如何用第三方框架Quartz来实现
业务简单的时候可以用@Scheduled注解来解决任务,否则大部分情况下可能都是使用Quartz来做定时任务的,使用Quartz的步骤:
一、添加pom依赖
![](https://i-blog.csdnimg.cn/blog_migrate/6a7efa0aae4ae9e8d6f5dbb8801374fe.jpeg)
二、在项目主启动类上开启定时任务的注解@EnableScheduling
@SpringBootApplication
@EnableScheduling
public class SpringbootQuartzScheduledApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootQuartzScheduledApplication.class, args);
}
}
三、Quatrz使用过程中有两个概念,一个是jobDetail,另一个是触发器,要定义jobDetail首先要定义job,这里有两种方式来定义job
@Component
public class MyJob1{
public void sayHello( ){
System.out.println("myjob>>>"+new Date());
}
}
它的缺点是无法传参。
第二种方式则是集成QuartzJobBean并实现默认的方法
创建如下三个类,HelloService是用来模拟提供服务的类
public class HelloService{
public void sayHello(){
System.out.println("hello service>>>"+System.currentTimeMillis());
}
}
MyJob2继承QuartzJobBean
public class Myjob2 extends QuartzJobBean {
private HelloService helloService;
public HelloService getHelloService(){
return helloService;
}
public void setHelloService(HelloService helloService){
this.helloService = helloService;
}
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext)
{
helloService.sayHello();
}
}
与第一种方式相比,这种方式支持传参,任务启动时,executeInternal方法将会被执行。job创建好之后接下来创建类,配置JobDetail和Trigger触发器,如下:
@Configuration
public class QuartzConfig {
@Bean
MethodInvokingJobDetailFactoryBean methodInvokingJobDetailFactoryBean() {
MethodInvokingJobDetailFactoryBean bean = new MethodInvokingJobDetailFactoryBean();
bean.setTargetBeanName("myjob1");
bean.setTargetMethod("sayHello");
return bean;
}
@Bean
JobDetailFactoryBean jobDetailFactoryBean() {
JobDetailFactoryBean bean = new JobDetailFactoryBean();
bean.setJobClass(Myjob2.class);
JobDataMap map = new JobDataMap();
map.put("helloService",helloService());
bean.setJobDataMap(map);
return bean;
}
/*设置触发器SimpleTrigger*/
@Bean
SimpleTriggerFactoryBean simpleTriggerFactoryBean() {
SimpleTriggerFactoryBean bean = new SimpleTriggerFactoryBean();
bean.setStartTime(new Date());
//设置执行次数
bean.setRepeatCount(5);
bean.setJobDetail(methodInvokingJobDetailFactoryBean().getObject());
/*MyJob每3秒执行一次*/
bean.setRepeatInterval(3000);
return bean;
}
/*设置触发器CronTrigger*/
@Bean
CronTriggerFactoryBean cronTrigger() {
CronTriggerFactoryBean bean = new CronTriggerFactoryBean();
/*设置每10秒执行一次*/
bean.setCronExpression("0/10 * * * * ?");
bean.setJobDetail(jobDetailFactoryBean().getObject());
return bean;
}
@Bean
SchedulerFactoryBean schedulerFactoryBean() {
SchedulerFactoryBean bean = new SchedulerFactoryBean();
bean.setTriggers(cronTrigger().getObject(), simpleTriggerFactoryBean().getObject());
return bean;
}
@Bean
HelloService helloService() {
return new HelloService();
}
}
运行结果如图:
![](https://i-blog.csdnimg.cn/blog_migrate/3c7c4999b1dd4108f3bbd9586c89810d.png)
关于这个配置类的说明如下:
1.JobDetail的配置方式有两种:MethodInvokingJobDetailFactoryBean和JobDetailFactoryBean。
2.使用MethodInvokingJobDetailFactoryBean 可以配置目标Bean的名字和目标方法的名字,但是不支持传参
3.使用JobDetailFactoryBean可以配置JobDetail,任务类继承自QuartzJobBean,这种方式支持传参,参数封装在JobDataMap中传递。
4.Trigger是指触发器,Quartz中定义了多个触发器,上面代码使用了其中两种,SimpleTrigger和CronTrigger。
5.SimpleTrigger有点类似于前面说的@Scheduled的基本用法。
6.CronTrigger则有点类似于@Scheduled中cron表达式的用法
配置好以后就可以直接运行主启动类,里面定义的定时任务就会按照要求执行