分布式任务调度平台中文文档:https://www.xuxueli.com/xxl-job/
1、 概述
XXL-JOB是一个分布式任务调度平台,其核心设计目标是开发迅速、学习简单、轻量级、易扩展。现已开放源代码并接入多家公司线上产品线,开箱即用。
2、快速入门
2.1 初始化“调度数据库”
下载项目源码并解压sql脚本路径:/xxl-job/doc/db/tables_xxl_job.sql
2.2、编译源码
xxl-job-admin:调度中心
xxl-job-core:公共依赖
xxl-job-executor-samples:执行器Sample示例(选择合适的版本执行器,可直接使用,也可以参考其并将现有项目改造成执行器)
:xxl-job-executor-sample-springboot:Springboot版本,通过Springboot管理执行器,推荐这种方式;
:xxl-job-executor-sample-frameless:无框架版本;
2.3 配置部署“调度中心 xxl-job-admin”
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=123456
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
### 报警邮箱
spring.mail.host=smtp.qq.com
spring.mail.port=25
spring.mail.username=xxx@qq.com
spring.mail.password=xxx
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
spring.mail.properties.mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory
### 调度中心通讯TOKEN [选填]:非空时启用;
xxl.job.accessToken=
### 调度中心国际化配置 [必填]: 默认为 "zh_CN"/中文简体, 可选范围为 "zh_CN"/中文简体, "zh_TC"/中文繁体 and "en"/英文;
xxl.job.i18n=zh_CN
## 调度线程池最大线程配置【必填】
xxl.job.triggerpool.fast.max=200
xxl.job.triggerpool.slow.max=100
### 调度中心日志表数据保存天数 [必填]:过期日志自动清理;限制大于等于7时生效,否则, 如-1,关闭自动清理功能;
xxl.job.logretentiondays=30
2.4 配置部署执行器 xxl-job-executor-sample-springboot
<!-- xxl-job-core -->
<dependency>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-job-core</artifactId>
<version>${project.parent.version}</version>
</dependency>
### 调度中心部署根地址 [选填]:如调度中心集群部署存在多个地址则用逗号分隔。执行器将会使用该地址进行"执行器心跳注册"和"任务结果回调";为空则关闭自动注册;
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
2.5 执行器组件配置
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
*
* @author xuxueli 2017-04-28
*/
@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();
*/
}
2.6 自定义任务执行器
1、任务开发:在Spring Bean实例中,开发Job方法;
2、注解配置:为Job方法添加注解 "@XxlJob(value="自定义jobhandler名称", init = "JobHandler初始化方法", destroy = "JobHandler销毁方法")",注解value值对应的是调度中心新建任务的JobHandler属性的值。
3、执行日志:需要通过 "XxlJobHelper.log" 打印执行日志;
4、任务结果:默认任务结果为 "成功" 状态,不需要主动设置;如有诉求,比如设置任务结果为失败,可以通过 "XxlJobHelper.handleFail/handleSuccess" 自主设置任务结果;
@Component
public class MyXxlJob {
/**
*
* @throws Exception
*/
@XxlJob("myJobHandler")
public void execute() throws Exception {
/**
* 获取调度任务中传递的任务参数 可以为 单个值 也可以为 json
*/
String jobParam = XxlJobHelper.getJobParam();
System.out.println("测试");
}
}
2.7 任务调度中心创建执行器
AppName: 是每个执行器集群的唯一标示AppName, 执行器会周期性以AppName为对象进行自动注册。可通过该配置自动发现注册成功的执行器, 供任务调度时使用;
名称: 执行器的名称, 因为AppName限制字母数字等组成,可读性不强, 名称为了提高执行器的可读性;
排序: 执行器的排序, 系统中需要执行器的地方,如任务新增, 将会按照该排序读取可用的执行器列表;
注册方式:调度中心获取执行器地址的方式;
自动注册:执行器自动进行执行器注册,调度中心通过底层注册表可以动态发现执行器机器地址;
手动录入:人工手动录入执行器的地址信息,多地址逗号分隔,供调度中心使用;
机器地址:"注册方式"为"手动录入"时有效,支持人工维护执行器的地址信息;
2.8 任务调度中心创建调度任务
运行模式选中 “BEAN模式”,JobHandler属性填写任务注解“@XxlJob”中定义的值
3、通过HTTP请求配置调度任务
创建一个spring boot项目
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.10.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
<scope>provided</scope>
</dependency>
<!--fastjson-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.75</version>
</dependency>
<!--hutool-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.6.7</version>
</dependency>
</dependencies>
配置文件application.yml
xxl:
# xxl-job任务调度中心的注册地址
path: http://127.0.0.1:8080/xxl-job-admin
login: /login
add: /jobinfo/add
update: /jobinfo/update
remove: /jobinfo/remove
start: /jobinfo/start
stop: /jobinfo/stop
username: admin
pd: 123456
server:
port: 8088
XxlJobConfig 用于读取配置文件内容
@Component
public class XxlJobConfig {
public static String JOB_PATH;
public static String JOB_LOGIN;
public static String JOB_ADD;
public static String JOB_UPDATE;
public static String JOB_REMOVE;
public static String JOB_START;
public static String JOB_STOP;
public static String XXL_USERNAME;
public static String XXL_PD;
@Value("${xxl.path}")
public void setJobPath(String jobPath) {
JOB_PATH = jobPath;
}
@Value("${xxl.login}")
public void setJobLogin(String jobLogin) {
JOB_LOGIN = jobLogin;
}
@Value("${xxl.add}")
public void setJobAdd(String jobAdd) {
JOB_ADD = jobAdd;
}
@Value("${xxl.update}")
public void setJobUpdate(String jobUpdate) {
JOB_UPDATE = jobUpdate;
}
@Value("${xxl.remove}")
public void setJobRemove(String jobRemove) {
JOB_REMOVE = jobRemove;
}
@Value("${xxl.start}")
public void setJobStart(String jobStart) {
JOB_START = jobStart;
}
@Value("${xxl.stop}")
public void setJobStop(String jobStop) {
JOB_STOP = jobStop;
}
@Value("${xxl.username}")
public void setXxlUsername(String xxlUsername) {
XXL_USERNAME = xxlUsername;
}
@Value("${xxl.pd}")
public void setXxlPd(String xxlPd) {
XXL_PD = xxlPd;
}
}
OkHttpClientUtil 用于向任务调度中心发送请求
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.lx.job.config.XxlJobConfig;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import java.io.IOException;
import java.net.HttpCookie;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@Slf4j
public class OkHttpClientUtil {
static OkHttpClient client = new OkHttpClient();
/**
* 发送 post 请求
* @param url
* @param paramMap
* @return
*/
public static String doPost(String url, Map<String, Object> paramMap) throws IOException {
MediaType mediaType = MediaType.parse("application/json");
// 封装数据体
FormBody.Builder builder = new FormBody.Builder();
Iterator<Map.Entry<String,Object>> iterator = paramMap.entrySet().iterator();
Map.Entry<String,Object> item;
while (iterator.hasNext()){
item = iterator.next();
builder.add(item.getKey(),item.getValue() + "");
}
String cookie = OkHttpClientUtil.getCookie();
RequestBody body = builder.build();
Request request = new Request.Builder()
.url(url)
.post(body)
.addHeader("Cookie", cookie)
.addHeader("Content-Type", "application/json")
.build();
Response response = client.newCall(request).execute();
return response.body().string();
}
/**
* 模拟登录获取cookie
* @return
*/
public static String getCookie(){
String path = XxlJobConfig.JOB_PATH + XxlJobConfig.JOB_LOGIN;
Map<String, Object> hashMap = new HashMap();
hashMap.put("userName", XxlJobConfig.XXL_USERNAME);
hashMap.put("password", XxlJobConfig.XXL_PD);
HttpResponse response = HttpRequest.post(path).form(hashMap).execute();
List<HttpCookie> cookies = response.getCookies();
StringBuilder sb = new StringBuilder();
for (HttpCookie cookie : cookies) {
sb.append(cookie.toString());
}
return sb.toString();
}
}
JobUtil 对于调度任务的操作
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.lx.job.config.XxlJobConfig;
import com.lx.job.po.XxlJobPO;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
@Slf4j
public class JobUtil {
/**
* 新增任务
* @param jobGroup 执行器主键ID
* @param jobDesc 任务名称
* @param scheduleType 任务类型 CRON
* @param cron cron表达式
* @param executorHandler 执行器
* @param executorParam 执行参数
* @return
* @throws IOException
*/
public static int createJob(int jobGroup, String jobDesc,String scheduleType, String cron,
String executorHandler, String executorParam) throws IOException {
log.info("------------------------------start---------------------");
Integer jobId = null;
Map<String, Object> paramMap = new HashMap<>();
/* 配置文件读取 */
paramMap.put("jobGroup", jobGroup);
/* 参数传递 */
paramMap.put("jobDesc", jobDesc);
paramMap.put("author", "admin");
paramMap.put("scheduleType", scheduleType);
paramMap.put("scheduleConf", cron);
paramMap.put("cronGen_display", cron);
paramMap.put("glueType", "BEAN");
/* 执行器 */
paramMap.put("executorHandler", executorHandler);
// 此处hander需提前在项目中定义
/* 参数 */
paramMap.put("executorParam", executorParam);
paramMap.put("executorRouteStrategy", "RANDOM");
paramMap.put("misfireStrategy", "DO_NOTHING");
paramMap.put("executorBlockStrategy", "SERIAL_EXECUTION");
paramMap.put("executorTimeout", "0");
paramMap.put("executorFailRetryCount", "0");
paramMap.put("glueRemark", "GLUE代码初始化");
String url = XxlJobConfig.JOB_PATH + XxlJobConfig.JOB_ADD;
String s = OkHttpClientUtil.doPost(url, paramMap);
JSONObject jsonObject = JSON.parseObject(s);
int code = jsonObject.getIntValue("code");
log.info("===================code: {}", code);
if (code == 200) {
jobId = jsonObject.getIntValue("content");
}
log.info("--------------------------------end---------------------------");
return jobId;
}
/**
* 修改任务
* @return
* @throws IOException
*/
public static int updateJob(XxlJobPO xxlJobPO) throws IOException{
log.info("------------------------------start---------------------");
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("id", xxlJobPO.getId());
/* 配置文件读取 */
paramMap.put("jobGroup", xxlJobPO.getJobGroup());
/* 参数传递 */
paramMap.put("jobDesc", xxlJobPO.getJobDesc());
paramMap.put("author", "admin");
paramMap.put("scheduleType", xxlJobPO.getScheduleType());
paramMap.put("scheduleConf", xxlJobPO.getScheduleConf());
paramMap.put("cronGen_display", xxlJobPO.getScheduleConf());
paramMap.put("glueType", "BEAN");
/* 执行器 */
paramMap.put("executorHandler", xxlJobPO.getExecutorHandler());
// 此处hander需提前在项目中定义
/* 参数 */
paramMap.put("executorParam", xxlJobPO.getExecutorParam());
paramMap.put("executorRouteStrategy", "RANDOM");
paramMap.put("misfireStrategy", "DO_NOTHING");
paramMap.put("executorBlockStrategy", "SERIAL_EXECUTION");
paramMap.put("executorTimeout", "0");
paramMap.put("executorFailRetryCount", "0");
paramMap.put("glueRemark", "GLUE代码初始化");
String url = XxlJobConfig.JOB_PATH + XxlJobConfig.JOB_UPDATE;
String s = OkHttpClientUtil.doPost(url, paramMap);
JSONObject jsonObject = JSON.parseObject(s);
int code = jsonObject.getIntValue("code");
int jobId = 0;
log.info("===================code: {}", code);
if (code == 200) {
jobId = jsonObject.getIntValue("content");
} else {
log.error("修改任务失败, 任务编号:{}", jobId);
}
return jobId;
}
/**
* 删除任务
* @param jobId 任务ID
* @throws IOException
*/
public static void removeJob(int jobId) throws IOException{
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("id", jobId);
String removeUrl = XxlJobConfig.JOB_PATH + XxlJobConfig.JOB_REMOVE;
String responseResult = OkHttpClientUtil.doPost(removeUrl, paramMap);
JSONObject jsonObject = JSON.parseObject(responseResult);
int code = jsonObject.getIntValue("code");
if (code == 200) {
log.info("删除任务成功,任务编号:{}", jobId);
} else {
log.error("删除任务失败,任务编号:{}", jobId);
}
}
/**
* 启动任务
* @param jobId
* @throws IOException
*/
public static void startJob(int jobId) throws IOException{
Map<String, Object> parmaMap = new HashMap<>();
parmaMap.put("id", jobId);
String startUrl = XxlJobConfig.JOB_PATH + XxlJobConfig.JOB_START;
String responseResult = OkHttpClientUtil.doPost(startUrl, parmaMap);
JSONObject jsonObject = JSON.parseObject(responseResult);
int code = jsonObject.getIntValue("code");
if (code == 200) {
log.info("启动任务成功,任务编号:{}", jobId);
} else {
log.error("启动任务失败,任务编号:{}", jobId);
}
}
/**
* 停止任务
* @param jobId
* @throws IOException
*/
public static void stopJob(int jobId) throws IOException{
Map<String, Object> parmaMap = new HashMap<>();
parmaMap.put("id", jobId);
String stopUrl = XxlJobConfig.JOB_PATH + XxlJobConfig.JOB_STOP;
String responseResult = OkHttpClientUtil.doPost(stopUrl, parmaMap);
JSONObject jsonObject = JSON.parseObject(responseResult);
int code = jsonObject.getIntValue("code");
if (code == 200) {
log.info("停止任务成功,任务编号:{}", jobId);
} else {
log.error("停止任务失败,任务编号:{}", jobId);
}
}
}
JobController 接收请求处理参数然后将请求转发至任务调度中心
@Slf4j
@RestController
@RequestMapping("/job")
public class JobController {
@Autowired
private JobService jobService;
/**
* 新增调度任务
*
* @param xxlJobInfoDTO
* @return
*/
@PostMapping(value = "/add")
public R<String> add(@RequestBody XxlJobInfoDTO xxlJobInfoDTO) {
log.info("新增调度任务传递参数: {}", xxlJobInfoDTO);
int jobId = jobService.addJob(xxlJobInfoDTO);
log.info("新增调度任务返回参数: {}", jobId);
return R.data(String.valueOf(jobId));
}
/**
* 修改调度任务
*
* @param xxlJobInfoDTO
* @return
*/
@PostMapping(value = "/update")
public R<String> update(@RequestBody XxlJobInfoDTO xxlJobInfoDTO) {
log.info("修改调度任务传递参数: {}", xxlJobInfoDTO);
int jobId = jobService.updateJob(xxlJobInfoDTO);
log.info("修改调度任务返回参数: {}", jobId);
return R.data(String.valueOf(jobId));
}
/**
* 删除调度任务
*
* @param id
* @return
*/
@PostMapping(value = "/remove")
public R<String> remove(@RequestBody String id) {
log.info("删除调度任务请求参数: {}", id);
jobService.removeJob(id);
log.info("删除调度任务返回结果: {}", id);
return R.data(id);
}
/**
* 启动调度任务
*
* @param id
* @return
*/
@PostMapping(value = "/start")
public R<String> start(@RequestBody String id) {
log.info("启动调度任务请求参数: {}", id);
jobService.start(id);
log.info("启动调度任务返回结果: {}", id);
return R.data(id);
}
/**
* 停止调度任务
*
* @param id
* @return
*/
@PostMapping(value = "/stop")
public R<String> stop(@RequestBody String id) {
log.info("停止调度任务请求参数: {}", id);
jobService.stopJob(id);
log.info("停止调度任务返回结果: {}", id);
return R.data(id);
}
}
public interface JobService {
/**
* 新增任务
* @param xxlJobInfoDTO
* @return
*/
int addJob(XxlJobInfoDTO xxlJobInfoDTO);
/**
* 修改任务
* @param xxlJobInfoDTO
* @return
*/
int updateJob(XxlJobInfoDTO xxlJobInfoDTO);
/**
* 删除任务
* @param executorParam
* @return
*/
int removeJob(String executorParam);
/**
* 启动任务
* @param executorParam
* @return
*/
int start(String executorParam);
/**
* 停止任务
* @param executorParam
* @return
*/
int stopJob(String executorParam);
}
@Slf4j
@Service
public class JobServiceImpl implements JobService {
@Override
public int addJob(XxlJobInfoDTO xxlJobInfoDTO) {
String scheduleType = xxlJobInfoDTO.getScheduleType() != null ? xxlJobInfoDTO.getScheduleType() : "CRON";
int jobId = 0;
try {
jobId = JobUtil.createJob(xxlJobInfoDTO.getJobGroup(), xxlJobInfoDTO.getJobDesc(), scheduleType, xxlJobInfoDTO.getScheduleConf(),
xxlJobInfoDTO.getExecutorHandler(), xxlJobInfoDTO.getExecutorParam());
JobUtil.startJob(jobId);
} catch (IOException e) {
log.error("新增定时任务失败: {}", e.getMessage());
}
return jobId;
}
@Override
public int updateJob(XxlJobInfoDTO xxlJobInfoDTO) {
Map<String, Object> params = new HashMap<>();
params.put("executorParam", xxlJobInfoDTO.getExecutorParam());
//调用远程数据库插入接口
XxlJobPO xxlJobPO =new XxlJobPO();
String scheduleType = xxlJobInfoDTO.getScheduleType() != null ? xxlJobInfoDTO.getScheduleType() : "CRON";
xxlJobPO.setScheduleType(scheduleType);
xxlJobPO.setScheduleConf(xxlJobInfoDTO.getScheduleConf());
int jobId = 0;
try {
jobId = JobUtil.updateJob(xxlJobPO);
} catch (IOException e) {
log.error("修改定时任务失败", e.getMessage());
}
return jobId;
}
@Override
public int removeJob(String executorParam) {
try {
JobUtil.removeJob(Integer.parseInt(executorParam));
} catch (IOException e) {
log.error(e.getMessage());
}
return 0;
}
@Override
public int start(String executorParam) {
try {
JobUtil.startJob(Integer.parseInt(executorParam));
} catch (IOException e) {
log.error(e.getMessage());
}
return Integer.valueOf(executorParam);
}
@Override
public int stopJob(String executorParam) {
try {
JobUtil.stopJob(Integer.parseInt(executorParam));
} catch (IOException e) {
log.error(e.getMessage());
}
return 0;
}
}
@Data
public class XxlJobPO implements Serializable {
private static final long serialVersionUID = -6295333500034188754L;
/**
* 主键ID
*/
private int id;
/**
* 执行器主键ID
*/
private int jobGroup;
private String jobDesc;
private Date addTime;
private Date updateTime;
/**
* 负责人
*/
private String author;
/**
* 报警邮件
*/
private String alarmEmail;
/**
* 调度类型
*/
private String scheduleType;
/**
* 调度配置,值含义取决于调度类型
*/
private String scheduleConf;
/**
* 调度过期策略
*/
private String misfireStrategy;
/**
* 执行器路由策略
*/
private String executorRouteStrategy;
/**
* 执行器,任务Handler名称
*/
private String executorHandler;
/**
* 执行器,任务参数
*/
private String executorParam;
/**
* 阻塞处理策略
*/
private String executorBlockStrategy;
/**
* 任务执行超时时间,单位秒
*/
private int executorTimeout;
/**
* 失败重试次数
*/
private int executorFailRetryCount;
/**
* LUE类型 com.xxl.job.core.glue.GlueTypeEnum
*/
private String glueType;
/**
* GLUE源代码
*/
private String glueSource;
/**
* GLUE备注
*/
private String glueRemark;
/**
* GLUE更新时间
*/
private Date glueUpdatetime;
/**
* 子任务ID,多个逗号分隔
*/
private String childJobId;
/**
* 调度状态:0-停止,1-运行
*/
private int triggerStatus;
/**
* 上次调度时间
*/
private long triggerLastTime;
/**
* 下次调度时间
*/
private long triggerNextTime;
}
@Data
public class XxlJobPO implements Serializable {
private static final long serialVersionUID = -6295333500034188754L;
/**
* 主键ID
*/
private int id;
/**
* 执行器主键ID
*/
private int jobGroup;
private String jobDesc;
private Date addTime;
private Date updateTime;
/**
* 负责人
*/
private String author;
/**
* 报警邮件
*/
private String alarmEmail;
/**
* 调度类型
*/
private String scheduleType;
/**
* 调度配置,值含义取决于调度类型
*/
private String scheduleConf;
/**
* 调度过期策略
*/
private String misfireStrategy;
/**
* 执行器路由策略
*/
private String executorRouteStrategy;
/**
* 执行器,任务Handler名称
*/
private String executorHandler;
/**
* 执行器,任务参数
*/
private String executorParam;
/**
* 阻塞处理策略
*/
private String executorBlockStrategy;
/**
* 任务执行超时时间,单位秒
*/
private int executorTimeout;
/**
* 失败重试次数
*/
private int executorFailRetryCount;
/**
* LUE类型 com.xxl.job.core.glue.GlueTypeEnum
*/
private String glueType;
/**
* GLUE源代码
*/
private String glueSource;
/**
* GLUE备注
*/
private String glueRemark;
/**
* GLUE更新时间
*/
private Date glueUpdatetime;
/**
* 子任务ID,多个逗号分隔
*/
private String childJobId;
/**
* 调度状态:0-停止,1-运行
*/
private int triggerStatus;
/**
* 上次调度时间
*/
private long triggerLastTime;
/**
* 下次调度时间
*/
private long triggerNextTime;
}
封装返回类型
public interface IResultCode extends Serializable {
String getMessage();
int getCode();
}
public enum ResultCode implements IResultCode {
SUCCESS(200, "操作成功"),
FAILURE(400, "业务异常"),
UN_AUTHORIZED(401, "请求未授权"),
NOT_FOUND(404, "404 没找到请求"),
MSG_NOT_READABLE(400, "消息不能读取"),
METHOD_NOT_SUPPORTED(405, "不支持当前请求方法"),
MEDIA_TYPE_NOT_SUPPORTED(415, "不支持当前媒体类型"),
REQ_REJECT(403, "请求被拒绝"),
INTERNAL_SERVER_ERROR(500, "服务器异常"),
PARAM_MISS(400, "缺少必要的请求参数"),
PARAM_TYPE_ERROR(400, "请求参数类型错误"),
PARAM_BIND_ERROR(400, "请求参数绑定错误"),
PARAM_VALID_ERROR(400, "参数校验失败"),
PWD_NOT_RESET(600, "参数校验失败"),
BUSINESS_ERROR(-1, "业务异常"),
TYPE_CONVERT_ERROR(700, "类型转换异常"),
TYPE_ERROR(800, "非法关键字异常"),
REMOTE_SQL_ERROR(900, "远程sql执行异常");
final int code;
final String message;
@Override
public int getCode() {
return this.code;
}
@Override
public String getMessage() {
return this.message;
}
private ResultCode(final int code, final String message) {
this.code = code;
this.message = message;
}
}
public class R<T> implements Serializable {
private static final Logger log = LoggerFactory.getLogger(R.class);
private static final long serialVersionUID = 1L;
private int code;
private boolean success;
private String message;
@JsonIgnore
private String messageCode;
private String timestamp;
private T data;
@JsonIgnore
private static Props props = new Props();
public static <T> R<T> data(int code, T data, String msg) {
return new R(code, data, data == null ? "暂无承载数据" : msg);
}
public static <T> R<T> data(T data, String msg) {
return data(200, data, msg);
}
public static <T> R<T> data(T data) {
return data(data, "操作成功");
}
private R(IResultCode resultCode, T data) {
this(resultCode, data, resultCode.getMessage());
}
private R(IResultCode resultCode, T data, String message) {
this(resultCode.getCode(), data, message);
}
private R(int code, T data, String message) {
this.code = code;
this.data = data;
this.message = message;
this.timestamp = String.valueOf(System.currentTimeMillis());
this.success = ResultCode.SUCCESS.code == code;
}
private R(int code, T data, String messageCode, String message) {
this.code = code;
this.data = data;
this.timestamp = String.valueOf(System.currentTimeMillis());
this.success = ResultCode.SUCCESS.code == code;
if (Strings.isNotBlank(message)) {
this.message = message;
} else if (Strings.isNotBlank(messageCode)) {
String propVal = props.getProperty(messageCode);
this.message = Strings.isBlank(propVal) ? messageCode : propVal;
}
}
}
Q.E.D.