diff --git a/austin-cron/pom.xml b/austin-cron/pom.xml
new file mode 100644
index 0000000..a45cc07
--- /dev/null
+++ b/austin-cron/pom.xml
@@ -0,0 +1,30 @@
+
+
+
+ austin
+ com.java3y.austin
+ 0.0.1-SNAPSHOT
+
+ 4.0.0
+
+ austin-cron
+
+ 8
+ 8
+
+
+
+
+ com.java3y.austin
+ austin-support
+ 0.0.1-SNAPSHOT
+
+
+ com.xuxueli
+ xxl-job-core
+
+
+
+
\ No newline at end of file
diff --git a/austin-cron/src/main/java/com/java3y/austin/config/XxlJobConfig.java b/austin-cron/src/main/java/com/java3y/austin/config/XxlJobConfig.java
new file mode 100644
index 0000000..df1aa11
--- /dev/null
+++ b/austin-cron/src/main/java/com/java3y/austin/config/XxlJobConfig.java
@@ -0,0 +1,43 @@
+package com.java3y.austin.config;
+
+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;
+
+@Slf4j
+@Configuration
+public class XxlJobConfig {
+
+ @Value("${xxl.job.admin.addresses}")
+ private String adminAddresses;
+ @Value("${xxl.job.executor.appname}")
+ private String appName;
+ @Value("${xxl.job.executor.ip}")
+ private String ip;
+ @Value("${xxl.job.executor.port}")
+ private int port;
+ @Value("${xxl.job.accessToken}")
+ private String accessToken;
+ @Value("${xxl.job.executor.logpath}")
+ private String logPath;
+ @Value("${xxl.job.executor.logretentiondays}")
+ private int logRetentionDays;
+
+ @Bean
+ public XxlJobSpringExecutor xxlJobExecutor() {
+ // 创建 XxlJobSpringExecutor 执行器
+ XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
+ xxlJobSpringExecutor.setAdminAddresses(adminAddresses);
+ xxlJobSpringExecutor.setAppname(appName);
+ xxlJobSpringExecutor.setIp(ip);
+ xxlJobSpringExecutor.setPort(port);
+ xxlJobSpringExecutor.setAccessToken(accessToken);
+ xxlJobSpringExecutor.setLogPath(logPath);
+ xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);
+ // 返回
+ return xxlJobSpringExecutor;
+ }
+
+}
diff --git a/austin-cron/src/main/java/com/java3y/austin/constants/XxlJobConstant.java b/austin-cron/src/main/java/com/java3y/austin/constants/XxlJobConstant.java
new file mode 100644
index 0000000..8c98cfc
--- /dev/null
+++ b/austin-cron/src/main/java/com/java3y/austin/constants/XxlJobConstant.java
@@ -0,0 +1,36 @@
+package com.java3y.austin.constants;
+
+
+/**
+ * xxl-job常量信息
+ *
+ * @author 3y
+ */
+public class XxlJobConstant {
+
+ /**
+ * 接口路径
+ */
+ public static final String LOGIN_URL = "/xxl-job-admin/login";
+ public static final String INSERT_URL = "/jobinfo/add";
+ public static final String UPDATE_URL = "/jobinfo/update";
+ public static final String DELETE_URL = "/jobinfo/remove";
+ public static final String RUN_URL = "/jobinfo/start";
+ public static final String STOP_URL = "/jobinfo/stop";
+
+ /**
+ * 执行器名称
+ */
+ public static final String HANDLER_NAME = "austinJobHandler";
+
+ /**
+ * 超时时间
+ */
+ public static final Integer TIME_OUT = 120;
+
+ /**
+ * 失败重试次数
+ */
+ public static final Integer RETRY_COUNT = 2;
+
+}
diff --git a/austin-cron/src/main/java/com/java3y/austin/entity/XxlJobInfo.java b/austin-cron/src/main/java/com/java3y/austin/entity/XxlJobInfo.java
new file mode 100644
index 0000000..95e1ef9
--- /dev/null
+++ b/austin-cron/src/main/java/com/java3y/austin/entity/XxlJobInfo.java
@@ -0,0 +1,57 @@
+package com.java3y.austin.entity;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.util.Date;
+
+
+/**
+ * xxl 任务信息 配置
+ */
+@Data
+@Accessors(chain = true)
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+public class XxlJobInfo implements Serializable {
+
+ private Integer id; // 主键ID
+
+ private int jobGroup; // 执行器主键ID
+ 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; // 执行器路由策略
+ 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.GlueTypeEnum
+ private 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; // 下次调度时间
+
+}
diff --git a/austin-cron/src/main/java/com/java3y/austin/enums/ExecutorBlockStrategyEnum.java b/austin-cron/src/main/java/com/java3y/austin/enums/ExecutorBlockStrategyEnum.java
new file mode 100644
index 0000000..fe4dea5
--- /dev/null
+++ b/austin-cron/src/main/java/com/java3y/austin/enums/ExecutorBlockStrategyEnum.java
@@ -0,0 +1,26 @@
+package com.java3y.austin.enums;
+
+/**
+ * 执行阻塞队列
+ * @author 3y
+ */
+public enum ExecutorBlockStrategyEnum {
+ /**
+ * 单机串行
+ */
+ SERIAL_EXECUTION,
+
+ /**
+ * 丢弃后续调度
+ */
+ DISCARD_LATER,
+
+ /**
+ * 覆盖之前调度
+ */
+ COVER_EARLY;
+
+ ExecutorBlockStrategyEnum() {
+
+ }
+}
diff --git a/austin-cron/src/main/java/com/java3y/austin/enums/ExecutorRouteStrategyEnum.java b/austin-cron/src/main/java/com/java3y/austin/enums/ExecutorRouteStrategyEnum.java
new file mode 100644
index 0000000..d1e702b
--- /dev/null
+++ b/austin-cron/src/main/java/com/java3y/austin/enums/ExecutorRouteStrategyEnum.java
@@ -0,0 +1,23 @@
+package com.java3y.austin.enums;
+
+
+/**
+ * 路由策略
+ * @author 3y
+ */
+public enum ExecutorRouteStrategyEnum {
+
+ FIRST,
+ LAST,
+ ROUND,
+ RANDOM,
+ CONSISTENT_HASH,
+ LEAST_FREQUENTLY_USED,
+ LEAST_RECENTLY_USED,
+ FAILOVER,
+ BUSYOVER,
+ SHARDING_BROADCAST;
+
+ ExecutorRouteStrategyEnum() {
+ }
+}
diff --git a/austin-cron/src/main/java/com/java3y/austin/enums/GlueTypeEnum.java b/austin-cron/src/main/java/com/java3y/austin/enums/GlueTypeEnum.java
new file mode 100644
index 0000000..14fcdca
--- /dev/null
+++ b/austin-cron/src/main/java/com/java3y/austin/enums/GlueTypeEnum.java
@@ -0,0 +1,19 @@
+package com.java3y.austin.enums;
+
+/**
+ * GlueTyp 类型(默认BEAN)
+ * @author 3y
+ */
+public enum GlueTypeEnum {
+
+ BEAN,
+ GLUE_GROOVY,
+ GLUE_SHELL,
+ GLUE_PYTHON,
+ GLUE_PHP,
+ GLUE_NODEJS,
+ GLUE_POWERSHELL;
+
+ GlueTypeEnum() {
+ }
+}
diff --git a/austin-cron/src/main/java/com/java3y/austin/enums/MisfireStrategyEnum.java b/austin-cron/src/main/java/com/java3y/austin/enums/MisfireStrategyEnum.java
new file mode 100644
index 0000000..b5fa6ae
--- /dev/null
+++ b/austin-cron/src/main/java/com/java3y/austin/enums/MisfireStrategyEnum.java
@@ -0,0 +1,21 @@
+package com.java3y.austin.enums;
+
+/**
+ * 调度过期策略
+ * @author 3y
+ */
+public enum MisfireStrategyEnum {
+
+ /**
+ * do nothing
+ */
+ DO_NOTHING,
+
+ /**
+ * fire once now
+ */
+ FIRE_ONCE_NOW;
+
+ MisfireStrategyEnum() {
+ }
+}
diff --git a/austin-cron/src/main/java/com/java3y/austin/enums/ScheduleTypeEnum.java b/austin-cron/src/main/java/com/java3y/austin/enums/ScheduleTypeEnum.java
new file mode 100644
index 0000000..7fe2e03
--- /dev/null
+++ b/austin-cron/src/main/java/com/java3y/austin/enums/ScheduleTypeEnum.java
@@ -0,0 +1,23 @@
+package com.java3y.austin.enums;
+
+/**
+ * 调度类型
+ * @author 3y
+ */
+public enum ScheduleTypeEnum {
+
+ NONE,
+ /**
+ * schedule by cron
+ */
+ CRON,
+
+ /**
+ * schedule by fixed rate (in seconds)
+ */
+ FIX_RATE;
+
+ ScheduleTypeEnum() {
+ }
+
+}
diff --git a/austin-cron/src/main/java/com/java3y/austin/handler/CronTaskHandler.java b/austin-cron/src/main/java/com/java3y/austin/handler/CronTaskHandler.java
new file mode 100644
index 0000000..ff537a5
--- /dev/null
+++ b/austin-cron/src/main/java/com/java3y/austin/handler/CronTaskHandler.java
@@ -0,0 +1,19 @@
+package com.java3y.austin.handler;
+
+import com.xxl.job.core.handler.annotation.XxlJob;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+@Service
+@Slf4j
+public class CronTaskHandler {
+
+ /**
+ * 简单任务
+ */
+ @XxlJob("austinJobHandler")
+ public void execute() {
+ log.info("XXL-JOB, Hello World.");
+ }
+
+}
diff --git a/austin-cron/src/main/java/com/java3y/austin/service/CronTaskService.java b/austin-cron/src/main/java/com/java3y/austin/service/CronTaskService.java
new file mode 100644
index 0000000..01ccfc6
--- /dev/null
+++ b/austin-cron/src/main/java/com/java3y/austin/service/CronTaskService.java
@@ -0,0 +1,42 @@
+package com.java3y.austin.service;
+
+import com.java3y.austin.entity.XxlJobInfo;
+import com.java3y.austin.vo.BasicResultVO;
+
+/**
+ * 定时任务服务
+ */
+public interface CronTaskService {
+
+
+ /**
+ * 新增/修改 定时任务
+ *
+ * @return 新增时返回任务Id,修改时无返回
+ */
+ BasicResultVO saveCronTask(XxlJobInfo xxlJobInfo);
+
+ /**
+ * 删除定时任务
+ *
+ * @param taskId
+ */
+ BasicResultVO deleteCronTask(Integer taskId);
+
+ /**
+ * 启动定时任务
+ *
+ * @param taskId
+ */
+ BasicResultVO startCronTask(Integer taskId);
+
+
+ /**
+ * 暂停定时任务
+ *
+ * @param taskId
+ */
+ BasicResultVO stopCronTask(Integer taskId);
+
+
+}
diff --git a/austin-cron/src/main/java/com/java3y/austin/service/impl/CronTaskServiceImpl.java b/austin-cron/src/main/java/com/java3y/austin/service/impl/CronTaskServiceImpl.java
new file mode 100644
index 0000000..c1fd646
--- /dev/null
+++ b/austin-cron/src/main/java/com/java3y/austin/service/impl/CronTaskServiceImpl.java
@@ -0,0 +1,139 @@
+package com.java3y.austin.service.impl;
+
+import cn.hutool.http.HttpRequest;
+import cn.hutool.http.HttpResponse;
+import com.alibaba.fastjson.JSON;
+import com.java3y.austin.constants.XxlJobConstant;
+import com.java3y.austin.entity.XxlJobInfo;
+import com.java3y.austin.enums.RespStatusEnum;
+import com.java3y.austin.service.CronTaskService;
+import com.java3y.austin.vo.BasicResultVO;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+import java.net.HttpCookie;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author 3y
+ */
+@Slf4j
+@Service
+public class CronTaskServiceImpl implements CronTaskService {
+
+ @Value("${xxl.job.admin.username}")
+ private String xxlUserName;
+
+ @Value("${xxl.job.admin.password}")
+ private String xxlPassword;
+
+ @Value("${xxl.job.admin.addresses}")
+ private String xxlAddresses;
+
+
+ @Override
+ public BasicResultVO saveCronTask(XxlJobInfo xxlJobInfo) {
+ Map params = JSON.parseObject(JSON.toJSONString(xxlJobInfo), Map.class);
+
+ String path;
+ if (xxlJobInfo.getId() != null) {
+ path = xxlAddresses + XxlJobConstant.INSERT_URL;
+ } else {
+ path = xxlAddresses + XxlJobConstant.UPDATE_URL;
+ }
+ //XxlJobInfo.builder().jobGroup(1).jobDesc()
+// Map paramMap = new HashMap<>();
+// paramMap.put("jobGroup", 1);
+// paramMap.put("jobDesc", "这是测试任务");
+// paramMap.put("executorRouteStrategy", "FIRST");
+// paramMap.put("cronGen_display", "* * * * * ? *");
+// paramMap.put("scheduleConf", "* * * * * ? *");
+// paramMap.put("year", "2");
+// paramMap.put("misfireStrategy", "DO_NOTHING");
+// paramMap.put("glueType", "BEAN");
+// paramMap.put("schedule_conf_CRON", "* * * * * ? *");
+// paramMap.put("executorHandler", "messageJob"); // 此处hander需提前在项目中定义
+// paramMap.put("executorBlockStrategy", "SERIAL_EXECUTION");
+// paramMap.put("executorTimeout", 0);
+// paramMap.put("executorFailRetryCount", 1);
+// paramMap.put("author", "admin");
+// paramMap.put("glueRemark", "GLUE代码初始化");
+// paramMap.put("triggerStatus", 1);
+// paramMap.put("scheduleType", "CRON");
+
+ HttpResponse response = HttpRequest.post(path).form(params).cookie(getCookie()).execute();
+ if (!response.isOk()) {
+ log.error("TaskService#saveTask fail:{}", JSON.toJSONString(response.body()));
+ return BasicResultVO.fail(RespStatusEnum.SERVICE_ERROR, JSON.toJSONString(response.body()));
+ }
+ return BasicResultVO.success(JSON.toJSONString(response.body()));
+ }
+
+ @Override
+ public BasicResultVO deleteCronTask(Integer taskId) {
+ HashMap params = new HashMap<>();
+ params.put("id", taskId);
+ String path = xxlAddresses + XxlJobConstant.DELETE_URL;
+ HttpResponse response = HttpRequest.post(path).form(params).cookie(getCookie()).execute();
+ if (!response.isOk()) {
+ log.error("TaskService#deleteCronTask fail:{}", JSON.toJSONString(response.body()));
+ return BasicResultVO.fail(RespStatusEnum.SERVICE_ERROR, JSON.toJSONString(response.body()));
+ }
+ return BasicResultVO.success();
+ }
+
+ @Override
+ public BasicResultVO startCronTask(Integer taskId) {
+ HashMap params = new HashMap<>();
+ params.put("id", taskId);
+ String path = xxlAddresses + XxlJobConstant.RUN_URL;
+ HttpResponse response = HttpRequest.post(path).form(params).cookie(getCookie()).execute();
+ if (!response.isOk()) {
+ log.error("TaskService#startCronTask fail:{}", JSON.toJSONString(response.body()));
+ return BasicResultVO.fail(RespStatusEnum.SERVICE_ERROR, JSON.toJSONString(response.body()));
+ }
+ return BasicResultVO.success();
+ }
+
+ @Override
+ public BasicResultVO stopCronTask(Integer taskId) {
+ HashMap params = new HashMap<>();
+ params.put("id", taskId);
+
+ String path = xxlAddresses + XxlJobConstant.STOP_URL;
+ HttpResponse response = HttpRequest.post(path).form(params).cookie(getCookie()).execute();
+ if (!response.isOk()) {
+ log.error("TaskService#stopCronTask fail:{}", JSON.parseObject(response.body()));
+ return BasicResultVO.fail(RespStatusEnum.SERVICE_ERROR, JSON.toJSONString(response.body()));
+ }
+ return BasicResultVO.success();
+ }
+
+ /**
+ * 获取xxl cookie
+ *
+ * @return String
+ */
+ private String getCookie() {
+ String path = xxlAddresses + XxlJobConstant.LOGIN_URL;
+ Map hashMap = new HashMap<>();
+ hashMap.put("userName", xxlUserName);
+ hashMap.put("password", xxlPassword);
+ log.info("TaskService#getCookie params:{}", hashMap);
+
+ HttpResponse response = HttpRequest.post(path).form(hashMap).execute();
+ if (response.isOk()) {
+ List cookies = response.getCookies();
+ StringBuilder sb = new StringBuilder();
+ for (HttpCookie cookie : cookies) {
+ sb.append(cookie.toString());
+ }
+ return sb.toString();
+ }
+ log.error("TaskService#getCookie fail:{}", JSON.parseObject(response.body()));
+ return null;
+ }
+}
diff --git a/austin-cron/src/main/java/com/java3y/austin/utils/XxlJobUtils.java b/austin-cron/src/main/java/com/java3y/austin/utils/XxlJobUtils.java
new file mode 100644
index 0000000..7fe937b
--- /dev/null
+++ b/austin-cron/src/main/java/com/java3y/austin/utils/XxlJobUtils.java
@@ -0,0 +1,58 @@
+package com.java3y.austin.utils;
+
+import cn.hutool.core.util.StrUtil;
+import com.alibaba.fastjson.JSON;
+import com.java3y.austin.constant.AustinConstant;
+import com.java3y.austin.constants.XxlJobConstant;
+import com.java3y.austin.domain.MessageTemplate;
+import com.java3y.austin.entity.XxlJobInfo;
+import com.java3y.austin.enums.*;
+
+/**
+ * xxlJob工具类
+ *
+ * @author 3y
+ */
+public class XxlJobUtils {
+
+ /**
+ * 构建xxlJobInfo信息
+ *
+ * @param messageTemplate
+ * @param triggerStatus 是否启动定时任务
+ * @return
+ */
+ public static XxlJobInfo buildXxlJobInfo(MessageTemplate messageTemplate) {
+
+ // 判断是否为cron表达式
+ String scheduleConf = StrUtil.EMPTY;
+ String scheduleType = ScheduleTypeEnum.NONE.name();
+ if (!messageTemplate.getExpectPushTime().equals(String.valueOf(AustinConstant.FALSE))) {
+ scheduleType = ScheduleTypeEnum.CRON.name();
+ scheduleConf = messageTemplate.getExpectPushTime();
+ }
+
+ XxlJobInfo xxlJobInfo = XxlJobInfo.builder().jobGroup(1).jobDesc(messageTemplate.getName())
+ .author(messageTemplate.getCreator())
+ .scheduleConf(scheduleConf)
+ .scheduleType(scheduleType)
+ .misfireStrategy(MisfireStrategyEnum.DO_NOTHING.name())
+ .executorBlockStrategy(ExecutorRouteStrategyEnum.CONSISTENT_HASH.name())
+ .executorHandler(XxlJobConstant.HANDLER_NAME)
+ .executorParam(JSON.toJSONString(messageTemplate))
+ .executorBlockStrategy(ExecutorBlockStrategyEnum.SERIAL_EXECUTION.name())
+ .executorTimeout(XxlJobConstant.TIME_OUT)
+ .executorFailRetryCount(XxlJobConstant.RETRY_COUNT)
+ .glueType(GlueTypeEnum.BEAN.name())
+ .triggerStatus(AustinConstant.FALSE)
+ .glueRemark(StrUtil.EMPTY)
+ .glueSource(StrUtil.EMPTY)
+ .alarmEmail(StrUtil.EMPTY)
+ .childJobId(StrUtil.EMPTY).build();
+
+ if (messageTemplate.getCronTaskId() != null) {
+ xxlJobInfo.setId(messageTemplate.getCronTaskId());
+ }
+ return xxlJobInfo;
+ }
+}
diff --git a/austin-support/src/main/java/com/java3y/austin/domain/MessageTemplate.java b/austin-support/src/main/java/com/java3y/austin/domain/MessageTemplate.java
index beabaf2..cae21f6 100644
--- a/austin-support/src/main/java/com/java3y/austin/domain/MessageTemplate.java
+++ b/austin-support/src/main/java/com/java3y/austin/domain/MessageTemplate.java
@@ -50,6 +50,12 @@ public class MessageTemplate implements Serializable {
*/
private Integer msgStatus;
+ /**
+ * 定时任务Id(由xxl-job返回)
+ */
+ private Integer cronTaskId;
+
+
/**
* 发送的Id类型
*/
diff --git a/austin-web/pom.xml b/austin-web/pom.xml
index f1af1f5..44715d5 100644
--- a/austin-web/pom.xml
+++ b/austin-web/pom.xml
@@ -31,6 +31,11 @@
austin-service-api-impl
0.0.1-SNAPSHOT
+
+ com.java3y.austin
+ austin-cron
+ 0.0.1-SNAPSHOT
+
diff --git a/austin-web/src/main/java/com/java3y/austin/controller/MessageTemplateController.java b/austin-web/src/main/java/com/java3y/austin/controller/MessageTemplateController.java
index 9a64b60..68a1d5c 100644
--- a/austin-web/src/main/java/com/java3y/austin/controller/MessageTemplateController.java
+++ b/austin-web/src/main/java/com/java3y/austin/controller/MessageTemplateController.java
@@ -48,7 +48,7 @@ public class MessageTemplateController {
* 如果Id不存在,则保存
*/
@PostMapping("/save")
- @ApiOperation("/插入数据")
+ @ApiOperation("/保存数据")
public BasicResultVO saveOrUpdate(@RequestBody MessageTemplate messageTemplate) {
MessageTemplate info = messageTemplateService.saveOrUpdate(messageTemplate);
@@ -123,4 +123,25 @@ public class MessageTemplateController {
return BasicResultVO.success(response);
}
+
+ /**
+ * 启动模板的定时任务
+ */
+ @PostMapping("start/{id}")
+ @ApiOperation("/启动模板的定时任务")
+ public BasicResultVO start(@RequestBody @PathVariable("id") Long id) {
+ messageTemplateService.startCronTask(id);
+
+ return BasicResultVO.success();
+ }
+ /**
+ * 启动模板的定时任务
+ */
+ @PostMapping("stop/{id}")
+ @ApiOperation("/暂停模板的定时任务")
+ public BasicResultVO stop(@RequestBody @PathVariable("id") Long id) {
+ messageTemplateService.stopCronTask(id);
+
+ return BasicResultVO.success();
+ }
}
diff --git a/austin-web/src/main/java/com/java3y/austin/controller/XxlJobController.java b/austin-web/src/main/java/com/java3y/austin/controller/XxlJobController.java
new file mode 100644
index 0000000..97200d7
--- /dev/null
+++ b/austin-web/src/main/java/com/java3y/austin/controller/XxlJobController.java
@@ -0,0 +1,24 @@
+package com.java3y.austin.controller;
+
+
+import com.java3y.austin.service.CronTaskService;
+import io.swagger.annotations.Api;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@Api(tags = {"定时任务接口"})
+@RestController
+public class XxlJobController {
+
+ @Autowired
+ private CronTaskService cronTaskService;
+
+
+ @RequestMapping("/xxl/add/task")
+ public Integer addTask() {
+
+ // return taskService.saveTask();
+ return null;
+ }
+}
diff --git a/austin-web/src/main/java/com/java3y/austin/service/MessageTemplateService.java b/austin-web/src/main/java/com/java3y/austin/service/MessageTemplateService.java
index 1b30588..63e883c 100644
--- a/austin-web/src/main/java/com/java3y/austin/service/MessageTemplateService.java
+++ b/austin-web/src/main/java/com/java3y/austin/service/MessageTemplateService.java
@@ -1,6 +1,7 @@
package com.java3y.austin.service;
import com.java3y.austin.domain.MessageTemplate;
+import com.java3y.austin.vo.BasicResultVO;
import com.java3y.austin.vo.MessageTemplateParam;
import java.util.List;
@@ -60,4 +61,15 @@ public interface MessageTemplateService {
* @param id
*/
void copy(Long id);
+
+ /**
+ * 启动模板的定时任务
+ */
+ BasicResultVO startCronTask(Long id);
+
+ /**
+ * 暂停模板的定时任务
+ */
+ BasicResultVO stopCronTask(Long id);
+
}
diff --git a/austin-web/src/main/java/com/java3y/austin/service/impl/MessageTemplateServiceImpl.java b/austin-web/src/main/java/com/java3y/austin/service/impl/MessageTemplateServiceImpl.java
index 58d3cfa..a929db8 100644
--- a/austin-web/src/main/java/com/java3y/austin/service/impl/MessageTemplateServiceImpl.java
+++ b/austin-web/src/main/java/com/java3y/austin/service/impl/MessageTemplateServiceImpl.java
@@ -6,9 +6,14 @@ import cn.hutool.core.util.StrUtil;
import com.java3y.austin.constant.AustinConstant;
import com.java3y.austin.dao.MessageTemplateDao;
import com.java3y.austin.domain.MessageTemplate;
+import com.java3y.austin.entity.XxlJobInfo;
import com.java3y.austin.enums.AuditStatus;
import com.java3y.austin.enums.MessageStatus;
+import com.java3y.austin.enums.TemplateType;
+import com.java3y.austin.service.CronTaskService;
import com.java3y.austin.service.MessageTemplateService;
+import com.java3y.austin.utils.XxlJobUtils;
+import com.java3y.austin.vo.BasicResultVO;
import com.java3y.austin.vo.MessageTemplateParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
@@ -24,9 +29,13 @@ import java.util.List;
*/
@Service
public class MessageTemplateServiceImpl implements MessageTemplateService {
+
+
@Autowired
private MessageTemplateDao messageTemplateDao;
+ @Autowired
+ private CronTaskService cronTaskService;
@Override
public List queryList(MessageTemplateParam param) {
@@ -43,10 +52,15 @@ public class MessageTemplateServiceImpl implements MessageTemplateService {
public MessageTemplate saveOrUpdate(MessageTemplate messageTemplate) {
if (messageTemplate.getId() == null) {
initStatus(messageTemplate);
+ } else {
+ resetStatus(messageTemplate);
}
+
+ messageTemplate.setUpdated(Math.toIntExact(DateUtil.currentSeconds()));
return messageTemplateDao.save(messageTemplate);
}
+
@Override
public void deleteByIds(List ids) {
Iterable messageTemplates = messageTemplateDao.findAllById(ids);
@@ -62,9 +76,36 @@ public class MessageTemplateServiceImpl implements MessageTemplateService {
@Override
public void copy(Long id) {
MessageTemplate messageTemplate = messageTemplateDao.findById(id).get();
- MessageTemplate clone = ObjectUtil.clone(messageTemplate);
- clone.setId(null);
+ MessageTemplate clone = ObjectUtil.clone(messageTemplate).setId(null);
+ messageTemplateDao.save(clone);
+ }
+
+ @Override
+ public BasicResultVO startCronTask(Long id) {
+ // 1.修改模板状态
+ MessageTemplate messageTemplate = messageTemplateDao.findById(id).get();
+
+ // 2.动态创建定时任务并启动
+ XxlJobInfo xxlJobInfo = XxlJobUtils.buildXxlJobInfo(messageTemplate);
+
+ BasicResultVO basicResultVO = cronTaskService.saveCronTask(xxlJobInfo);
+ // basicResultVO.getData()
+ //cronTaskService.startCronTask()
+
+ MessageTemplate clone = ObjectUtil.clone(messageTemplate).setMsgStatus(MessageStatus.RUN.getCode()).setUpdated(Math.toIntExact(DateUtil.currentSeconds()));
+ messageTemplateDao.save(clone);
+ return BasicResultVO.success();
+ }
+
+ @Override
+ public BasicResultVO stopCronTask(Long id) {
+ // 1.修改模板状态
+ MessageTemplate messageTemplate = messageTemplateDao.findById(id).get();
+ MessageTemplate clone = ObjectUtil.clone(messageTemplate).setMsgStatus(MessageStatus.STOP.getCode()).setUpdated(Math.toIntExact(DateUtil.currentSeconds()));
messageTemplateDao.save(clone);
+
+ // 2.暂停定时任务
+ return cronTaskService.stopCronTask(clone.getCronTaskId());
}
@@ -79,8 +120,26 @@ public class MessageTemplateServiceImpl implements MessageTemplateService {
.setMsgStatus(MessageStatus.INIT.getCode()).setAuditStatus(AuditStatus.WAIT_AUDIT.getCode())
.setCreator("Java3y").setUpdator("Java3y").setTeam("公众号Java3y").setAuditor("3y")
.setDeduplicationTime(AustinConstant.FALSE).setIsNightShield(AustinConstant.FALSE)
- .setCreated(Math.toIntExact(DateUtil.currentSeconds())).setUpdated(Math.toIntExact(DateUtil.currentSeconds()))
+ .setCreated(Math.toIntExact(DateUtil.currentSeconds()))
.setIsDeleted(AustinConstant.FALSE);
+
+ }
+
+ /**
+ * 1. 重置模板的状态
+ * 2. 修改定时任务信息
+ *
+ * @param messageTemplate
+ */
+ private void resetStatus(MessageTemplate messageTemplate) {
+ messageTemplate.setUpdator(messageTemplate.getUpdator())
+ .setMsgStatus(MessageStatus.INIT.getCode()).setAuditStatus(AuditStatus.WAIT_AUDIT.getCode());
+
+ if (messageTemplate.getCronTaskId() != null && TemplateType.CLOCKING.getCode().equals(messageTemplate.getTemplateType())) {
+ XxlJobInfo xxlJobInfo = XxlJobUtils.buildXxlJobInfo(messageTemplate);
+ cronTaskService.saveCronTask(xxlJobInfo);
+ cronTaskService.stopCronTask(messageTemplate.getCronTaskId());
+ }
}
diff --git a/austin-web/src/main/java/com/java3y/austin/vo/TaskParam.java b/austin-web/src/main/java/com/java3y/austin/vo/TaskParam.java
new file mode 100644
index 0000000..88e0ff6
--- /dev/null
+++ b/austin-web/src/main/java/com/java3y/austin/vo/TaskParam.java
@@ -0,0 +1,42 @@
+package com.java3y.austin.vo;
+
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Map;
+
+/**
+ * xxlJob任务的参数
+ * @author 3y
+ */
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class TaskParam {
+
+ /**
+ * 模板Id
+ */
+ private String messageTemplateId;
+
+ /**
+ * cron表达式
+ */
+ private String cron;
+
+ /**
+ * 创建者
+ */
+ private String creator;
+
+
+ /**
+ * 额外参数信息
+ */
+ private Map extra;
+
+}
diff --git a/austin-web/src/main/resources/application.yml b/austin-web/src/main/resources/application.yml
index ce4b6ed..68f78fe 100644
--- a/austin-web/src/main/resources/application.yml
+++ b/austin-web/src/main/resources/application.yml
@@ -68,4 +68,19 @@ apollo:
bootstrap:
enabled: true
namespaces: boss.austin
+
+# xxl job TODO
+xxl:
+ job:
+ admin:
+ addresses: # 调度中心部署跟地址 [选填]:如调度中心集群部署存在多个地址则用逗号分隔。执行器将会使用该地址进行"执行器心跳注册"和"任务结果回调";为空则关闭自动注册;
+ username: # 后台用户名
+ password: # 后台密码
+ executor:
+ appname: austin # 执行器 AppName [选填]:执行器心跳注册分组依据;为空则关闭自动注册
+ ip: # 执行器IP [选填]:默认为空表示自动获取IP,多网卡时可手动设置指定IP,该IP不会绑定Host仅作为通讯实用;地址信息用于 "执行器注册" 和 "调度中心请求并触发任务";
+ port: 6666 # ### 执行器端口号 [选填]:小于等于0则自动获取;默认端口为9999,单机部署多个执行器时,注意要配置不同执行器端口;
+ logpath: # 执行器运行日志文件存储磁盘路径 [选填] :需要对该路径拥有读写权限;为空则使用默认路径;
+ logretentiondays: 30 # 执行器日志文件保存天数 [选填] : 过期日志自动清理, 限制值大于等于3时生效; 否则, 如-1, 关闭自动清理功能;
+ accessToken: # 执行器通讯TOKEN [选填]:非空时启用;
# tomcat / HikariPool(数据库连接池 配置) TODO
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 83a80b2..7fed6ac 100644
--- a/pom.xml
+++ b/pom.xml
@@ -11,6 +11,7 @@
austin-common
austin-support
austin-handler
+ austin-cron
@@ -37,7 +38,6 @@
mysql
mysql-connector-java
5.1.35
-
@@ -111,6 +111,13 @@
3.0.0
+
+
+ com.xuxueli
+ xxl-job-core
+ 2.3.0
+
+
diff --git a/sql/austin.sql b/sql/austin.sql
index f3c729e..d44fc91 100644
--- a/sql/austin.sql
+++ b/sql/austin.sql
@@ -1,31 +1,33 @@
-create database austin;
+create
+database austin;
CREATE TABLE `message_template`
(
- `id` bigint(20) NOT NULL AUTO_INCREMENT,
+ `id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '标题',
- `audit_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '当前消息审核状态: 10.待审核 20.审核成功 30.被拒绝',
+ `audit_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '当前消息审核状态: 10.待审核 20.审核成功 30.被拒绝',
`flow_id` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '工单ID',
- `msg_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '当前消息状态:10.新建 20.停用 30.启用 40.等待发送 50.发送中 60.发送成功 70.发送失败',
- `id_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '消息的发送ID类型:10. userId 20.did 30.手机号 40.openId 50.email',
- `send_channel` tinyint(4) NOT NULL DEFAULT '0' COMMENT '消息发送渠道:10.IM 20.Push 30.短信 40.Email 50.公众号 60.小程序',
- `template_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '10.运营类 20.技术类接口调用',
- `msg_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '10.通知类消息 20.营销类消息 30.验证码类消息',
+ `msg_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '当前消息状态:10.新建 20.停用 30.启用 40.等待发送 50.发送中 60.发送成功 70.发送失败',
+ `cron_task_id` int(11) COMMENT '定时任务Id (xxl-job-admin返回)',
+ `id_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '消息的发送ID类型:10. userId 20.did 30.手机号 40.openId 50.email',
+ `send_channel` tinyint(4) NOT NULL DEFAULT '0' COMMENT '消息发送渠道:10.IM 20.Push 30.短信 40.Email 50.公众号 60.小程序',
+ `template_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '10.运营类 20.技术类接口调用',
+ `msg_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '10.通知类消息 20.营销类消息 30.验证码类消息',
`expect_push_time` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '期望发送时间:立即发送.10 定时任务以及周期任务.cron表达式',
`msg_content` varchar(600) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '消息内容 占位符用{$var}表示',
- `send_account` tinyint(4) NOT NULL DEFAULT '0' COMMENT '发送账号 一个渠道下可存在多个账号',
+ `send_account` tinyint(4) NOT NULL DEFAULT '0' COMMENT '发送账号 一个渠道下可存在多个账号',
`creator` varchar(45) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '创建者',
`updator` varchar(45) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '更新者',
`auditor` varchar(45) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '审核人',
`team` varchar(45) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '业务方团队',
`proposer` varchar(45) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '业务方',
- `is_deleted` tinyint(4) NOT NULL DEFAULT '0' COMMENT '是否删除:0.不删除 1.删除',
- `created` int(11) NOT NULL DEFAULT '0' COMMENT '创建时间',
- `updated` int(11) NOT NULL DEFAULT '0' COMMENT '更新时间',
- `deduplication_time` tinyint(4) NOT NULL DEFAULT '0' COMMENT '去重时间 单位小时',
- `is_night_shield` tinyint(4) NOT NULL DEFAULT '0' COMMENT '是否夜间屏蔽:0.夜间不屏蔽 1.夜间屏蔽',
+ `is_deleted` tinyint(4) NOT NULL DEFAULT '0' COMMENT '是否删除:0.不删除 1.删除',
+ `created` int(11) NOT NULL DEFAULT '0' COMMENT '创建时间',
+ `updated` int(11) NOT NULL DEFAULT '0' COMMENT '更新时间',
+ `deduplication_time` tinyint(4) NOT NULL DEFAULT '0' COMMENT '去重时间 单位小时',
+ `is_night_shield` tinyint(4) NOT NULL DEFAULT '0' COMMENT '是否夜间屏蔽:0.夜间不屏蔽 1.夜间屏蔽',
PRIMARY KEY (`id`),
- KEY `idx_channel` (`send_channel`)
+ KEY `idx_channel` (`send_channel`)
) ENGINE = InnoDB
AUTO_INCREMENT = 1
DEFAULT CHARSET = utf8mb4
@@ -35,21 +37,21 @@ CREATE TABLE `message_template`
CREATE TABLE `sms_record`
(
- `id` bigint(20) NOT NULL AUTO_INCREMENT,
- `message_template_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '消息模板ID',
- `phone` bigint(20) NOT NULL DEFAULT '0' COMMENT '手机号',
- `supplier_id` tinyint(4) NOT NULL DEFAULT '0' COMMENT '发送短信渠道商的ID',
+ `id` bigint(20) NOT NULL AUTO_INCREMENT,
+ `message_template_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '消息模板ID',
+ `phone` bigint(20) NOT NULL DEFAULT '0' COMMENT '手机号',
+ `supplier_id` tinyint(4) NOT NULL DEFAULT '0' COMMENT '发送短信渠道商的ID',
`supplier_name` varchar(40) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '发送短信渠道商的名称',
`msg_content` varchar(600) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '短信发送的内容',
`series_id` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '下发批次的ID',
- `charging_num` tinyint(4) NOT NULL DEFAULT '0' COMMENT '计费条数',
+ `charging_num` tinyint(4) NOT NULL DEFAULT '0' COMMENT '计费条数',
`report_content` varchar(50) NOT NULL DEFAULT '' COMMENT '回执内容',
- `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '短信状态: 10.发送 20.成功 30.失败',
- `send_date` int(11) NOT NULL DEFAULT '0' COMMENT '发送日期:20211112',
- `created` int(11) NOT NULL DEFAULT '0' COMMENT '创建时间',
- `updated` int(11) NOT NULL DEFAULT '0' COMMENT '更新时间',
+ `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '短信状态: 10.发送 20.成功 30.失败',
+ `send_date` int(11) NOT NULL DEFAULT '0' COMMENT '发送日期:20211112',
+ `created` int(11) NOT NULL DEFAULT '0' COMMENT '创建时间',
+ `updated` int(11) NOT NULL DEFAULT '0' COMMENT '更新时间',
PRIMARY KEY (`id`),
- KEY `idx_send_date` (`send_date`)
+ KEY `idx_send_date` (`send_date`)
) ENGINE = InnoDB
AUTO_INCREMENT = 1
DEFAULT CHARSET = utf8mb4
@@ -60,7 +62,16 @@ CREATE TABLE `sms_record`
INSERT INTO austin.message_template (id, name, audit_status, flow_id, msg_status, id_type, send_channel, template_type, msg_type, expect_push_time, msg_content, send_account, creator, updator, auditor, team, proposer, is_deleted, created, updated, deduplication_time, is_night_shield) VALUES (1, 'test短信', 10, 'yyyy', 10, 30, 30, 10, 10, '0', '{"content":"{$contentValue}"}', 10, 'yyyyc', 'yyyyu', 'yyyyyyz', 'yyyt', 'yyyy22', 0, 1636978066, 1636978066, 1, 0);
/*测试短信+url链接追踪*/
-INSERT INTO austin.message_template (id, name, audit_status, flow_id, msg_status, id_type, send_channel, template_type, msg_type, expect_push_time, msg_content, send_account, creator, updator, auditor, team, proposer, is_deleted, created, updated, deduplication_time, is_night_shield) VALUES (2, 'test短信', 10, 'yyyy', 10, 30, 30, 10, 20, '0', '{"content":"{$contentValue}","url":"https://gitee.com/zhongfucheng/austin"}', 10, 'yyyyc', 'yyyyu', 'yyyyyyz', 'yyyt', 'yyyy22', 0, 1637411536, 1637411536, 1, 0);
+INSERT INTO austin.message_template (id, name, audit_status, flow_id, msg_status, id_type, send_channel, template_type,
+ msg_type, expect_push_time, msg_content, send_account, creator, updator, auditor,
+ team, proposer, is_deleted, created, updated, deduplication_time, is_night_shield)
+VALUES (2, 'test短信', 10, 'yyyy', 10, 30, 30, 10, 20, '0',
+ '{"content":"{$contentValue}","url":"https://gitee.com/zhongfucheng/austin"}', 10, 'yyyyc', 'yyyyu', 'yyyyyyz',
+ 'yyyt', 'yyyy22', 0, 1637411536, 1637411536, 1, 0);
/*测试邮件发送*/
-INSERT INTO austin.message_template (id, name, audit_status, flow_id, msg_status, id_type, send_channel, template_type, msg_type, expect_push_time, msg_content, send_account, creator, updator, auditor, team, proposer, is_deleted, created, updated, deduplication_time, is_night_shield) VALUES (3, 'test邮件', 10, 'yyyy', 10, 50, 40, 20, 10, '0', '{"content":"{$contentValue}","title":"{$title}"}', 10, 'yyyyc', 'yyyyu', 'yyyyyyz', 'yyyt', 'yyyy22', 0, 1641546914, 1641546914, 1, 0);
\ No newline at end of file
+INSERT INTO austin.message_template (id, name, audit_status, flow_id, msg_status, id_type, send_channel, template_type,
+ msg_type, expect_push_time, msg_content, send_account, creator, updator, auditor,
+ team, proposer, is_deleted, created, updated, deduplication_time, is_night_shield)
+VALUES (3, 'test邮件', 10, 'yyyy', 10, 50, 40, 20, 10, '0', '{"content":"{$contentValue}","title":"{$title}"}', 10,
+ 'yyyyc', 'yyyyu', 'yyyyyyz', 'yyyt', 'yyyy22', 0, 1641546914, 1641546914, 1, 0);
\ No newline at end of file