当前位置: 首页 > news >正文

SpringBoot教程(二十三) | SpringBoot实现分布式定时任务之xxl-job

SpringBoot教程(二十三) | SpringBoot实现分布式定时任务之xxl-job

  • 简介
  • 一、前置条件:需要搭建调度中心
    • 1、先下载调度中心源码
    • 2、修改配置文件
    • 3、启动项目
    • 4、进行访问
    • 5、打包部署(上正式)
  • 二、SpringBoot集成Xxl-Job
    • 1. 引入xxl-job的依赖
    • 2. 在application.yml加上xxljob的配置
    • 3. 添加配置类
    • 4. 添加xxl-job测试(由调度中心进行测试)
      • 1.先在自己的Springboot项目中创建测试类
      • 2. 再进入已经启动成功的调度中心页面中进行操作
    • 5. 动态API调度任务 (看个人需求)
      • 在 xxl-job-admin 项目中
        • 1. 新建 MyDynamicApiController
        • 2. 创建 XxlJobQuery
      • 在 自己的 SpringBoot 项目中
        • 加maven依赖
        • 1.创建 XxlJobInfo 类
        • 2.创建 XxlJobUtil 类
        • 3. 创建 XxlJobController 进行测试

参考文章
【1】SpringBoot集成XxlJob分布式任务调度中心(超详细之手把手教学)
【2】搭建部署xxl-job调度中心详细过程
【3】springboot整合xxl-job项目使用(含完整代码)
【4】Springboot 整合 xxljob 动态API调度任务(进阶篇)

简介

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

一、前置条件:需要搭建调度中心

调度中心控制台页面,对所有的定时任务进行统一配置管理(配置执行器,配置任务,管理任务)

1、先下载调度中心源码

下载调度中心源码

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

我这边使用的是gitee上的master分支
使用idea拉取代码后,在xxl-job\doc\db的位置下存在一个tables_xxl_job.sql(初始化数据库sql脚本),将它导入数据库(默认使用的是mysql)
在这里插入图片描述

#
# XXL-JOB v2.4.2-SNAPSHOT
# Copyright (c) 2015-present, xuxueli.CREATE database if NOT EXISTS `xxl_job` default character set utf8mb4 collate utf8mb4_unicode_ci;
use `xxl_job`;SET NAMES utf8mb4;CREATE TABLE `xxl_job_info` (`id` int(11) NOT NULL AUTO_INCREMENT,`job_group` int(11) NOT NULL COMMENT '执行器主键ID',`job_desc` varchar(255) NOT NULL,`add_time` datetime DEFAULT NULL,`update_time` datetime DEFAULT NULL,`author` varchar(64) DEFAULT NULL COMMENT '作者',`alarm_email` varchar(255) DEFAULT NULL COMMENT '报警邮件',`schedule_type` varchar(50) NOT NULL DEFAULT 'NONE' COMMENT '调度类型',`schedule_conf` varchar(128) DEFAULT NULL COMMENT '调度配置,值含义取决于调度类型',`misfire_strategy` varchar(50) NOT NULL DEFAULT 'DO_NOTHING' COMMENT '调度过期策略',`executor_route_strategy` varchar(50) DEFAULT NULL COMMENT '执行器路由策略',`executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler',`executor_param` varchar(512) DEFAULT NULL COMMENT '执行器任务参数',`executor_block_strategy` varchar(50) DEFAULT NULL COMMENT '阻塞处理策略',`executor_timeout` int(11) NOT NULL DEFAULT '0' COMMENT '任务执行超时时间,单位秒',`executor_fail_retry_count` int(11) NOT NULL DEFAULT '0' COMMENT '失败重试次数',`glue_type` varchar(50) NOT NULL COMMENT 'GLUE类型',`glue_source` mediumtext COMMENT 'GLUE源代码',`glue_remark` varchar(128) DEFAULT NULL COMMENT 'GLUE备注',`glue_updatetime` datetime DEFAULT NULL COMMENT 'GLUE更新时间',`child_jobid` varchar(255) DEFAULT NULL COMMENT '子任务ID,多个逗号分隔',`trigger_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '调度状态:0-停止,1-运行',`trigger_last_time` bigint(13) NOT NULL DEFAULT '0' COMMENT '上次调度时间',`trigger_next_time` bigint(13) NOT NULL DEFAULT '0' COMMENT '下次调度时间',PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;CREATE TABLE `xxl_job_log` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`job_group` int(11) NOT NULL COMMENT '执行器主键ID',`job_id` int(11) NOT NULL COMMENT '任务,主键ID',`executor_address` varchar(255) DEFAULT NULL COMMENT '执行器地址,本次执行的地址',`executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler',`executor_param` varchar(512) DEFAULT NULL COMMENT '执行器任务参数',`executor_sharding_param` varchar(20) DEFAULT NULL COMMENT '执行器任务分片参数,格式如 1/2',`executor_fail_retry_count` int(11) NOT NULL DEFAULT '0' COMMENT '失败重试次数',`trigger_time` datetime DEFAULT NULL COMMENT '调度-时间',`trigger_code` int(11) NOT NULL COMMENT '调度-结果',`trigger_msg` text COMMENT '调度-日志',`handle_time` datetime DEFAULT NULL COMMENT '执行-时间',`handle_code` int(11) NOT NULL COMMENT '执行-状态',`handle_msg` text COMMENT '执行-日志',`alarm_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '告警状态:0-默认、1-无需告警、2-告警成功、3-告警失败',PRIMARY KEY (`id`),KEY `I_trigger_time` (`trigger_time`),KEY `I_handle_code` (`handle_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;CREATE TABLE `xxl_job_log_report` (`id` int(11) NOT NULL AUTO_INCREMENT,`trigger_day` datetime DEFAULT NULL COMMENT '调度-时间',`running_count` int(11) NOT NULL DEFAULT '0' COMMENT '运行中-日志数量',`suc_count` int(11) NOT NULL DEFAULT '0' COMMENT '执行成功-日志数量',`fail_count` int(11) NOT NULL DEFAULT '0' COMMENT '执行失败-日志数量',`update_time` datetime DEFAULT NULL,PRIMARY KEY (`id`),UNIQUE KEY `i_trigger_day` (`trigger_day`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;CREATE TABLE `xxl_job_logglue` (`id` int(11) NOT NULL AUTO_INCREMENT,`job_id` int(11) NOT NULL COMMENT '任务,主键ID',`glue_type` varchar(50) DEFAULT NULL COMMENT 'GLUE类型',`glue_source` mediumtext COMMENT 'GLUE源代码',`glue_remark` varchar(128) NOT NULL COMMENT 'GLUE备注',`add_time` datetime DEFAULT NULL,`update_time` datetime DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;CREATE TABLE `xxl_job_registry` (`id` int(11) NOT NULL AUTO_INCREMENT,`registry_group` varchar(50) NOT NULL,`registry_key` varchar(255) NOT NULL,`registry_value` varchar(255) NOT NULL,`update_time` datetime DEFAULT NULL,PRIMARY KEY (`id`),KEY `i_g_k_v` (`registry_group`,`registry_key`,`registry_value`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;CREATE TABLE `xxl_job_group` (`id` int(11) NOT NULL AUTO_INCREMENT,`app_name` varchar(64) NOT NULL COMMENT '执行器AppName',`title` varchar(12) NOT NULL COMMENT '执行器名称',`address_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '执行器地址类型:0=自动注册、1=手动录入',`address_list` text COMMENT '执行器地址列表,多地址逗号分隔',`update_time` datetime DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;CREATE TABLE `xxl_job_user` (`id` int(11) NOT NULL AUTO_INCREMENT,`username` varchar(50) NOT NULL COMMENT '账号',`password` varchar(50) NOT NULL COMMENT '密码',`role` tinyint(4) NOT NULL COMMENT '角色:0-普通用户、1-管理员',`permission` varchar(255) DEFAULT NULL COMMENT '权限:执行器ID列表,多个逗号分割',PRIMARY KEY (`id`),UNIQUE KEY `i_username` (`username`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;CREATE TABLE `xxl_job_lock` (`lock_name` varchar(50) NOT NULL COMMENT '锁名称',PRIMARY KEY (`lock_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;INSERT INTO `xxl_job_group`(`id`, `app_name`, `title`, `address_type`, `address_list`, `update_time`) VALUES (1, 'xxl-job-executor-sample', '示例执行器', 0, NULL, '2018-11-03 22:21:31' );
INSERT INTO `xxl_job_info`(`id`, `job_group`, `job_desc`, `add_time`, `update_time`, `author`, `alarm_email`, `schedule_type`, `schedule_conf`, `misfire_strategy`, `executor_route_strategy`, `executor_handler`, `executor_param`, `executor_block_strategy`, `executor_timeout`, `executor_fail_retry_count`, `glue_type`, `glue_source`, `glue_remark`, `glue_updatetime`, `child_jobid`) VALUES (1, 1, '测试任务1', '2018-11-03 22:21:31', '2018-11-03 22:21:31', 'XXL', '', 'CRON', '0 0 0 * * ? *', 'DO_NOTHING', 'FIRST', 'demoJobHandler', '', 'SERIAL_EXECUTION', 0, 0, 'BEAN', '', 'GLUE代码初始化', '2018-11-03 22:21:31', '');
INSERT INTO `xxl_job_user`(`id`, `username`, `password`, `role`, `permission`) VALUES (1, 'admin', 'e10adc3949ba59abbe56e057f20f883e', 1, NULL);
INSERT INTO `xxl_job_lock` ( `lock_name`) VALUES ( 'schedule_lock');commit;

在我们的数据库运行一下这些sql文件,运行完成后,会产生如下的库与对应的表

在这里插入图片描述

2、修改配置文件

此处需要修改xxl-job-admin模块下的application.properties文件,

第一:端口号(看个人)

我这边是没有改动

server.port=8080

第二:修改数据库相关配置

主要是账号和密码

### xxl-job, datasource
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=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

第三:accessToken的设置:

我这边是设置为空

### xxl-job, access token
#xxl.job.accessToken=default_token
xxl.job.accessToken=

3、启动项目

此时我们准备工作已经做完,直接启动xxl-job-admin模块下的XxlJobAdminApplication项目即可。

提示以下内容表示成功
在这里插入图片描述

4、进行访问

在浏览器输入:http://127.0.0.1:8080/xxl-job-admin 即可成功访问。
用户密码分别为:admin/123456
登陆成功后可以看到此页面即为搭建成功。
在这里插入图片描述

5、打包部署(上正式)

暂未操作

二、SpringBoot集成Xxl-Job

1. 引入xxl-job的依赖

<dependency><groupId>com.xuxueli</groupId><artifactId>xxl-job-core</artifactId><version>2.3.1</version>
</dependency>

2. 在application.yml加上xxljob的配置

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

细节:

  • address的值 举例格式为 http://127.0.0.1:9999
  • 如果 address 不填, 控制器的地址取值就是 另外两个参数的组合 IP:PORT
    (ip不填就自动获取IP,port小于等于0则自动获取;默认端口为9999)
  • 如果 address 填了, 控制器的地址就是这个address

实际的启动端口 请观察控制台(port配置很重要,address配置中的端口是无法影响port的,请注意!!!)
在这里插入图片描述

配置参数讲解

属性名含义概要是否必填
addresses调度中心部署的地址如调度中心集群部署存在多个地址则用逗号(,)分隔。
执行器将会使用该地址进行"执行器心跳注册"和"任务结果回调";为空则关闭自动注册;
选填
属性名含义概要是否必填
accessToken执行器通讯TOKEN要和调度中心服务部署配置的accessToken一致,要不然无法连接注册选填
appname执行器名称执行器心跳注册分组依据;为空则关闭自动注册选填
address执行器注册地址有值时优先使用该配置作为注册地址,为空时使用内嵌服务 ”IP:PORT“ 作为注册地址。选填
ip执行器IP默认为空表示自动获取IP,多网卡时可手动设置指定IP,该IP不会绑定Host仅作为通讯实用。
地址信息用于 “执行器注册” 和 “调度中心请求并触发任务”;
选填
port执行器端口号小于等于0则自动获取;默认端口为9999,单机部署多个执行器时,注意要配置不同执行器端口必填
logpath执行器运行日志文件存储磁盘路径需要对该路径拥有读写权限;为空则使用默认路径选填
logretentiondays执行器日志文件保存天数过期日志自动清理, 限制值大于等于3时生效; 否则, 如-1, 关闭自动清理功能选填

3. 添加配置类

XxlJobConfig.java

package com.example.xxjob.config;import com.example.xxjob.job.DemoHandler;
import com.xxl.job.core.executor.XxlJobExecutor;
import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.Arrays;@Configuration
@Slf4j
public class XxlJobConfig {@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;@Beanpublic XxlJobSpringExecutor xxlJobExecutor() {log.info(">>>>>>>>>>> start xxl-job config init. >>>>>>>>");XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();//调度中心服务部署的地址xxlJobSpringExecutor.setAdminAddresses(adminAddresses);//执行器AppNamexxlJobSpringExecutor.setAppname(appname);//一般情况下Address何二ip用不上)xxlJobSpringExecutor.setAddress(address);xxlJobSpringExecutor.setIp(ip);//执行器端口号xxlJobSpringExecutor.setPort(port);//一般情况下AccessToken用不上xxlJobSpringExecutor.setAccessToken(accessToken);//执行器运行日志文件存储磁盘路径xxlJobSpringExecutor.setLogPath(logPath);//执行器日志文件保存天数xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);log.info(">>>>>>>>>>> end xxl-job config init. >>>>>>>>");return xxlJobSpringExecutor;}
}

4. 添加xxl-job测试(由调度中心进行测试)

1.先在自己的Springboot项目中创建测试类

@Slf4j
@Component
public class XxlJobTest {//配置运行模式名称@XxlJob("xxlJobTest")public ReturnT<String> xxlJobTest(String date) {log.info("---------xxlJobTest定时任务执行成功--------");return ReturnT.SUCCESS;}}

2. 再进入已经启动成功的调度中心页面中进行操作

1.根据 配置文件 新增 执行器
在这里插入图片描述
关于注册方式:自动注册和手动注册

  • 自动注册:AppName 不能乱填,要和配置文件统一,它才能自动注册进去
  • 手动注册:AppName 可以随意填写,但是机器地址就要需要填写正确
    (比如本地就是http://127.0.0.1:8889,其中这个8889来自于配置文件里面port参数)

2.根据 @XxlJob标注的方法 配置 执行器任务

我这边上面测试方法用的是 @XxlJob(“xxlJobTest”) 标注的

配置的任务时,要选好之前的执行器,再配置cros表达式和相应的方法
在这里插入图片描述

点击启动

在这里插入图片描述

就可以看到后台的这个方法被触发(5秒一次)

在这里插入图片描述

5. 动态API调度任务 (看个人需求)

通过API方式(或者方法函数),我们动态随意地去 增删改查、设置定时规则等等去调度任务。

在 xxl-job-admin 项目中

1. 新建 MyDynamicApiController

在这里插入图片描述

package com.xxl.job.admin.controller;import com.xxl.job.admin.controller.annotation.PermissionLimit;
import com.xxl.job.admin.core.cron.CronExpression;
import com.xxl.job.admin.core.model.XxlJobInfo;
import com.xxl.job.admin.core.model.XxlJobQuery;
import com.xxl.job.admin.core.thread.JobScheduleHelper;
import com.xxl.job.admin.core.util.I18nUtil;
import com.xxl.job.admin.service.LoginService;
import com.xxl.job.admin.service.XxlJobService;
import com.xxl.job.core.biz.model.ReturnT;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.text.ParseException;
import java.util.Date;
import java.util.Map;/*** @Author: JCccc* @Date: 2022-6-2 14:23* @Description: xxl job rest api*/
@RestController
@RequestMapping("/api/jobinfo")
public class MyDynamicApiController {private static Logger logger = LoggerFactory.getLogger(MyDynamicApiController.class);@Autowiredprivate XxlJobService xxlJobService;@Autowiredprivate LoginService loginService;@RequestMapping(value = "/pageList",method = RequestMethod.POST)public Map<String, Object> pageList(@RequestBody XxlJobQuery xxlJobQuery) {return xxlJobService.pageList(xxlJobQuery.getStart(),xxlJobQuery.getLength(),xxlJobQuery.getJobGroup(),xxlJobQuery.getTriggerStatus(),xxlJobQuery.getJobDesc(),xxlJobQuery.getExecutorHandler(),xxlJobQuery.getAuthor());}@PostMapping("/save")public ReturnT<String> add(@RequestBody(required = true)XxlJobInfo jobInfo) {// next trigger time (5s后生效,避开预读周期)long nextTriggerTime = 0;try {Date nextValidTime = new CronExpression(jobInfo.getScheduleConf()).getNextValidTimeAfter(new Date(System.currentTimeMillis() + JobScheduleHelper.PRE_READ_MS));if (nextValidTime == null) {return new ReturnT<String>(ReturnT.FAIL_CODE, I18nUtil.getString("jobinfo_field_cron_never_fire"));}nextTriggerTime = nextValidTime.getTime();} catch (ParseException e) {logger.error(e.getMessage(), e);return new ReturnT<String>(ReturnT.FAIL_CODE, I18nUtil.getString("jobinfo_field_cron_unvalid")+" | "+ e.getMessage());}jobInfo.setTriggerStatus(1);jobInfo.setTriggerLastTime(0);jobInfo.setTriggerNextTime(nextTriggerTime);jobInfo.setUpdateTime(new Date());if(jobInfo.getId()==0){return xxlJobService.add(jobInfo);}else{return xxlJobService.update(jobInfo);}}@RequestMapping(value = "/delete",method = RequestMethod.GET)public ReturnT<String> delete(int id) {return xxlJobService.remove(id);}@RequestMapping(value = "/start",method = RequestMethod.GET)public ReturnT<String> start(int id) {return xxlJobService.start(id);}@RequestMapping(value = "/stop",method = RequestMethod.GET)public ReturnT<String> stop(int id) {return xxlJobService.stop(id);}@RequestMapping(value="login", method=RequestMethod.GET)@PermissionLimit(limit=false)public ReturnT<String> loginDo(HttpServletRequest request, HttpServletResponse response, String userName, String password, String ifRemember){boolean ifRem = (ifRemember!=null && ifRemember.trim().length()>0 && "on".equals(ifRemember))?true:false;ReturnT<String> result= loginService.login(request, response, userName, password, ifRem);return result;}
}
2. 创建 XxlJobQuery

在这里插入图片描述

package com.xxl.job.admin.core.model;/*** @Author: JCccc* @Date: 2022-6-2 14:23* @Description: xxl job rest api*/
public class XxlJobQuery {private int start;private int length;private int triggerStatus;private String jobDesc;private String executorHandler;private String author;private int jobGroup;public int getStart() {return start;}public void setStart(int start) {this.start = start;}public int getLength() {return length;}public void setLength(int length) {this.length = length;}public int getTriggerStatus() {return triggerStatus;}public void setTriggerStatus(int triggerStatus) {this.triggerStatus = triggerStatus;}public String getJobDesc() {return jobDesc;}public void setJobDesc(String jobDesc) {this.jobDesc = jobDesc;}public String getExecutorHandler() {return executorHandler;}public void setExecutorHandler(String executorHandler) {this.executorHandler = executorHandler;}public String getAuthor() {return author;}public void setAuthor(String author) {this.author = author;}public int getJobGroup() {return jobGroup;}public void setJobGroup(int jobGroup) {this.jobGroup = jobGroup;}
}

在 自己的 SpringBoot 项目中

加maven依赖
      <!--(一个是fastjson,大家别学我,我是为了实战示例图方便,用的JsonObject来传参)--><!--(一个是httpClient ,用于调用admin服务的api接口)--><dependency><groupId>commons-httpclient</groupId><artifactId>commons-httpclient</artifactId><version>3.1</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.47</version></dependency>
1.创建 XxlJobInfo 类

这个就是原作者的使用的实体类

import java.util.Date;/*** xxl-job info** @author xuxueli  2016-1-12 18:25:49*/
public class XxlJobInfo {private int id;       // 主键IDprivate int jobGroup;   // 执行器主键IDprivate String jobDesc;     // 备注private String jobCron;private Date addTime;private Date updateTime;private String author;    // 负责人private String alarmEmail;  // 报警邮件private String scheduleType;      // 调度类型private String scheduleConf;      // 调度配置,值含义取决于调度类型private String misfireStrategy;     // 调度过期策略private String executorRouteStrategy; // 执行器路由策略private String executorHandler;       // 执行器,任务Handler名称private String executorParam;       // 执行器,任务参数private String executorBlockStrategy; // 阻塞处理策略private int executorTimeout;        // 任务执行超时时间,单位秒private int executorFailRetryCount;   // 失败重试次数private String glueType;    // GLUE类型 #com.xxl.job.core.glue.GlueTypeEnumprivate String glueSource;    // GLUE源代码private String glueRemark;    // GLUE备注private Date glueUpdatetime;  // GLUE更新时间private String childJobId;    // 子任务ID,多个逗号分隔private int triggerStatus;    // 调度状态:0-停止,1-运行private long triggerLastTime; // 上次调度时间private long triggerNextTime; // 下次调度时间public String getJobCron() {return jobCron;}public void setJobCron(String jobCron) {this.jobCron = jobCron;}public int getId() {return id;}public void setId(int id) {this.id = id;}public int getJobGroup() {return jobGroup;}public void setJobGroup(int jobGroup) {this.jobGroup = jobGroup;}public String getJobDesc() {return jobDesc;}public void setJobDesc(String jobDesc) {this.jobDesc = jobDesc;}public Date getAddTime() {return addTime;}public void setAddTime(Date addTime) {this.addTime = addTime;}public Date getUpdateTime() {return updateTime;}public void setUpdateTime(Date updateTime) {this.updateTime = updateTime;}public String getAuthor() {return author;}public void setAuthor(String author) {this.author = author;}public String getAlarmEmail() {return alarmEmail;}public void setAlarmEmail(String alarmEmail) {this.alarmEmail = alarmEmail;}public String getScheduleType() {return scheduleType;}public void setScheduleType(String scheduleType) {this.scheduleType = scheduleType;}public String getScheduleConf() {return scheduleConf;}public void setScheduleConf(String scheduleConf) {this.scheduleConf = scheduleConf;}public String getMisfireStrategy() {return misfireStrategy;}public void setMisfireStrategy(String misfireStrategy) {this.misfireStrategy = misfireStrategy;}public String getExecutorRouteStrategy() {return executorRouteStrategy;}public void setExecutorRouteStrategy(String executorRouteStrategy) {this.executorRouteStrategy = executorRouteStrategy;}public String getExecutorHandler() {return executorHandler;}public void setExecutorHandler(String executorHandler) {this.executorHandler = executorHandler;}public String getExecutorParam() {return executorParam;}public void setExecutorParam(String executorParam) {this.executorParam = executorParam;}public String getExecutorBlockStrategy() {return executorBlockStrategy;}public void setExecutorBlockStrategy(String executorBlockStrategy) {this.executorBlockStrategy = executorBlockStrategy;}public int getExecutorTimeout() {return executorTimeout;}public void setExecutorTimeout(int executorTimeout) {this.executorTimeout = executorTimeout;}public int getExecutorFailRetryCount() {return executorFailRetryCount;}public void setExecutorFailRetryCount(int executorFailRetryCount) {this.executorFailRetryCount = executorFailRetryCount;}public String getGlueType() {return glueType;}public void setGlueType(String glueType) {this.glueType = glueType;}public String getGlueSource() {return glueSource;}public void setGlueSource(String glueSource) {this.glueSource = glueSource;}public String getGlueRemark() {return glueRemark;}public void setGlueRemark(String glueRemark) {this.glueRemark = glueRemark;}public Date getGlueUpdatetime() {return glueUpdatetime;}public void setGlueUpdatetime(Date glueUpdatetime) {this.glueUpdatetime = glueUpdatetime;}public String getChildJobId() {return childJobId;}public void setChildJobId(String childJobId) {this.childJobId = childJobId;}public int getTriggerStatus() {return triggerStatus;}public void setTriggerStatus(int triggerStatus) {this.triggerStatus = triggerStatus;}public long getTriggerLastTime() {return triggerLastTime;}public void setTriggerLastTime(long triggerLastTime) {this.triggerLastTime = triggerLastTime;}public long getTriggerNextTime() {return triggerNextTime;}public void setTriggerNextTime(long triggerNextTime) {this.triggerNextTime = triggerNextTime;}
}
2.创建 XxlJobUtil 类
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.commons.httpclient.methods.StringRequestEntity;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;/*** @Author: JCccc* @Date: 2022-6-22 9:51* @Description:*/
public class XxlJobUtil {private static String cookie="";/*** 查询现有的任务(可以关注这个整个调用链,可以自己模仿着写其他的拓展接口)* @param url* @param requestInfo* @return* @throws HttpException* @throws IOException*/public static JSONObject pageList(String url,JSONObject requestInfo) throws HttpException, IOException {String path = "/api/jobinfo/pageList";String targetUrl = url + path;HttpClient httpClient = new HttpClient();PostMethod post = new PostMethod(targetUrl);post.setRequestHeader("cookie", cookie);RequestEntity requestEntity = new StringRequestEntity(requestInfo.toString(), "application/json", "utf-8");post.setRequestEntity(requestEntity);httpClient.executeMethod(post);JSONObject result = new JSONObject();result = getJsonObject(post, result);System.out.println(result.toJSONString());return result;}/*** 新增/编辑任务* @param url* @param requestInfo* @return* @throws HttpException* @throws IOException*/public static JSONObject addJob(String url,JSONObject requestInfo) throws HttpException, IOException {String path = "/api/jobinfo/save";String targetUrl = url + path;HttpClient httpClient = new HttpClient();PostMethod post = new PostMethod(targetUrl);post.setRequestHeader("cookie", cookie);RequestEntity requestEntity = new StringRequestEntity(requestInfo.toString(), "application/json", "utf-8");post.setRequestEntity(requestEntity);httpClient.executeMethod(post);JSONObject result = new JSONObject();result = getJsonObject(post, result);System.out.println(result.toJSONString());return result;}/*** 删除任务* @param url* @param id* @return* @throws HttpException* @throws IOException*/public static JSONObject deleteJob(String url,int id) throws HttpException, IOException {String path = "/api/jobinfo/delete?id="+id;return doGet(url,path);}/*** 开始任务* @param url* @param id* @return* @throws HttpException* @throws IOException*/public static JSONObject startJob(String url,int id) throws HttpException, IOException {String path = "/api/jobinfo/start?id="+id;return doGet(url,path);}/*** 停止任务* @param url* @param id* @return* @throws HttpException* @throws IOException*/public static JSONObject stopJob(String url,int id) throws HttpException, IOException {String path = "/api/jobinfo/stop?id="+id;return doGet(url,path);}public static JSONObject doGet(String url,String path) throws HttpException, IOException {String targetUrl = url + path;HttpClient httpClient = new HttpClient();HttpMethod get = new GetMethod(targetUrl);get.setRequestHeader("cookie", cookie);httpClient.executeMethod(get);JSONObject result = new JSONObject();result = getJsonObject(get, result);return result;}private static JSONObject getJsonObject(HttpMethod postMethod, JSONObject result) throws IOException {if (postMethod.getStatusCode() == HttpStatus.SC_OK) {InputStream inputStream = postMethod.getResponseBodyAsStream();BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));StringBuffer stringBuffer = new StringBuffer();String str;while((str = br.readLine()) != null){stringBuffer.append(str);}String response = new String(stringBuffer);br.close();return (JSONObject) JSONObject.parse(response);} else {return null;}}/*** 登录* @param url* @param userName* @param password* @return* @throws HttpException* @throws IOException*/public static String login(String url, String userName, String password) throws HttpException, IOException {String path = "/api/jobinfo/login?userName="+userName+"&password="+password;String targetUrl = url + path;HttpClient httpClient = new HttpClient();HttpMethod get = new GetMethod((targetUrl));httpClient.executeMethod(get);if (get.getStatusCode() == 200) {Cookie[] cookies = httpClient.getState().getCookies();StringBuffer tmpcookies = new StringBuffer();for (Cookie c : cookies) {tmpcookies.append(c.toString() + ";");}cookie = tmpcookies.toString();} else {try {cookie = "";} catch (Exception e) {cookie="";}}return cookie;}
}
3. 创建 XxlJobController 进行测试

(用于模拟触发我们的任务创建、编辑、删除、停止等等)

import java.util.Date;
import com.alibaba.fastjson.JSONObject;
import org.springframework.web.bind.annotation.*;
import java.io.IOException;/*** @Author: JCccc* @Date: 2022-6-22 9:26* @Description:*/
@RestController
public class XxlJobController {@RequestMapping(value = "/pageList",method = RequestMethod.GET)public Object pageList() throws IOException {//int jobGroup, int triggerStatus, String jobDesc, String executorHandler, String authorJSONObject test=new JSONObject();test.put("length",10);XxlJobUtil.login("http://127.0.0.1:8961/xxl-job-admin","admin","123456");JSONObject response = XxlJobUtil.pageList("http://127.0.0.1:8961/xxl-job-admin", test);return  response.get("data");}@RequestMapping(value = "/add",method = RequestMethod.GET)public void add() throws IOException {XxlJobInfo xxlJobInfo=new XxlJobInfo();xxlJobInfo.setJobCron("0/5 * * * * ?");xxlJobInfo.setJobGroup(3);xxlJobInfo.setJobDesc("我来试试");xxlJobInfo.setAddTime(new Date());xxlJobInfo.setUpdateTime(new Date());xxlJobInfo.setAuthor("JCccc");xxlJobInfo.setAlarmEmail("864477182@com");xxlJobInfo.setScheduleType("CRON");xxlJobInfo.setScheduleConf("0/5 * * * * ?");xxlJobInfo.setMisfireStrategy("DO_NOTHING");xxlJobInfo.setExecutorRouteStrategy("FIRST");xxlJobInfo.setExecutorHandler("clockInJobHandler");xxlJobInfo.setExecutorParam("att");xxlJobInfo.setExecutorBlockStrategy("SERIAL_EXECUTION");xxlJobInfo.setExecutorTimeout(0);xxlJobInfo.setExecutorFailRetryCount(1);xxlJobInfo.setGlueType("BEAN");xxlJobInfo.setGlueSource("");xxlJobInfo.setGlueRemark("GLUE代码初始化");xxlJobInfo.setGlueUpdatetime(new Date());JSONObject test = (JSONObject) JSONObject.toJSON(xxlJobInfo);XxlJobUtil.login("http://127.0.0.1:8961/xxl-job-admin","admin","123456");JSONObject response = XxlJobUtil.addJob("http://127.0.0.1:8961/xxl-job-admin", test);if (response.containsKey("code") && 200 == (Integer) response.get("code")) {System.out.println("新增成功");} else {System.out.println("新增失败");}}@RequestMapping(value = "/stop/{jobId}",method = RequestMethod.GET)public void stop(@PathVariable("jobId") Integer jobId) throws IOException {XxlJobUtil.login("http://127.0.0.1:8961/xxl-job-admin","admin","123456");JSONObject response = XxlJobUtil.stopJob("http://127.0.0.1:8961/xxl-job-admin", jobId);if (response.containsKey("code") && 200 == (Integer) response.get("code")) {System.out.println("任务停止成功");} else {System.out.println("任务停止失败");}}@RequestMapping(value = "/delete/{jobId}",method = RequestMethod.GET)public void delete(@PathVariable("jobId") Integer jobId) throws IOException {XxlJobUtil.login("http://127.0.0.1:8961/xxl-job-admin","admin","123456");JSONObject response = XxlJobUtil.deleteJob("http://127.0.0.1:8961/xxl-job-admin", jobId);if (response.containsKey("code") && 200 == (Integer) response.get("code")) {System.out.println("任务移除成功");} else {System.out.println("任务移除失败");}}@RequestMapping(value = "/start/{jobId}",method = RequestMethod.GET)public void start(@PathVariable("jobId") Integer jobId) throws IOException {XxlJobUtil.login("http://127.0.0.1:8961/xxl-job-admin","admin","123456");JSONObject response = XxlJobUtil.startJob("http://127.0.0.1:8961/xxl-job-admin", jobId);if (response.containsKey("code") && 200 == (Integer) response.get("code")) {System.out.println("任务启动成功");} else {System.out.println("任务启动失败");}}}

相关文章:

SpringBoot教程(二十三) | SpringBoot实现分布式定时任务之xxl-job

SpringBoot教程&#xff08;二十三&#xff09; | SpringBoot实现分布式定时任务之xxl-job 简介一、前置条件&#xff1a;需要搭建调度中心1、先下载调度中心源码2、修改配置文件3、启动项目4、进行访问5、打包部署&#xff08;上正式&#xff09; 二、SpringBoot集成Xxl-Job1.…...

微前端架构的数据持久化策略与实践

微前端架构通过将一个大型前端应用拆分成多个小型、自治的子应用&#xff0c;提升了开发效率和应用的可维护性。然而&#xff0c;数据持久化作为应用的基础需求&#xff0c;在微前端架构中实现起来面临着一些挑战。本文将详细介绍在微前端架构下实现数据持久化的策略、技术和最…...

讲解 狼人杀中的买单双是什么意思

买单双这个概念通常出现在有第三方的板子中 比如 咒狐板子 丘比特板子 咒狐板子 第一天狼队只要推掉预言家 第二天就可以与咒狐协商绑票 推出其他好人 以及丘比特板子 如果拉出一个人狼链 那么如果孤独再连一个狼人 那么 狼队第一天就可以直接派人上去拿警徽&#xff0c;这样…...

回归分析系列5-贝叶斯回归

07贝叶斯回归 7.1 简介 贝叶斯回归将贝叶斯统计的思想应用于回归分析中&#xff0c;通过先验分布和似然函数来推断后验分布。在贝叶斯回归中&#xff0c;模型参数被视为随机变量&#xff0c;并且有自己的分布。通过贝叶斯公式&#xff0c;可以更新这些参数的分布&#xff0c;…...

oracle 数据中lsnrctl 是干啥的

突然发现lsnrctl stop 之后&#xff0c;依然可以启动数据库 就感觉怪怪的&#xff0c;一直以为这个是数据库的守护进程&#xff0c;原来不是。。。。 lsnrctl 是 Oracle 监听器控制实用程序的命令行界面工具&#xff0c;用于管理 Oracle Net 服务监听器。监听器是 Oracle 网络…...

Linux进程--进程地址空间

文章目录 一、进程地址空间1.想当然的内存2.实际的内存1.什么是地址空间2.地址空间和内存3.为什么要区分两种内存 一、进程地址空间 1.想当然的内存 我们在之前的学习中了解过内存的概念&#xff0c;所以变量都要存在内存中我们的程序才能跑起来&#xff0c;那么我们肯定也见…...

C语言传递指针给函数

C 语言允许您传递指针给函数&#xff0c;只需要简单地声明函数参数为指针类型即可。 下面的实例中&#xff0c;我们传递一个无符号的 long 型指针给函数&#xff0c;并在函数内改变这个值 实例1&#xff1a;获取系统的时间值 能接受指针作为参数的函数&#xff0c;也能接受数…...

探索 Kubernetes 持久化存储之 Rook Ceph 初窥门径

在 Kubernetes 生态系统中&#xff0c;持久化存储是支撑业务应用稳定运行的基石&#xff0c;对于维护整个系统的健壮性至关重要。对于选择自主搭建 Kubernetes 集群的运维架构师来说&#xff0c;挑选合适的后端持久化存储解决方案是关键的选型决策。目前&#xff0c;Ceph、Glus…...

今日(2024 年 8 月 13 日)科技新闻

我国成功发射卫星互联网高轨卫星&#xff1a;该卫星的成功发射将助力我国卫星互联网的发展。中国首台中子全散射谱仪运行 3 年成果丰硕&#xff1a;由粤港科技合作打造的多物理谱仪&#xff0c;在中国散裂中子源上运行 3 年来&#xff0c;已完成 300 多项用户实验。该谱仪的关键…...

Unity大场景切换进行异步加载时,如何设计加载进度条,并配置滑动条按照的曲线给定的速率滑动

一、异步加载场景的过程 1、异步加载场景用到的API LoadSceneAsync 2、异步加载的参数说明 &#xff08;1&#xff09;默认参数&#xff1a;SceneManagement.LoadSceneAsync(“SceneName”); AsyncOperation task SceneManager.LoadSceneAsync("SceneName");&a…...

Selenium + Python 自动化测试16(Python基础复习)

我们的目标是&#xff1a;按照这一套资料学习下来&#xff0c;大家可以独立完成自动化测试的任务。 上一篇我们讨论了使用模块化测试的测试模型&#xff0c;从某一程度也反映出熟练掌握一门编程语言的重要性。 为了后续进一步深入学习。本篇文章主要做下Python基础知识的复习。…...

2024新型数字政府综合解决方案(六)

新型数字政府综合解决方案通过融合人工智能、大数据、区块链和云计算技术&#xff0c;构建了一个全方位智能化的政务平台&#xff0c;旨在提升政府服务的效率、透明度和公众参与度。该方案实现了跨部门的数据互联互通与实时更新&#xff0c;利用先进的数据分析和自动化处理技术…...

vscode的C/C++环境配置和调试技巧

目录 1.背景 2.下载编译器 3.配置环境变量 4.安装C/C插件 5.写C语言代码并且编译成功 5.1文件操作 5.2对于两个窗口的解释 5.3C语言编译环境配置 6.创建执行文件 7.编译运行过程 8.写其他的代码的解决方案一 9.写其他的代码的解决方案二 10.同时编译多个.c文件 10…...

Python制作《扫雷》游戏-附源码,轻松看懂,简单易学

今天介绍另一款经典小游戏&#xff0c;扫雷&#xff0c;这个应该是很多人windows电脑里玩的最多的游戏了&#xff0c;乐趣很多&#xff0c;而且还有一定的技术含量在里面&#xff0c;今天我们就来通过python实现这个小游戏。 创建扫雷文件 打开pycharm&#xff0c;创建一个名…...

8路VBO转HDMI2.0支持4K60频率ITE6265芯片方案心得分享

在此之前&#xff0c;有人找到我这边询问能不能将智能电视主板改成机顶盒&#xff0c;将VBO信号转换输出位HDMI进行投屏&#xff0c;具体应用奇奇怪怪&#xff01;但是奈何是甲方大佬。认命照做。从网上也有搜索了解过这类芯片&#xff0c;发现资料很少&#xff0c;所以有了这篇…...

【问题解决3】【已解决】Cannot determine path to‘tools.jar‘libraryfor17

前几天在IDEA运行JAVA项目时&#xff0c;出现这个报错。 这是因为是这个笔记本上安装的IDEA版本是“IntelliJ IDEA 2020.3.1”&#xff0c;与JDK17版本不兼容&#xff0c;这种情况下要想使得IDEA版本与JDK版本兼容&#xff0c;就需要升级IDEA版本或者使用JDK较低版本&#xff…...

基于Spring Boot的高效宠物购物平台

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…...

【Vue3】路由基础

【Vue3】路由基础 背景简介开发环境开发步骤及源码总结 背景 随着年龄的增长&#xff0c;很多曾经烂熟于心的技术原理已被岁月摩擦得愈发模糊起来&#xff0c;技术出身的人总是很难放下一些执念&#xff0c;遂将这些知识整理成文&#xff0c;以纪念曾经努力学习奋斗的日子。本…...

掌握网络数据的钥匙:Python Requests-HTML库深度解析

文章目录 掌握网络数据的钥匙&#xff1a;Python Requests-HTML库深度解析背景&#xff1a;为何选择Requests-HTML&#xff1f;什么是Requests-HTML&#xff1f;如何安装Requests-HTML&#xff1f;5个简单库函数的使用方法3个场景下库的使用示例常见Bug及解决方案总结 掌握网络…...

网络安全: 模型的脆弱性,鲁棒性和隐私性

在网络安全领域&#xff0c;通常描述模型安全性时&#xff0c;会提到以下三个特性&#xff1a; 脆弱性&#xff08;Vulnerability&#xff09;&#xff1a;指模型在某些情况下容易受到攻击或被利用的弱点。例如&#xff0c;模型可能对对抗性攻击或梯度泄露攻击敏感。 鲁棒性&a…...

Python实现prophet 理论及参数优化

文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候&#xff0c;写过一篇简单实现&#xff0c;后期随着对该模型的深入研究&#xff0c;本次记录涉及到prophet 的公式以及参数调优&#xff0c;从公式可以更直观…...

数据链路层的主要功能是什么

数据链路层&#xff08;OSI模型第2层&#xff09;的核心功能是在相邻网络节点&#xff08;如交换机、主机&#xff09;间提供可靠的数据帧传输服务&#xff0c;主要职责包括&#xff1a; &#x1f511; 核心功能详解&#xff1a; 帧封装与解封装 封装&#xff1a; 将网络层下发…...

python如何将word的doc另存为docx

将 DOCX 文件另存为 DOCX 格式&#xff08;Python 实现&#xff09; 在 Python 中&#xff0c;你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是&#xff0c;.doc 是旧的 Word 格式&#xff0c;而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...

什么是EULA和DPA

文章目录 EULA&#xff08;End User License Agreement&#xff09;DPA&#xff08;Data Protection Agreement&#xff09;一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA&#xff08;End User License Agreement&#xff09; 定义&#xff1a; EULA即…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

如何在网页里填写 PDF 表格?

有时候&#xff0c;你可能希望用户能在你的网站上填写 PDF 表单。然而&#xff0c;这件事并不简单&#xff0c;因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件&#xff0c;但原生并不支持编辑或填写它们。更糟的是&#xff0c;如果你想收集表单数据&#xff…...

用机器学习破解新能源领域的“弃风”难题

音乐发烧友深有体会&#xff0c;玩音乐的本质就是玩电网。火电声音偏暖&#xff0c;水电偏冷&#xff0c;风电偏空旷。至于太阳能发的电&#xff0c;则略显朦胧和单薄。 不知你是否有感觉&#xff0c;近两年家里的音响声音越来越冷&#xff0c;听起来越来越单薄&#xff1f; —…...

elementUI点击浏览table所选行数据查看文档

项目场景&#xff1a; table按照要求特定的数据变成按钮可以点击 解决方案&#xff1a; <el-table-columnprop"mlname"label"名称"align"center"width"180"><template slot-scope"scope"><el-buttonv-if&qu…...

论文阅读:LLM4Drive: A Survey of Large Language Models for Autonomous Driving

地址&#xff1a;LLM4Drive: A Survey of Large Language Models for Autonomous Driving 摘要翻译 自动驾驶技术作为推动交通和城市出行变革的催化剂&#xff0c;正从基于规则的系统向数据驱动策略转变。传统的模块化系统受限于级联模块间的累积误差和缺乏灵活性的预设规则。…...

实战设计模式之模板方法模式

概述 模板方法模式定义了一个操作中的算法骨架&#xff0c;并将某些步骤延迟到子类中实现。模板方法使得子类可以在不改变算法结构的前提下&#xff0c;重新定义算法中的某些步骤。简单来说&#xff0c;就是在一个方法中定义了要执行的步骤顺序或算法框架&#xff0c;但允许子类…...