定时任务

cron表达式

在线cron表达式生成器:https://cron.qqe2.com/

SpringBoot使用定时任务

配置文件

1
2
3
4
5
6
7
8
9
# Spring配置
spring:
# 异步线程定时任务设置
task:
execution:
pool:
# 定时任务线程池大小设置
core-size: 5
max-size: 50

配置类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.xiaofei.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;

/**
* 定时任务配置类
* Date: 2023/3/8
*
* @author XiaoFei
*/
@EnableAsync//开启异步
@EnableScheduling//开启定时任务
@Configuration
public class ScheduledConfig {

}

使用

1
2
3
4
5
6
7
8
9
@Component
public class TestScheduled {

//cron表达式可以使用上面给的cron表达式生成
@Scheduled(cron = "0/5 * * * * ? ")
public void test(){
System.out.println("哈哈哈哈");
}
}

分布式任务调度

一个SpringBoot应用部署多个节点,会导致应用中的定时任务重复执行,这个时候需要引入分布式任务调度系统,对系统中的定时任务进行统一管理

xxl-job

如果该文档不能满足需求,可以查看官方文档查看详细使用

下载xxl-job

xxl-job仓库地址:https://gitee.com/xuxueli0323/xxl-job

官方文档:https://www.xuxueli.com/xxl-job/

该文档使用的是xxl-job-2.3.1版本进行编写,按照官方文档将xxl-job-admin进行启动,然后再参照xxl-job-executor-sample-springboot模块,将xxl-job-admin集成到系统中

创建一个spring boot项目

下载代码生成器,快速创建一个spring boot项目进行测试:https://gitee.com/xiao-i-fei/xiaofei-generator

引入依赖

1
2
3
4
5
6
<!-- xxl-job-core -->
<dependency>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-job-core</artifactId>
<version>2.3.1</version>
</dependency>

配置文件

配置文件中的address+port最终会注册到xxl-admin中的执行器中,所以address+port必须是唯一的,如果没有配置address,则会使用本机默认ip,这时,同一台机器如果启动多个项目,port就必须唯一了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
xxl:
job:
# 执行器通讯TOKEN [选填]:非空时启用:需要和调度中心模块中配置的一致
accessToken: default_token
admin:
# 调度中心部署根地址 [选填]:如调度中心集群部署存在多个地址则用逗号分隔。执行器将会使用该地址进行"执行器心跳注册"和"任务结果回调";为空则关闭自动注册;
addresses: http://127.0.0.1:8080/xxl-job-admin
executor:
# 执行器注册 [选填]:优先使用该配置作为注册地址,为空时使用内嵌服务 ”IP:PORT“ 作为注册地址。从而更灵活的支持容器类型执行器动态IP和动态映射端口问题。
address:
# 执行器AppName [选填]:执行器心跳注册分组依据;为空则关闭自动注册
appname: task
# 执行器IP [选填]:默认为空表示自动获取IP,多网卡时可手动设置指定IP,该IP不会绑定Host仅作为通讯实用;地址信息用于 "执行器注册" 和 "调度中心请求并触发任务";
ip:
# 执行器运行日志文件存储磁盘路径 [选填] :需要对该路径拥有读写权限;为空则使用默认路径;
logpath: C:/Users/19030/Desktop/tmp/xxl-job
# 执行器日志文件保存天数 [选填] : 过期日志自动清理, 限制值大于等于3时生效; 否则, 如-1, 关闭自动清理功能;
logretentiondays: 30
# 执行器端口号 [选填]:小于等于0则自动获取;默认端口为9999,单机部署多个执行器时,注意要配置不同执行器端口;
port: 8091

配置类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
* xxl-job config
*/
@Configuration
public class XxlJobConfig {
private Logger logger = LoggerFactory.getLogger(XxlJobConfig.class);

@Value("${xxl.job.admin.addresses}")
private String adminAddresses;

@Value("${xxl.job.accessToken}")
private String accessToken;

@Value("${xxl.job.executor.appname}")
private String appname;

@Value("${xxl.job.executor.address}")
private String address;

@Value("${xxl.job.executor.ip}")
private String ip;

@Value("${xxl.job.executor.port}")
private int port;

@Value("${xxl.job.executor.logpath}")
private String logPath;

@Value("${xxl.job.executor.logretentiondays}")
private int logRetentionDays;

@Bean
public XxlJobSpringExecutor xxlJobExecutor() {
logger.info(">>>>>>>>>>> xxl-job config init.");
XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
xxlJobSpringExecutor.setAdminAddresses(adminAddresses);
xxlJobSpringExecutor.setAppname(appname);
xxlJobSpringExecutor.setAddress(address);
xxlJobSpringExecutor.setIp(ip);
xxlJobSpringExecutor.setPort(port);
xxlJobSpringExecutor.setAccessToken(accessToken);
xxlJobSpringExecutor.setLogPath(logPath);
xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);

return xxlJobSpringExecutor;
}

}

创建测试任务

1
2
3
4
5
6
7
8
9
10
11
12
13
@Component
public class ScheduledTest {

/**
* 1、简单任务示例(Bean模式)
*/
@XxlJob(value = "demoJobHandler")
public void demoJobHandler() {
//声明需要格式化的格式(日期加时间)
DateTimeFormatter dfDateTime = DateTimeFormatter.ofPattern("yyyy-MM-dd HH mm ss");
System.out.println(dfDateTime.format(LocalDateTime.now()));
}
}

SpringBoot启动多个任务

image-20230309163705547

image-20230309163805792

执行器管理

image-20230309164158220

image-20230309164305994

任务管理

image-20230309164707489

image-20230309164723720

调度日志查看

image-20230309164801002

image-20230309164835295

image-20230309164843007

系统日志查看

image-20230309164922917