@@ -0,0 +1,25 @@ | |||||
/target/ | |||||
!.mvn/wrapper/maven-wrapper.jar | |||||
### STS ### | |||||
.apt_generated | |||||
.classpath | |||||
.factorypath | |||||
.project | |||||
.settings | |||||
.springBeans | |||||
.sts4-cache | |||||
### IntelliJ IDEA ### | |||||
.idea | |||||
*.iws | |||||
*.iml | |||||
*.ipr | |||||
### NetBeans ### | |||||
/nbproject/private/ | |||||
/build/ | |||||
/nbbuild/ | |||||
/dist/ | |||||
/nbdist/ | |||||
/.nb-gradle/ |
@@ -20,6 +20,7 @@ | |||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> | <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> | ||||
<java.version>1.8</java.version> | <java.version>1.8</java.version> | ||||
<xxl-job.version>2.1.0</xxl-job.version> | |||||
</properties> | </properties> | ||||
<dependencies> | <dependencies> | ||||
@@ -29,10 +30,23 @@ | |||||
</dependency> | </dependency> | ||||
<dependency> | <dependency> | ||||
<groupId>org.springframework.boot</groupId> | |||||
<artifactId>spring-boot-configuration-processor</artifactId> | |||||
<optional>true</optional> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>mysql</groupId> | <groupId>mysql</groupId> | ||||
<artifactId>mysql-connector-java</artifactId> | <artifactId>mysql-connector-java</artifactId> | ||||
</dependency> | </dependency> | ||||
<!-- xxl-job-core --> | |||||
<dependency> | |||||
<groupId>com.xuxueli</groupId> | |||||
<artifactId>xxl-job-core</artifactId> | |||||
<version>${xxl-job.version}</version> | |||||
</dependency> | |||||
<dependency> | <dependency> | ||||
<groupId>org.springframework.boot</groupId> | <groupId>org.springframework.boot</groupId> | ||||
<artifactId>spring-boot-starter-test</artifactId> | <artifactId>spring-boot-starter-test</artifactId> | ||||
@@ -0,0 +1,20 @@ | |||||
package com.xkcoding.task.xxl.job; | |||||
import org.springframework.boot.SpringApplication; | |||||
import org.springframework.boot.autoconfigure.SpringBootApplication; | |||||
/** | |||||
* <p> | |||||
* 启动器 | |||||
* </p> | |||||
* | |||||
* @author yangkai.shen | |||||
* @date Created in 2019-08-07 10:13 | |||||
*/ | |||||
@SpringBootApplication | |||||
public class SpringBootDemoTaskXxlJobApplication { | |||||
public static void main(String[] args) { | |||||
SpringApplication.run(SpringBootDemoTaskXxlJobApplication.class, args); | |||||
} | |||||
} |
@@ -0,0 +1,42 @@ | |||||
package com.xkcoding.task.xxl.job.config; | |||||
import com.xkcoding.task.xxl.job.config.props.XxlJobProps; | |||||
import com.xxl.job.core.executor.impl.XxlJobSpringExecutor; | |||||
import lombok.RequiredArgsConstructor; | |||||
import lombok.extern.slf4j.Slf4j; | |||||
import org.springframework.beans.factory.annotation.Autowired; | |||||
import org.springframework.boot.context.properties.EnableConfigurationProperties; | |||||
import org.springframework.context.annotation.Bean; | |||||
import org.springframework.context.annotation.Configuration; | |||||
/** | |||||
* <p> | |||||
* xxl-job 自动装配 | |||||
* </p> | |||||
* | |||||
* @author yangkai.shen | |||||
* @date Created in 2019-08-07 10:20 | |||||
*/ | |||||
@Slf4j | |||||
@Configuration | |||||
@EnableConfigurationProperties(XxlJobProps.class) | |||||
@RequiredArgsConstructor(onConstructor_ = @Autowired) | |||||
public class XxlJobConfig { | |||||
private final XxlJobProps xxlJobProps; | |||||
@Bean(initMethod = "start", destroyMethod = "destroy") | |||||
public XxlJobSpringExecutor xxlJobExecutor() { | |||||
log.info(">>>>>>>>>>> xxl-job config init."); | |||||
XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor(); | |||||
xxlJobSpringExecutor.setAdminAddresses(xxlJobProps.getAdmin().getAddress()); | |||||
xxlJobSpringExecutor.setAccessToken(xxlJobProps.getAccessToken()); | |||||
xxlJobSpringExecutor.setAppName(xxlJobProps.getExecutor().getAppName()); | |||||
xxlJobSpringExecutor.setIp(xxlJobProps.getExecutor().getIp()); | |||||
xxlJobSpringExecutor.setPort(xxlJobProps.getExecutor().getPort()); | |||||
xxlJobSpringExecutor.setLogPath(xxlJobProps.getExecutor().getLogPath()); | |||||
xxlJobSpringExecutor.setLogRetentionDays(xxlJobProps.getExecutor().getLogRetentionDays()); | |||||
return xxlJobSpringExecutor; | |||||
} | |||||
} |
@@ -0,0 +1,67 @@ | |||||
package com.xkcoding.task.xxl.job.config.props; | |||||
import lombok.Data; | |||||
import org.springframework.boot.context.properties.ConfigurationProperties; | |||||
/** | |||||
* <p> | |||||
* xxl-job 配置 | |||||
* </p> | |||||
* | |||||
* @author yangkai.shen | |||||
* @date Created in 2019-08-07 10:25 | |||||
*/ | |||||
@Data | |||||
@ConfigurationProperties(prefix = "xxl.job") | |||||
public class XxlJobProps { | |||||
/** | |||||
* 调度中心配置 | |||||
*/ | |||||
private XxlJobAdminProps admin; | |||||
/** | |||||
* 执行器配置 | |||||
*/ | |||||
private XxlJobExecutorProps executor; | |||||
/** | |||||
* 与调度中心交互的accessToken | |||||
*/ | |||||
private String accessToken; | |||||
@Data | |||||
public static class XxlJobAdminProps { | |||||
/** | |||||
* 调度中心地址 | |||||
*/ | |||||
private String address; | |||||
} | |||||
@Data | |||||
public static class XxlJobExecutorProps { | |||||
/** | |||||
* 执行器名称 | |||||
*/ | |||||
private String appName; | |||||
/** | |||||
* 执行器 IP | |||||
*/ | |||||
private String ip; | |||||
/** | |||||
* 执行器端口 | |||||
*/ | |||||
private int port; | |||||
/** | |||||
* 执行器日志 | |||||
*/ | |||||
private String logPath; | |||||
/** | |||||
* 执行器日志保留天数,-1 | |||||
*/ | |||||
private int logRetentionDays; | |||||
} | |||||
} |
@@ -0,0 +1,138 @@ | |||||
package com.xkcoding.task.xxl.job.controller; | |||||
import cn.hutool.http.HttpResponse; | |||||
import cn.hutool.http.HttpUtil; | |||||
import cn.hutool.json.JSONUtil; | |||||
import com.google.common.collect.Maps; | |||||
import com.xxl.job.core.enums.ExecutorBlockStrategyEnum; | |||||
import com.xxl.job.core.glue.GlueTypeEnum; | |||||
import lombok.RequiredArgsConstructor; | |||||
import lombok.extern.slf4j.Slf4j; | |||||
import org.springframework.beans.factory.annotation.Autowired; | |||||
import org.springframework.web.bind.annotation.GetMapping; | |||||
import org.springframework.web.bind.annotation.RequestMapping; | |||||
import org.springframework.web.bind.annotation.RestController; | |||||
import java.util.Map; | |||||
/** | |||||
* <p> | |||||
* 手动操作 xxl-job | |||||
* </p> | |||||
* | |||||
* @author yangkai.shen | |||||
* @date Created in 2019-08-07 14:58 | |||||
*/ | |||||
@Slf4j | |||||
@RestController | |||||
@RequestMapping("/xxl-job") | |||||
@RequiredArgsConstructor(onConstructor_ = @Autowired) | |||||
public class ManualOperateController { | |||||
private final static String baseUri = "http://127.0.0.1:18080/xxl-job-admin"; | |||||
private final static String JOB_INFO_URI = "/jobinfo"; | |||||
private final static String JOB_GROUP_URI = "/jobgroup"; | |||||
/** | |||||
* 任务组列表,xxl-job叫做触发器列表 | |||||
*/ | |||||
@GetMapping("/group") | |||||
public String xxlJobGroup() { | |||||
HttpResponse execute = HttpUtil.createGet(baseUri + JOB_GROUP_URI + "/list").execute(); | |||||
log.info("【execute】= {}", execute); | |||||
return execute.body(); | |||||
} | |||||
/** | |||||
* 分页任务列表 | |||||
* @param page 当前页,第一页 -> 0 | |||||
* @param size 每页条数,默认10 | |||||
* @return 分页任务列表 | |||||
*/ | |||||
@GetMapping("/list") | |||||
public String xxlJobList(Integer page, Integer size) { | |||||
Map<String, Object> jobInfo = Maps.newHashMap(); | |||||
jobInfo.put("start", page != null ? page : 0); | |||||
jobInfo.put("length", size != null ? size : 10); | |||||
jobInfo.put("jobGroup", 2); | |||||
jobInfo.put("triggerStatus", -1); | |||||
HttpResponse execute = HttpUtil.createGet(baseUri + JOB_INFO_URI + "/pageList").form(jobInfo).execute(); | |||||
log.info("【execute】= {}", execute); | |||||
return execute.body(); | |||||
} | |||||
/** | |||||
* 测试手动保存任务 | |||||
*/ | |||||
@GetMapping("/add") | |||||
public String xxlJobAdd() { | |||||
Map<String, Object> jobInfo = Maps.newHashMap(); | |||||
jobInfo.put("jobGroup", 2); | |||||
jobInfo.put("jobCron", "0 0/1 * * * ? *"); | |||||
jobInfo.put("jobDesc", "手动添加的任务"); | |||||
jobInfo.put("author", "admin"); | |||||
jobInfo.put("executorRouteStrategy", "ROUND"); | |||||
jobInfo.put("executorHandler", "demoTask"); | |||||
jobInfo.put("executorParam", "手动添加的任务的参数"); | |||||
jobInfo.put("executorBlockStrategy", ExecutorBlockStrategyEnum.SERIAL_EXECUTION); | |||||
jobInfo.put("glueType", GlueTypeEnum.BEAN); | |||||
HttpResponse execute = HttpUtil.createGet(baseUri + JOB_INFO_URI + "/add").form(jobInfo).execute(); | |||||
log.info("【execute】= {}", execute); | |||||
return execute.body(); | |||||
} | |||||
/** | |||||
* 测试手动触发一次任务 | |||||
*/ | |||||
@GetMapping("/trigger") | |||||
public String xxlJobTrigger() { | |||||
Map<String, Object> jobInfo = Maps.newHashMap(); | |||||
jobInfo.put("id", 4); | |||||
jobInfo.put("executorParam", JSONUtil.toJsonStr(jobInfo)); | |||||
HttpResponse execute = HttpUtil.createGet(baseUri + JOB_INFO_URI + "/trigger").form(jobInfo).execute(); | |||||
log.info("【execute】= {}", execute); | |||||
return execute.body(); | |||||
} | |||||
/** | |||||
* 测试手动删除任务 | |||||
*/ | |||||
@GetMapping("/remove") | |||||
public String xxlJobRemove() { | |||||
Map<String, Object> jobInfo = Maps.newHashMap(); | |||||
jobInfo.put("id", 4); | |||||
HttpResponse execute = HttpUtil.createGet(baseUri + JOB_INFO_URI + "/remove").form(jobInfo).execute(); | |||||
log.info("【execute】= {}", execute); | |||||
return execute.body(); | |||||
} | |||||
/** | |||||
* 测试手动停止任务 | |||||
*/ | |||||
@GetMapping("/stop") | |||||
public String xxlJobStop() { | |||||
Map<String, Object> jobInfo = Maps.newHashMap(); | |||||
jobInfo.put("id", 4); | |||||
HttpResponse execute = HttpUtil.createGet(baseUri + JOB_INFO_URI + "/stop").form(jobInfo).execute(); | |||||
log.info("【execute】= {}", execute); | |||||
return execute.body(); | |||||
} | |||||
/** | |||||
* 测试手动停止任务 | |||||
*/ | |||||
@GetMapping("/start") | |||||
public String xxlJobStart() { | |||||
Map<String, Object> jobInfo = Maps.newHashMap(); | |||||
jobInfo.put("id", 4); | |||||
HttpResponse execute = HttpUtil.createGet(baseUri + JOB_INFO_URI + "/start").form(jobInfo).execute(); | |||||
log.info("【execute】= {}", execute); | |||||
return execute.body(); | |||||
} | |||||
} |
@@ -0,0 +1,39 @@ | |||||
package com.xkcoding.task.xxl.job.task; | |||||
import cn.hutool.core.date.DateUtil; | |||||
import cn.hutool.core.util.RandomUtil; | |||||
import com.xxl.job.core.biz.model.ReturnT; | |||||
import com.xxl.job.core.handler.IJobHandler; | |||||
import com.xxl.job.core.handler.annotation.JobHandler; | |||||
import com.xxl.job.core.log.XxlJobLogger; | |||||
import lombok.extern.slf4j.Slf4j; | |||||
import org.springframework.stereotype.Component; | |||||
/** | |||||
* <p> | |||||
* 测试定时任务 | |||||
* </p> | |||||
* | |||||
* @author yangkai.shen | |||||
* @date Created in 2019-08-07 10:15 | |||||
*/ | |||||
@Slf4j | |||||
@Component | |||||
@JobHandler("demoTask") | |||||
public class DemoTask extends IJobHandler { | |||||
/** | |||||
* execute handler, invoked when executor receives a scheduling request | |||||
* | |||||
* @param param 定时任务参数 | |||||
* @return 执行状态 | |||||
* @throws Exception 任务异常 | |||||
*/ | |||||
@Override | |||||
public ReturnT<String> execute(String param) throws Exception { | |||||
// 可以动态获取传递过来的参数,根据参数不同,当前调度的任务不同 | |||||
log.info("【param】= {}", param); | |||||
XxlJobLogger.log("demo task run at : {}", DateUtil.now()); | |||||
return RandomUtil.randomInt(1, 11) % 2 == 0 ? SUCCESS : FAIL; | |||||
} | |||||
} |
@@ -1,4 +1,22 @@ | |||||
server: | server: | ||||
port: 8080 | port: 8080 | ||||
servlet: | servlet: | ||||
context-path: /demo | |||||
context-path: /demo | |||||
xxl: | |||||
job: | |||||
# 执行器通讯TOKEN [选填]:非空时启用; | |||||
access-token: | |||||
admin: | |||||
# 调度中心部署跟地址 [选填]:如调度中心集群部署存在多个地址则用逗号分隔。执行器将会使用该地址进行"执行器心跳注册"和"任务结果回调";为空则关闭自动注册; | |||||
address: http://localhost:18080/xxl-job-admin | |||||
executor: | |||||
# 执行器AppName [选填]:执行器心跳注册分组依据;为空则关闭自动注册 | |||||
app-name: spring-boot-demo-task-xxl-job-executor | |||||
# 执行器IP [选填]:默认为空表示自动获取IP,多网卡时可手动设置指定IP,该IP不会绑定Host仅作为通讯实用;地址信息用于 "执行器注册" 和 "调度中心请求并触发任务"; | |||||
ip: | |||||
# 执行器端口号 [选填]:小于等于0则自动获取;默认端口为9999,单机部署多个执行器时,注意要配置不同执行器端口; | |||||
port: 9999 | |||||
# 执行器运行日志文件存储磁盘路径 [选填] :需要对该路径拥有读写权限;为空则使用默认路径; | |||||
log-path: logs/spring-boot-demo-task-xxl-job/task-log | |||||
# 执行器日志保存天数 [选填] :值大于3时生效,启用执行器Log文件定期清理功能,否则不生效; | |||||
log-retention-days: -1 |