首页 > 其他分享 >XXJ-JOB任务调度-快速入门-集成项目-动态创建任务

XXJ-JOB任务调度-快速入门-集成项目-动态创建任务

时间:2024-10-13 13:19:50浏览次数:10  
标签:执行器 spring xxlJobInfo job 动态创建 JOB 任务 任务调度 xxl

XXJ-JOB任务调度

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

概述

XXL-JOB是一个分布式任务调度平台,其核心设计目标是开发迅速、学习简单、轻量级、易扩展。现已开放源代码并接入多家公司线上产品线,开箱即用。

文档地址

一、快速入门

依赖

<dependency>
    <groupId>com.xuxueli</groupId>
    <artifactId>xxl-job-core</artifactId>
    <version>${最新稳定版本}</version>
</dependency>

1 导入项目到idea

![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=assets%5C1690169616781.png&pos_id=img-s6gh5jCO-1728796431068
项目结构说明:
在这里插入图片描述

xxl-job-master:
xxl-job-admin:调度中心
xxl-job-core:公共依赖
xxl-job-executor-samples:执行器Sample示例(选择合适的版本执行器,可直接使用,也可以参考其并将现有项目改造成执行器)
xxl-job-executor-sample-springboot:Springboot版本,通过Springboot管理执行器,推荐这种方式;
xxl-job-executor-sample-frameless:无框架版本;

2 初始化数据库

获取 “调度数据库初始化SQL脚本” 并执行即可。

调度数据库初始化SQL脚本” 位置为:/xxl-job-master/doc/db/tables_xxl_job.sql

在这里插入图片描述

3 部署调度中心:xxl-job-admin

3.1 修改数据库连接

打开xxl-job-admin的application.propertiest。路径:xxl-job-admin\src\main\resources\application.properties

修改数据库连接信息:

spring.datasource.url=jdbc:mysql://localhost:3306/xxl_job?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai
### 记得改数据库ip地址
spring.datasource.username=root 
### 数据库密码改成你自己的
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

完整的application.properties配置信息:

### web
# 指定服务运行的端口号,默认为8080
server.port=8080
# 设置web应用的访问路径前缀
server.servlet.context-path=/xxl-job-admin

### actuator
# 设置actuator端点的基础路径
management.server.base-path=/actuator
# 禁用邮件健康检查功能,因为可能需要额外的配置才能使用
management.health.mail.enabled=false

### resources
# 设置Spring MVC Servlet的启动加载顺序,值为0表示随容器启动而加载
spring.mvc.servlet.load-on-startup=0
# 配置静态资源的访问路径,例如图片、CSS等
spring.mvc.static-path-pattern=/static/**
# 静态资源的位置,这里指定了在类路径下的/static目录中查找
spring.web.resources.static-locations=classpath:/static/

### freemarker
# Freemarker模板文件的加载路径,这里设置为类路径下的/templates目录
spring.freemarker.templateLoaderPath=classpath:/templates/
# 设置模板文件的后缀名
spring.freemarker.suffix=.ftl
# 设置模板文件的字符集
spring.freemarker.charset=UTF-8
# 将请求对象作为属性传递给模板
spring.freemarker.request-context-attribute=request
# 设置数字格式化方式
spring.freemarker.settings.number_format=0.##########

### mybatis
# MyBatis映射文件的位置,这里指定了类路径下的/mybatis-mapper目录中的所有Mapper.xml文件
mybatis.mapper-locations=classpath:/mybatis-mapper/*Mapper.xml
# # 如果需要指定实体类的位置,可以取消注释并设置相应的包名
# mybatis.type-aliases-package=com.xxl.job.admin.core.model

### xxl-job, datasource
# 数据库连接的URL,这里配置了MySQL数据库,指定了数据库名为xxl_job,并设置了相关参数以支持中文及自动重连
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/xxl_job?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai
# 数据库用户名
spring.datasource.username=root
# 数据库密码
spring.datasource.password=1234
# 指定数据库驱动类名
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

### datasource-pool
# 指定数据源类型为HikariCP,这是一个高性能的数据库连接池
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
# 设置HikariCP最小空闲连接数
spring.datasource.hikari.minimum-idle=10
# 设置HikariCP最大连接池大小
spring.datasource.hikari.maximum-pool-size=30
# 设置是否自动提交SQL语句
spring.datasource.hikari.auto-commit=true
# 设置连接空闲超时时间(毫秒)
spring.datasource.hikari.idle-timeout=30000
# 设置连接池名称
spring.datasource.hikari.pool-name=HikariCP
# 设置连接的最大生命周期(毫秒)
spring.datasource.hikari.max-lifetime=900000
# 设置获取连接的超时时间(毫秒)
spring.datasource.hikari.connection-timeout=10000
# 设置连接测试查询语句
spring.datasource.hikari.connection-test-query=SELECT 1
# 设置验证超时时间(毫秒)
spring.datasource.hikari.validation-timeout=1000

### xxl-job, email
# 邮件服务器地址,这里配置的是QQ邮箱的SMTP服务器
spring.mail.host=smtp.qq.com
# SMTP服务器端口
spring.mail.port=25
# 发送邮件的用户名
[email protected]
# 发送邮件的默认发件人地址
[email protected]
# 发送邮件的密码或授权码
spring.mail.password=xxx
# 设置是否需要认证
spring.mail.properties.mail.smtp.auth=true
# 启用STARTTLS安全连接
spring.mail.properties.mail.smtp.starttls.enable=true
# 强制要求使用STARTTLS
spring.mail.properties.mail.smtp.starttls.required=true
# 设置用于创建安全套接字工厂的类
spring.mail.properties.mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory

### xxl-job, access token
# 设置XXL-JOB的访问令牌,用于保护API接口
xxl.job.accessToken=default_token

### xxl-job, i18n (国际化)
# 设置XXL-JOB的界面语言,默认为简体中文,可选值还有"zh_TC"(繁体中文)和"en"(英文)
xxl.job.i18n=zh_CN

## xxl-job, triggerpool max size
# 设置快速任务触发池的最大线程数
xxl.job.triggerpool.fast.max=200
# 设置慢速任务触发池的最大线程数
xxl.job.triggerpool.slow.max=100

### xxl-job, log retention days
# 设置日志保留天数,超过该天数的日志将被自动清理
xxl.job.logretentiondays=30
3.2 启动项目

调度中心访问地址:http://localhost:8080/xxl-job-admin

默认登录账号 “admin/123456”, 登录后运行界面如下图所示:

在这里插入图片描述

3.3 调度中心集群部署(可选)

调度中心支持集群部署,提升调度系统容灾和可用性。

调度中心集群部署时,几点要求和建议:

  • DB配置保持一致;
  • 集群机器时钟保持一致(单机集群忽视);
  • 建议:推荐通过nginx为调度中心集群做负载均衡,分配域名。调度中心访问、执行器回调配置、调用API服务等操作均通过该域名进行。

4 配置执行器

“执行器”项目:xxl-job-executor-sample-springboot (提供多种版本执行器供选择,现以 springboot 版本为例,可直接使用,也可以参考其并将现有项目改造成执行器)
作用:负责接收“调度中心”的调度并执行;可直接部署执行器,也可以将执行器集成到现有业务项目中。

4.1 maven依赖

确认pom文件中引入了 “xxl-job-core” 的maven依赖;

<!-- xxl-job-core -->
<dependency>
    <groupId>com.xuxueli</groupId>
    <artifactId>xxl-job-core</artifactId>
    <version>2.4.1-SNAPSHOT</version>
</dependency>
4.2 执行器配置

执行器配置,配置内容说明:

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

执行器组件,配置内容说明:

package com.xxl.job.executor.core.config;

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配置类,用于初始化XXL-JOB执行器的相关配置。
 *
 * @author xuxueli 2017-04-28
 */
@Configuration
public class XxlJobConfig {

    // 日志记录器,用于记录配置初始化过程中的日志信息
    private Logger logger = LoggerFactory.getLogger(XxlJobConfig.class);

    // 从application.properties中读取XXL-JOB管理端的地址
    @Value("${xxl.job.admin.addresses}")
    private String adminAddresses;

    // 从application.properties中读取XXL-JOB的访问令牌,用于保护API接口
    @Value("${xxl.job.accessToken}")
    private String accessToken;

    // 从application.properties中读取执行器的应用名称
    @Value("${xxl.job.executor.appname}")
    private String appname;

    // 从application.properties中读取执行器的地址
    @Value("${xxl.job.executor.address}")
    private String address;

    // 从application.properties中读取执行器的IP地址
    @Value("${xxl.job.executor.ip}")
    private String ip;

    // 从application.properties中读取执行器的端口号
    @Value("${xxl.job.executor.port}")
    private int port;

    // 从application.properties中读取执行器日志的存储路径
    @Value("${xxl.job.executor.logpath}")
    private String logPath;

    // 从application.properties中读取执行器日志的保留天数
    @Value("${xxl.job.executor.logretentiondays}")
    private int logRetentionDays;

    /**
     * 创建并初始化XXL-JOB执行器的Bean。
     *
     * @return 初始化后的XXL-JOB执行器实例
     */
    @Bean
    public XxlJobSpringExecutor xxlJobExecutor() {
        logger.info(">>>>>>>>>>> xxl-job config init.");
        
        // 创建XXL-JOB执行器实例
        XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
        
        // 设置管理端地址
        xxlJobSpringExecutor.setAdminAddresses(adminAddresses);
        
        // 设置应用名称
        xxlJobSpringExecutor.setAppname(appname);
        
        // 设置执行器地址
        xxlJobSpringExecutor.setAddress(address);
        
        // 设置执行器IP地址
        xxlJobSpringExecutor.setIp(ip);
        
        // 设置执行器端口号
        xxlJobSpringExecutor.setPort(port);
        
        // 设置访问令牌
        xxlJobSpringExecutor.setAccessToken(accessToken);
        
        // 设置日志存储路径
        xxlJobSpringExecutor.setLogPath(logPath);
        
        // 设置日志保留天数
        xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);

        return xxlJobSpringExecutor;
    }

    /**
     * 针对多网卡、容器内部署等情况,可借助 "spring-cloud-commons" 提供的 "InetUtils" 组件灵活定制注册IP。
     *
     * 1. 引入依赖:
     *      <dependency>
     *          <groupId>org.springframework.cloud</groupId>
     *          <artifactId>spring-cloud-commons</artifactId>
     *          <version>${version}</version>
     *      </dependency>
     *
     * 2. 配置文件,或者容器启动变量:
     *      spring.cloud.inetutils.preferred-networks: 'xxx.xxx.xxx.'
     *
     * 3. 获取IP地址:
     *      String ip_ = inetUtils.findFirstNonLoopbackHostInfo().getIpAddress();
     */
}

详细说明

  1. 日志记录器:
    • private Logger logger = LoggerFactory.getLogger(XxlJobConfig.class);
    • 用于记录配置初始化过程中的日志信息,方便调试和问题排查。
  2. 配置项注入:
    • 使用 @Value 注解从 application.properties 文件中读取配置项。
    • 例如:@Value("${xxl.job.admin.addresses}") 会从配置文件中读取 xxl.job.admin.addresses 的值,并赋值给 adminAddresses 变量。
  3. Bean 创建方法:
    • @Bean 注解的方法用于创建并初始化一个 XxlJobSpringExecutor 实例。
    • 在方法中,通过调用 XxlJobSpringExecutor 的各个 set 方法,设置其属性值。
    • 最后返回初始化好的 XxlJobSpringExecutor 实例。
  4. 多网卡和容器内部署:
    • 对于多网卡或容器内部署的情况,可以通过 spring-cloud-commons 提供的 InetUtils 组件来灵活获取注册IP。
    • 需要引入 spring-cloud-commons 依赖,并在配置文件中指定优先网络段。
    • 最后通过 InetUtils 获取实际的IP地址。
4.4 启动xxl-job-executor-sample-springboot

在这里插入图片描述

5 开始第一个任务调度

5.1 配置执行器

在这里插入图片描述

上面我们启动了xxl-job-executor-sample-springboot 执行器项目,当前已注册上来,我们执行使用改执行器。

如果没有注册可以自己手动注册

AppName填的是执行的的application.properties里面的xxl.job.executor.appname
在这里插入图片描述

执行器属性说明:

​ AppName: 是每个执行器集群的唯一标示AppName, 执行器会周期性以AppName为对象进行自动注册。可通过该配置自动发现注册成功的执行器, 供任务调度时使用;
名称: 执行器的名称, 因为AppName限制字母数字等组成,可读性不强, 名称为了提高执行器的可读性;排序: 执行器的排序, 系统中需要执行器的地方,如任务新增, 将会按照该排序读取可用的执行器列表;
注册方式:调度中心获取执行器地址的方式;
​ 自动注册:执行器自动进行执行器注册,调度中心通过底层注册表可以动态发现执行器机器地址;
​ 手动录入:人工手动录入执行器的地址信息,多地址逗号分隔,供调度中心使用;
机器地址:"注册方式"为"手动录入"时有效,支持人工维护执行器的地址信息;

5.2 第一个调度任务

登录调度中心:http://localhost:8080/xxl-job-admin

默认登录账号 “admin/123456”

在xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/java/com/xxl/job/executor/service/jobhandler/SampleXxlJob.java
在这里插入图片描述

有该方法

@Component
public class SampleXxlJob {
    private static Logger logger = LoggerFactory.getLogger(SampleXxlJob.class);


    /**
     * 1、简单任务示例(Bean模式)
     */
    @XxlJob("demoJobHandler")
    public void demoJobHandler() throws Exception {
        for (int i = 0; i < 10; i++) {
            System.out.println("Hello XXL-JOB");
        }

    }
}

任务管理 --> 新增
在这里插入图片描述

然后点击执行一次
在这里插入图片描述

回到idea控制台
在这里插入图片描述

成功打印十次Hello XXL-JOB。

二、集成XXL-JOB

我们使用单独的一个微服务模块service-dispatch集成XXL-JOB执行器

1 引入maven依赖

<!-- xxl-job-core -->
<dependency>
    <groupId>com.xuxueli</groupId>
    <artifactId>xxl-job-core</artifactId>
    <version>2.4.1-SNAPSHOT</version>
</dependency>

2 执行器配置

在项目的配置文件application加入下面配置

xxl:
  job:
    admin:
      # 调度中心部署跟地址 [选填]:如调度中心集群部署存在多个地址则用逗号分隔。执行器将会使用该地址进行"执行器心跳注册"和"任务结果回调";为空则关闭自动注册
      addresses: http://localhost:8080/xxl-job-admin
      # 执行器通讯TOKEN [选填]:非空时启用
    accessToken: 

    executor:
      # 执行器AppName [选填]:执行器心跳注册分组依据;为空则关闭自动注册
      appname: xxl-job-executor-sample
      # 执行器注册 [选填]:优先使用该配置作为注册地址,为空时使用内嵌服务 ”IP:PORT“ 作为注册地址。从而更灵活的支持容器类型执行器动态IP和动态映射端口问题。
      address:
      # 执行器IP [选填]:默认为空表示自动获取IP,多网卡时可手动设置指定IP,该IP不会绑定Host仅作为通讯实用;地址信息用于 "执行器注册" 和 "调度中心请求并触发任务";
      ip:
      # 执行器端口号 [选填]:小于等于0则自动获取;默认端口为9999,单机部署多个执行器时,注意要配置不同执行器端口;
      port: 9999
      # 执行器运行日志文件存储磁盘路径 [选填] :需要对该路径拥有读写权限;为空则使用默认路径;
      logpath: /data/applogs/xxl-job/jobhandler
      # 执行器日志文件保存天数 [选填] : 过期日志自动清理, 限制值大于等于3时生效; 否则, 如-1, 关闭自动清理功能;
      logretentiondays: 30

3 执行器组件配置

将xxl-job-executor-sample-springboot 执行器项目的XxlJobConfig类复制过来

package com.atguigu.daijia.dispatch.xxl.config;

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;

@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;
    }

    /**
     * 针对多网卡、容器内部署等情况,可借助 "spring-cloud-commons" 提供的 "InetUtils" 组件灵活定制注册IP;
     *
     *      1、引入依赖:
     *          <dependency>
     *             <groupId>org.springframework.cloud</groupId>
     *             <artifactId>spring-cloud-commons</artifactId>
     *             <version>${version}</version>
     *         </dependency>
     *
     *      2、配置文件,或者容器启动变量
     *          spring.cloud.inetutils.preferred-networks: 'xxx.xxx.xxx.'
     *
     *      3、获取IP
     *          String ip_ = inetUtils.findFirstNonLoopbackHostInfo().getIpAddress();
     */


}

我们已经将XXL-JOB集成到项目中了

4 测试任务

编写测试任务job方法

@Component
public class DispatchJobHandler {

    @XxlJob("firstJobHandler")
    public void firstJobHandler() {
        log.info("xxl-job项目集成测试");
    }
}

在调度中心配置任务

在这里插入图片描述

记得启动 xxl-job-admin 哦!

启动任务就可以了

三 动态创建XXL-JOB任务

有些业务需要开启任务调度,指定只能动态创建XXL-JOB任务,因此我们要封装XXL-JOB客户端,通过接口的形式添加并启动任务。

1 改造XXL-JOB服务器端接口

在xxl-job-admin模块,添加改造后的api接口

在JobInfoController类末尾添加方法,如下:

// 定义一个用于添加新任务的方法
@RequestMapping("/addJob")
@ResponseBody
@PermissionLimit(limit = false) // 表示此方法不需要权限限制
public ReturnT<String> addJobInfo(@RequestBody XxlJobInfo jobInfo) {
    // 调用服务层的方法来添加新的任务信息,并返回操作结果
    return xxlJobService.add(jobInfo);
}

// 定义一个用于更新现有任务的方法
@RequestMapping("/updateJob")
@ResponseBody
@PermissionLimit(limit = false) // 表示此方法不需要权限限制
public ReturnT<String> updateJob(@RequestBody XxlJobInfo jobInfo) {
    // 调用服务层的方法来更新任务信息,并返回操作结果
    return xxlJobService.update(jobInfo);
}

// 定义一个用于删除任务的方法
@RequestMapping("/removeJob")
@ResponseBody
@PermissionLimit(limit = false) // 表示此方法不需要权限限制
public ReturnT<String> removeJob(@RequestBody XxlJobInfo jobInfo) {
    // 调用服务层的方法来移除指定ID的任务,并返回操作结果
    return xxlJobService.remove(jobInfo.getId());
}

// 定义一个用于暂停任务的方法
@RequestMapping("/stopJob")
@ResponseBody
@PermissionLimit(limit = false) // 表示此方法不需要权限限制
public ReturnT<String> pauseJob(@RequestBody XxlJobInfo jobInfo) {
    // 调用服务层的方法来停止指定ID的任务,并返回操作结果
    return xxlJobService.stop(jobInfo.getId());
}

// 定义一个用于启动任务的方法
@RequestMapping("/startJob")
@ResponseBody
@PermissionLimit(limit = false) // 表示此方法不需要权限限制
public ReturnT<String> startJob(@RequestBody XxlJobInfo jobInfo) {
    // 调用服务层的方法来启动指定ID的任务,并返回操作结果
    return xxlJobService.start(jobInfo.getId());
}

// 定义一个用于添加并立即启动任务的方法
@RequestMapping("/addAndStartJob")
@ResponseBody
@PermissionLimit(limit = false) // 表示此方法不需要权限限制
public ReturnT<String> addAndStartJob(@RequestBody XxlJobInfo jobInfo) {
    // 先调用服务层的方法来添加新的任务
    ReturnT<String> result = xxlJobService.add(jobInfo);
    // 获取新增任务的ID(从返回的结果中解析)
    int id = Integer.valueOf(result.getContent());
    // 启动刚刚添加的任务
    xxlJobService.start(id);
    // 立即执行一次该任务
    JobTriggerPoolHelper.trigger(id, TriggerTypeEnum.MANUAL, -1, null, jobInfo.getExecutorParam(), "");
    // 返回添加任务的操作结果
    return result;
}

说明:排除登录校验(@PermissionLimit(limit = false))

2 配置接口地址

在自己的项目的配置文件中添加

xxl:
  job:
    admin:
      # 调度中心部署地址 [选填]:如果调度中心是集群部署,则使用逗号分隔多个地址。执行器将使用这些地址进行“执行器心跳注册”和“任务结果回调”。如果留空,则关闭自动注册。
      addresses: http://139.198.30.131:8080/xxl-job-admin
      # addresses: http://localhost:8080/xxl-job-admin
      # 执行器与调度中心通信的TOKEN [选填]:如果设置,将启用安全验证。
      accessToken: 

    executor:
      # 执行器的应用名称 [选填]:执行器心跳注册时使用的分组标识。如果留空,则关闭自动注册。
      appname: xxl-job-executor-sample
      # 执行器注册地址 [选填]:优先级高于自动获取的“IP:PORT”,适合于容器化环境中执行器的动态IP和端口映射场景。
      address:
      # 执行器IP [选填]:默认为空,表示自动获取IP。在多网卡环境下,可以手动指定IP。该IP仅用于执行器之间的通信。
      ip:
      # 执行器端口号 [选填]:小于等于0则自动获取,默认为9999。如果在同一台机器上部署了多个执行器,确保每个执行器的端口不同。
      port: 9999
      # 执行器运行日志的文件存储路径 [选填]:需要对这个路径有读写权限。留空则使用默认路径。
      logpath: /data/applogs/xxl-job/jobhandler
      # 执行器日志文件保留天数 [选填]:当值大于等于3时,过期的日志文件会被自动清理;否则,如-1,关闭自动清理功能。
      logretentiondays: 30

    client:
      # 任务组ID [选填]:通常情况下不需要更改。
      jobGroupId: 1
      
      #下面的路径要对应上面自定义方法的 @RequestMapping("/.........")
      
      # 添加任务的URL [选填]:使用调度中心的地址拼接而成,用于向调度中心发送添加任务的请求。
      addUrl: ${xxl.job.admin.addresses}/jobinfo/addJob
      # 移除任务的URL [选填]:使用调度中心的地址拼接而成,用于向调度中心发送移除任务的请求。
      removeUrl: ${xxl.job.admin.addresses}/jobinfo/removeJob
      # 启动任务的URL [选填]:使用调度中心的地址拼接而成,用于向调度中心发送启动任务的请求。
      startJobUrl: ${xxl.job.admin.addresses}/jobinfo/startJob
      # 停止任务的URL [选填]:使用调度中心的地址拼接而成,用于向调度中心发送停止任务的请求。
      stopJobUrl: ${xxl.job.admin.addresses}/jobinfo/stopJob
      # 添加并立即启动任务的URL [选填]:使用调度中心的地址拼接而成,用于向调度中心发送添加任务并立即启动的请求。
      addAndStartUrl: ${xxl.job.admin.addresses}/jobinfo/addAndStartJob

3 配置XxlJobClientConfig

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Data
@Component
@ConfigurationProperties(prefix = "xxl.job.client")
public class XxlJobClientConfig {

    private Integer jobGroupId;
    private String addUrl;
    private String removeUrl;
    private String startJobUrl;
    private String stopJobUrl;
    private String addAndStartUrl;
}

4 配置XxlJobClient


/**
 * XXL-JOB 客户端类,用于与调度中心进行交互
 * 参考文档: https://dandelioncloud.cn/article/details/1598865461087518722
 */
@Slf4j
@Component
public class XxlJobClient {

    @Autowired
    private XxlJobClientConfig xxlJobClientConfig; // 注入 XXL-JOB 客户端配置

    @Autowired
    private RestTemplate restTemplate; // 注入 HTTP 请求模板

    /**
     * 添加一个新的任务
     *
     * @param executorHandler 任务处理器
     * @param param 任务参数
     * @param corn 定时表达式
     * @param desc 任务描述
     * @return 新增任务的 ID
     */
    @SneakyThrows
    public Long addJob(String executorHandler, String param, String corn, String desc) {
        XxlJobInfo xxlJobInfo = new XxlJobInfo(); // 创建任务信息对象
        xxlJobInfo.setJobGroup(xxlJobClientConfig.getJobGroupId()); // 设置任务组 ID
        xxlJobInfo.setJobDesc(desc); // 设置任务描述
        xxlJobInfo.setAuthor("qy"); // 设置任务创建者
        xxlJobInfo.setScheduleType("CRON"); // 设置调度类型为 CRON
        xxlJobInfo.setScheduleConf(corn); // 设置定时表达式
        xxlJobInfo.setGlueType("BEAN"); // 设置任务类型为 BEAN
        xxlJobInfo.setExecutorHandler(executorHandler); // 设置任务处理器
        xxlJobInfo.setExecutorParam(param); // 设置任务参数
        xxlJobInfo.setExecutorRouteStrategy("FIRST"); // 设置路由策略为 FIRST
        xxlJobInfo.setExecutorBlockStrategy("SERIAL_EXECUTION"); // 设置阻塞策略为 SERIAL_EXECUTION
        xxlJobInfo.setMisfireStrategy("FIRE_ONCE_NOW"); // 设置错过策略为 FIRE_ONCE_NOW
        xxlJobInfo.setExecutorTimeout(0); // 设置超时时间为 0(永不超时)
        xxlJobInfo.setExecutorFailRetryCount(0); // 设置失败重试次数为 0

        HttpHeaders headers = new HttpHeaders(); // 创建 HTTP 头
        headers.setContentType(MediaType.APPLICATION_JSON); // 设置内容类型为 JSON
        HttpEntity<XxlJobInfo> request = new HttpEntity<>(xxlJobInfo, headers); // 创建 HTTP 请求实体

        String url = xxlJobClientConfig.getAddUrl(); // 获取添加任务的 URL
        ResponseEntity<JSONObject> response = restTemplate.postForEntity(url, request, JSONObject.class); // 发送 POST 请求
        if (response.getStatusCode().value() == 200 && response.getBody().getIntValue("code") == 200) {
            log.info("增加xxl执行任务成功,返回信息:{}", response.getBody().toJSONString()); // 记录成功日志
            // content 为任务 ID
            return response.getBody().getLong("content");
        }
        log.info("调用xxl增加执行任务失败:{}", response.getBody().toJSONString()); // 记录失败日志
        throw new MyException(ResultCodeEnum.XXL_JOB_ERROR); // 抛出异常
    }

    /**
     * 启动一个已存在的任务
     *
     * @param jobId 任务 ID
     * @return 操作是否成功
     */
    public Boolean startJob(Long jobId) {
        XxlJobInfo xxlJobInfo = new XxlJobInfo(); // 创建任务信息对象
        xxlJobInfo.setId(jobId.intValue()); // 设置任务 ID

        HttpHeaders headers = new HttpHeaders(); // 创建 HTTP 头
        headers.setContentType(MediaType.APPLICATION_JSON); // 设置内容类型为 JSON
        HttpEntity<XxlJobInfo> request = new HttpEntity<>(xxlJobInfo, headers); // 创建 HTTP 请求实体

        String url = xxlJobClientConfig.getStartJobUrl(); // 获取启动任务的 URL
        ResponseEntity<JSONObject> response = restTemplate.postForEntity(url, request, JSONObject.class); // 发送 POST 请求
        if (response.getStatusCode().value() == 200 && response.getBody().getIntValue("code") == 200) {
            log.info("启动xxl执行任务成功:{},返回信息:{}", jobId, response.getBody().toJSONString()); // 记录成功日志
            return true;
        }
        log.info("启动xxl执行任务失败:{},返回信息:{}", jobId, response.getBody().toJSONString()); // 记录失败日志
        throw new MyException(ResultCodeEnum.XXL_JOB_ERROR); // 抛出异常
    }

    /**
     * 停止一个已存在的任务
     *
     * @param jobId 任务 ID
     * @return 操作是否成功
     */
    public Boolean stopJob(Long jobId) {
        XxlJobInfo xxlJobInfo = new XxlJobInfo(); // 创建任务信息对象
        xxlJobInfo.setId(jobId.intValue()); // 设置任务 ID

        HttpHeaders headers = new HttpHeaders(); // 创建 HTTP 头
        headers.setContentType(MediaType.APPLICATION_JSON); // 设置内容类型为 JSON
        HttpEntity<XxlJobInfo> request = new HttpEntity<>(xxlJobInfo, headers); // 创建 HTTP 请求实体

        String url = xxlJobClientConfig.getStopJobUrl(); // 获取停止任务的 URL
        ResponseEntity<JSONObject> response = restTemplate.postForEntity(url, request, JSONObject.class); // 发送 POST 请求
        if (response.getStatusCode().value() == 200 && response.getBody().getIntValue("code") == 200) {
            log.info("停止xxl执行任务成功:{},返回信息:{}", jobId, response.getBody().toJSONString()); // 记录成功日志
            return true;
        }
        log.info("停止xxl执行任务失败:{},返回信息:{}", jobId, response.getBody().toJSONString()); // 记录失败日志
        throw new MyException(ResultCodeEnum.XXL_JOB_ERROR); // 抛出异常
    }

    /**
     * 删除一个已存在的任务
     *
     * @param jobId 任务 ID
     * @return 操作是否成功
     */
    public Boolean removeJob(Long jobId) {
        XxlJobInfo xxlJobInfo = new XxlJobInfo(); // 创建任务信息对象
        xxlJobInfo.setId(jobId.intValue()); // 设置任务 ID

        HttpHeaders headers = new HttpHeaders(); // 创建 HTTP 头
        headers.setContentType(MediaType.APPLICATION_JSON); // 设置内容类型为 JSON
        HttpEntity<XxlJobInfo> request = new HttpEntity<>(xxlJobInfo, headers); // 创建 HTTP 请求实体

        String url = xxlJobClientConfig.getRemoveUrl(); // 获取删除任务的 URL
        ResponseEntity<JSONObject> response = restTemplate.postForEntity(url, request, JSONObject.class); // 发送 POST 请求
        if (response.getStatusCode().value() == 200 && response.getBody().getIntValue("code") == 200) {
            log.info("删除xxl执行任务成功:{},返回信息:{}", jobId, response.getBody().toJSONString()); // 记录成功日志
            return true;
        }
        log.info("删除xxl执行任务失败:{},返回信息:{}", jobId, response.getBody().toJSONString()); // 记录失败日志
        throw new MyException(ResultCodeEnum.XXL_JOB_ERROR); // 抛出异常
    }

    /**
     * 添加并立即启动一个新的任务
     *
     * @param executorHandler 任务处理器
     * @param param 任务参数
     * @param corn 定时表达式
     * @param desc 任务描述
     * @return 新增任务的 ID
     */
    public Long addAndStart(String executorHandler, String param, String corn, String desc) {
        XxlJobInfo xxlJobInfo = new XxlJobInfo(); // 创建任务信息对象
        xxlJobInfo.setJobGroup(xxlJobClientConfig.getJobGroupId()); // 设置任务组 ID
        xxlJobInfo.setJobDesc(desc); // 设置任务描述
        xxlJobInfo.setAuthor("qy"); // 设置任务创建者
        xxlJobInfo.setScheduleType("CRON"); // 设置调度类型为 CRON
        xxlJobInfo.setScheduleConf(corn); // 设置定时表达式
        xxlJobInfo.setGlueType("BEAN"); // 设置任务类型为 BEAN
        xxlJobInfo.setExecutorHandler(executorHandler); // 设置任务处理器
        xxlJobInfo.setExecutorParam(param); // 设置任务参数
        xxlJobInfo.setExecutorRouteStrategy("FIRST"); // 设置路由策略为 FIRST
        xxlJobInfo.setExecutorBlockStrategy("SERIAL_EXECUTION"); // 设置阻塞策略为 SERIAL_EXECUTION
        xxlJobInfo.setMisfireStrategy("FIRE_ONCE_NOW"); // 设置错过策略为 FIRE_ONCE_NOW
        xxlJobInfo.setExecutorTimeout(0); // 设置超时时间为 0(永不超时)
        xxlJobInfo.setExecutorFailRetryCount(0); // 设置失败重试次数为 0

        HttpHeaders headers = new HttpHeaders(); // 创建 HTTP 头
        headers.setContentType(MediaType.APPLICATION_JSON); // 设置内容类型为 JSON
        HttpEntity<XxlJobInfo> request = new HttpEntity<>(xxlJobInfo, headers); // 创建 HTTP 请求实体

        String url = xxlJobClientConfig.getAddAndStartUrl(); // 获取添加并启动任务的 URL
        ResponseEntity<JSONObject> response = restTemplate.postForEntity(url, request, JSONObject.class); // 发送 POST 请求
        if (response.getStatusCode().value() == 200 && response.getBody().getIntValue("code") == 200) {
            log.info("增加并开始执行xxl任务成功,返回信息:{}", response.getBody().toJSONString()); // 记录成功日志
            // content 为任务 ID
            return response.getBody().getLong("content");
        }
        log.info("增加并开始执行xxl任务失败:{}", response.getBody().toJSONString()); // 记录失败日志
        throw new MyException(ResultCodeEnum.XXL_JOB_ERROR); // 抛出异常
    }
}

5 启动类配置RestTemplate

@Bean
public RestTemplate restTemplate() {
    return new RestTemplate();
}

6 添加并启动任务接口

微服务接口

NewTaskController

@Autowired
private NewTaskService newTaskService;

@Operation(summary = "添加并开始新订单任务调度")
@PostMapping("/addAndStartTask")
public Result<Long> addAndStartTask(@RequestBody NewTaskVo newTaskVo) {
   return Result.ok(newTaskService.addAndStartTask(newTaskVo));
}

NewTaskService

void addAndStartTask(NewTaskVo newTaskVo);

NewTaskServiceImpl

public class OrderTaskService extends ServiceImpl<OrderJobMapper, OrderJob> {

    @Autowired
    private XxlJobClient xxlJobClient; // 注入 XXL-JOB 客户端

    @Autowired
    private OrderJobMapper orderJobMapper; // 注入订单任务映射器

    /**
     * 添加并启动一个新任务
     *
     * @param NewTaskVo 新订单任务的视图对象
     * @return 任务 ID
     */
    @Transactional(rollbackFor = Exception.class) // 开启事务管理,遇到异常时回滚事务
    @Override
    public void addAndStartTask(NewTaskVo NewTaskVo) {
            // 添加并启动一个新的任务
            Long jobId = xxlJobClient.addAndStart(
                "newOrderTaskHandler", // 任务处理器
                "", // 任务参数
                "0 0/1 * * * ?", // 定时表达式,每分钟执行一次
                "新订单任务,订单id:" + NewTaskVo.getOrderId() // 任务描述
            );
    }
}

说明:每1分钟执行一次,处理任务的bean为:newOrderTaskHandler

7 开发任务Job方法

@Component
public class JobHandler {

    @XxlJob("newOrderTaskHandler")
    public void newOrderTaskHandler() {
         //执行业务
    }
}
```java 

vice extends ServiceImpl<OrderJobMapper, OrderJob> {

    @Autowired
    private XxlJobClient xxlJobClient; // 注入 XXL-JOB 客户端

    @Autowired
    private OrderJobMapper orderJobMapper; // 注入订单任务映射器

    /**
     * 添加并启动一个新任务
     *
     * @param NewTaskVo 新订单任务的视图对象
     * @return 任务 ID
     */
    @Transactional(rollbackFor = Exception.class) // 开启事务管理,遇到异常时回滚事务
    @Override
    public void addAndStartTask(NewTaskVo NewTaskVo) {
            // 添加并启动一个新的任务
            Long jobId = xxlJobClient.addAndStart(
                "newOrderTaskHandler", // 任务处理器
                "", // 任务参数
                "0 0/1 * * * ?", // 定时表达式,每分钟执行一次
                "新订单任务,订单id:" + NewTaskVo.getOrderId() // 任务描述
            );
    }
}

说明:每1分钟执行一次,处理任务的bean为:newOrderTaskHandler

7 开发任务Job方法

@Component
public class JobHandler {

    @XxlJob("newOrderTaskHandler")
    public void newOrderTaskHandler() {
         //执行业务
    }
}

完成!

标签:执行器,spring,xxlJobInfo,job,动态创建,JOB,任务,任务调度,xxl
From: https://blog.csdn.net/2301_81717523/article/details/142897188

相关文章

  • ESP32移植Openharmony设备开发---(3)任务调度
    任务调度官方文档:OpenAtomOpenHarmony基本概念从系统角度看,任务是竞争系统资源的最小运行单元。任务可以使用或等待CPU、使用内存空间等系统资源,各任务的运行相互独立。OpenHarmonyLiteOS-M的任务模块可以给用户提供多个任务,实现任务间的切换,帮助用户管理业务程序流程。......
  • 深入解析 DolphinScheduler 任务调度、拆分与执行全流程
    ApacheDolphinScheduler介绍ApacheDolphinScheduler是一个分布式易扩展的可视化DAG工作流任务调度开源系统。适用于企业级场景,提供了一个可视化操作任务、工作流和全生命周期数据处理过程的解决方案。Dag背景知识摘录了一下Dag的offical定义Agraphisformedbyvertices......
  • 总奖金高达10万元!华为算法精英实战营“亲和任务调度系统”来啦!
    随着物联网、大数据、AI时代的到来,时延、可靠性等指标要求越来越高,海量的数据分析、大量复杂的运算对CPU的算力要求越来越高。CPU内部的大部分资源用于缓存和逻辑控制,适合运行具有分支跳转、逻辑复杂、数据结构不规则、递归等特点的串行程序。在集成电路工艺制程将要达到极限,摩尔......
  • 关于结合faststream + python rq callback 进行job 状态标记的简单说明
    以前简单介绍过基于faststream+pythonrqcallback进行job状态标记,以下是结合源码说明下处理参考玩法代码实现faststream参考代码fromfaststream.redisimportRedisBroker fromfaststream.asgiimportAsgiFastStream,get,AsgiResponse fromty......
  • XXL-JOB 安装及使用教程
    前言XXL-JOB是一个可以在WEB界面配置执行定时任务的中间件,支持分布式服务调用。XXL-JOB本身是一个基于SpringBoot的JavaWEB程序,可以部署多个节点组成集群,我们可以通过下载GitHub源码进行部署。一、XXL-JOB安装教程进入XXL-JOB官网,下方的README.md文件讲述了XX......
  • xxl-job之框架讲解和使用
    目录1xxl-job1.1前言1.1.1xxl-job简介1.1.2任务调度1.1.3分布式任务调度平台1.2使用xxl-job1.2.1dokcer安装xxl-job1.2.1.1拉取镜像1.2.1.2创建配置文件1.2.1.3执行docker命令1.2.1.4登录查看1.2.2SpringBoot项目集成xxl-job1.2.2.1pom依赖与配置文件1.2.2.2......
  • D23 kubernetes 工作负载资源对象-Job与CronJob
    1、简介 Deployment和DaemonSet资源主要用于部署和管理守护进程型的应用程序,如nginx、mysql、java进程等。这类应用程序的特点是持续运行,通常在没有明确停止或下线的情况下一直保持运行状态。此外,kubernetes还提供了Job和CronJob资源,用于管理一次性任务和定时任务,如计算任务、数......
  • cloud run job yaml file
    在GoogleCloudRun中,CloudRunJobs允许你运行一次性任务。下面是一个简单的CloudRunJob的YAML文件示例,它可以帮助你定义一个Job。这个文件将定义一个Job运行时的镜像、任务个数和执行参数等。CloudRunJobYAML示例yaml复制代码apiVersion:run.googleapis.co......
  • Java后端开发中的任务调度:使用Spring Batch实现批处理
    Java后端开发中的任务调度:使用SpringBatch实现批处理大家好,我是微赚淘客返利系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!在现代企业应用中,批处理是处理大规模数据的重要方式。SpringBatch为我们提供了强大的工具来实现批处理任务。本文将详细介绍如何使用SpringBatch......
  • Web Development Job in 4
    简介网络开发领域持续快速发展,为拥有适当技能和知识的个人提供了令人兴奋的机会。如果您想进入这个充满活力的行业或提升自己的职业生涯,这里有一些重要策略可以帮助您在2024年找到梦想的工作:1.掌握基本技能编程语言:熟练掌握JavaScript、Python、Ruby或PHP等语言至关......