feat:动态获取任务的cron和开关
This commit is contained in:
48
readme.md
Normal file
48
readme.md
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
# Xxz-job任务调度系统
|
||||||
|
|
||||||
|
### (一)
|
||||||
|
|
||||||
|
### (二)版本控制
|
||||||
|
|
||||||
|
#### (1)v1.0版本-master分支上
|
||||||
|
|
||||||
|
1. 设计Xxz-job注解以及EnableXxzJob注解,编写xxz-job注解扫描器以及注解执行器,本机单机执行任务。
|
||||||
|
|
||||||
|
```java
|
||||||
|
// 第一版Xxz-job注解内容
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Documented
|
||||||
|
public @interface XxzJob {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* bean的名称
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
String name();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cron调度方法
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
String cron();
|
||||||
|
|
||||||
|
boolean enabled() default true;
|
||||||
|
/**
|
||||||
|
* 是否支持多机分布式运行
|
||||||
|
* 若为false:每台机器都会执行一次
|
||||||
|
* 若为true:仅一台机器会执行
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
boolean distributed() default true;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
第一版XxzJob注解仅支持单机,并且cron固定的方式进行设计,能够将任务根据cron正常启动。
|
||||||
|
|
||||||
|
#### (2)v1.1版本-feat/schedule_v1_0106
|
||||||
|
|
||||||
|
1. 动态获取定时任务的cron和开关
|
||||||
|
1.
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package com.xiang.app.quartz.admin.server;
|
||||||
|
|
||||||
|
import com.xiang.app.quartz.admin.domain.entity.JobConfigDO;
|
||||||
|
import com.xiang.app.quartz.admin.service.ITaskConfigService;
|
||||||
|
import com.xiang.xservice.basic.common.resp.Result;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: xiang
|
||||||
|
* @Date: 2026-01-06 15:05
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@RequestMapping("/open/quartz/fetch")
|
||||||
|
public class XxzJobFetchController {
|
||||||
|
|
||||||
|
private final ITaskConfigService taskConfigService;
|
||||||
|
@GetMapping("/list")
|
||||||
|
public Result<JobConfigDO> list(@RequestParam("appName") String appName) {
|
||||||
|
List<JobConfigDO> jobsByAppName = taskConfigService.getJobsByAppName(appName);
|
||||||
|
return Result.success(jobsByAppName);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.xiang.app.quartz.admin.service;
|
package com.xiang.app.quartz.admin.service;
|
||||||
|
|
||||||
|
import com.xiang.app.quartz.admin.domain.entity.JobConfigDO;
|
||||||
import com.xiang.app.quartz.admin.domain.req.TaskRegisterRequest;
|
import com.xiang.app.quartz.admin.domain.req.TaskRegisterRequest;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -23,4 +24,6 @@ public interface ITaskConfigService {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
boolean registerTasks(List<TaskRegisterRequest> request);
|
boolean registerTasks(List<TaskRegisterRequest> request);
|
||||||
|
|
||||||
|
List<JobConfigDO> getJobsByAppName(String appName);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,6 +67,11 @@ public class TaskConfigServiceImpl implements ITaskConfigService {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<JobConfigDO> getJobsByAppName(String appName) {
|
||||||
|
return quartzConfigManage.selectByAppName(appName);
|
||||||
|
}
|
||||||
|
|
||||||
private static void putDataIntoDo(TaskRegisterRequest item, JobConfigDO jobConfigDO, String applicationName) {
|
private static void putDataIntoDo(TaskRegisterRequest item, JobConfigDO jobConfigDO, String applicationName) {
|
||||||
jobConfigDO.setApplicationName(applicationName);
|
jobConfigDO.setApplicationName(applicationName);
|
||||||
jobConfigDO.setApplicationAddress(item.getApplicationAddress());
|
jobConfigDO.setApplicationAddress(item.getApplicationAddress());
|
||||||
|
|||||||
@@ -25,6 +25,11 @@
|
|||||||
<artifactId>xmc-common</artifactId>
|
<artifactId>xmc-common</artifactId>
|
||||||
<version>1.0</version>
|
<version>1.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.xiang.starter</groupId>
|
||||||
|
<artifactId>xmc-http-starter</artifactId>
|
||||||
|
<version>1.0</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.xiang.starter</groupId>
|
<groupId>com.xiang.starter</groupId>
|
||||||
<artifactId>xmc-cache-starter</artifactId>
|
<artifactId>xmc-cache-starter</artifactId>
|
||||||
|
|||||||
@@ -22,11 +22,11 @@ public @interface XxzJob {
|
|||||||
*/
|
*/
|
||||||
String name();
|
String name();
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* cron调度方法
|
// * cron调度方法
|
||||||
* @return
|
// * @return
|
||||||
*/
|
// */
|
||||||
String cron();
|
// String cron();
|
||||||
|
|
||||||
boolean enabled() default true;
|
boolean enabled() default true;
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package com.xiang.core.quartz.api;
|
||||||
|
|
||||||
|
import com.xiang.core.quartz.model.JobConfigDO;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: xiang
|
||||||
|
* @Date: 2026-01-06 15:10
|
||||||
|
*/
|
||||||
|
public interface AdminJobClient {
|
||||||
|
|
||||||
|
List<JobConfigDO> fetchJobByAppName(String appName);
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package com.xiang.core.quartz.api;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
import com.xiang.core.quartz.model.JobConfigDO;
|
||||||
|
import com.xiang.core.quartz.model.XxzJobProperties;
|
||||||
|
import com.xiang.xmc.service.http.helper.HttpHelper;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: xiang
|
||||||
|
* @Date: 2026-01-06 15:11
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class HttpAdminJobClientImpl implements AdminJobClient{
|
||||||
|
|
||||||
|
private final XxzJobProperties xxzJobProperties;
|
||||||
|
@Override
|
||||||
|
public List<JobConfigDO> fetchJobByAppName(String appName) {
|
||||||
|
String address = xxzJobProperties.getAdminAddress();
|
||||||
|
address = address + "/open/quartz/fetch/list";
|
||||||
|
Map<String, String> params = Maps.newHashMap();
|
||||||
|
params.put("appName", appName);
|
||||||
|
String resp = HttpHelper.doGet(address, null, params);
|
||||||
|
if (StringUtils.isNotBlank(resp)) {
|
||||||
|
JSONObject jsonObject = JSON.parseObject(resp);
|
||||||
|
if (Objects.nonNull(jsonObject)) {
|
||||||
|
String data = JSON.toJSONString(jsonObject.get("data"));
|
||||||
|
if (StringUtils.isNotBlank(data)) {
|
||||||
|
return JSON.parseArray(data, JobConfigDO.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Lists.newArrayList();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,14 +1,22 @@
|
|||||||
package com.xiang.core.quartz.boostrap;
|
package com.xiang.core.quartz.boostrap;
|
||||||
|
|
||||||
|
import com.xiang.core.quartz.api.AdminJobClient;
|
||||||
import com.xiang.core.quartz.holder.JobDefinitionHolder;
|
import com.xiang.core.quartz.holder.JobDefinitionHolder;
|
||||||
import com.xiang.core.quartz.model.JobDefinition;
|
import com.xiang.core.quartz.model.JobConfigDO;
|
||||||
|
import com.xiang.core.quartz.model.XxzJobProperties;
|
||||||
import com.xiang.core.quartz.schedule.JobScheduler;
|
import com.xiang.core.quartz.schedule.JobScheduler;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.ApplicationArguments;
|
import org.springframework.boot.ApplicationArguments;
|
||||||
import org.springframework.boot.ApplicationRunner;
|
import org.springframework.boot.ApplicationRunner;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Author: xiang
|
* @Author: xiang
|
||||||
* @Date: 2026-01-06 09:50
|
* @Date: 2026-01-06 09:50
|
||||||
@@ -19,13 +27,29 @@ public class JobBootstrap implements ApplicationRunner {
|
|||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private JobScheduler scheduler;
|
private JobScheduler scheduler;
|
||||||
|
@Autowired
|
||||||
|
private AdminJobClient adminJobClient;
|
||||||
|
@Autowired
|
||||||
|
private XxzJobProperties xxzJobProperties;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run(ApplicationArguments args) {
|
public void run(ApplicationArguments args) {
|
||||||
|
List<JobConfigDO> jobConfigDOS = adminJobClient.fetchJobByAppName(xxzJobProperties.getAppName());
|
||||||
|
if (CollectionUtils.isEmpty(jobConfigDOS)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Map<String, JobConfigDO> map = jobConfigDOS.stream().collect(Collectors.toMap(JobConfigDO::getBeanName, Function.identity(), (a, b) -> a));
|
||||||
JobDefinitionHolder.getAll()
|
JobDefinitionHolder.getAll()
|
||||||
.stream()
|
.forEach(item -> {
|
||||||
.filter(JobDefinition::isEnabled)
|
if (map.containsKey(item.getName())) {
|
||||||
.forEach(scheduler::schedule);
|
JobConfigDO jobConfigDO = map.get(item.getName());
|
||||||
|
if (jobConfigDO.getJobSwitch() == 1) {
|
||||||
|
item.setCron(jobConfigDO.getCron());
|
||||||
|
item.setEnabled(jobConfigDO.getJobSwitch() == 1);
|
||||||
|
scheduler.schedule(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,84 @@
|
|||||||
|
package com.xiang.core.quartz.model;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: xiang
|
||||||
|
* @Date: 2025-12-30 09:42
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@TableName("xmc_quartz_config")
|
||||||
|
public class JobConfigDO implements Serializable {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* id
|
||||||
|
*/
|
||||||
|
private Long id;
|
||||||
|
/**
|
||||||
|
* 应用名称
|
||||||
|
*/
|
||||||
|
private String applicationName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用地址
|
||||||
|
*/
|
||||||
|
private String applicationAddress;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 定时任务名称
|
||||||
|
*/
|
||||||
|
private String beanName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 任务执行调度时间
|
||||||
|
*/
|
||||||
|
private String cron;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 类名
|
||||||
|
*/
|
||||||
|
private String clazz;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 方法
|
||||||
|
*/
|
||||||
|
private String method;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 任务开关
|
||||||
|
* 0:关闭 1:开启
|
||||||
|
*/
|
||||||
|
private Integer jobSwitch;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除标识(0:未删除 1:已删除)
|
||||||
|
*/
|
||||||
|
private Integer delFlag;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建时间
|
||||||
|
*/
|
||||||
|
private LocalDateTime createTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改时间
|
||||||
|
*/
|
||||||
|
private LocalDateTime updateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上次执行时间
|
||||||
|
*/
|
||||||
|
private LocalDateTime lastRunningTime;
|
||||||
|
}
|
||||||
@@ -20,4 +20,9 @@ public class XxzJobProperties {
|
|||||||
* DB刷新任务间隔(毫秒)
|
* DB刷新任务间隔(毫秒)
|
||||||
*/
|
*/
|
||||||
private int refreshInterval = 5000;
|
private int refreshInterval = 5000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 调度中心地址
|
||||||
|
*/
|
||||||
|
private String adminAddress;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,8 +50,8 @@ public class JobScanner implements SmartInitializingSingleton {
|
|||||||
job.setDistributed(xxzJob.distributed());
|
job.setDistributed(xxzJob.distributed());
|
||||||
job.setBean(bean);
|
job.setBean(bean);
|
||||||
job.setMethod(method);
|
job.setMethod(method);
|
||||||
job.setEnabled(xxzJob.enabled());
|
// job.setEnabled();
|
||||||
job.setCron(xxzJob.cron());
|
// job.setCron(xxzJob.cron());
|
||||||
JobDefinitionHolder.register(job);
|
JobDefinitionHolder.register(job);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import org.springframework.stereotype.Component;
|
|||||||
@Component
|
@Component
|
||||||
public class TestXxzJob1 {
|
public class TestXxzJob1 {
|
||||||
|
|
||||||
@XxzJob(name = "TestXxzJob", cron = "0/1 * * * * ? ", enabled = true)
|
@XxzJob(name = "TestXxzJob")
|
||||||
public void test() {
|
public void test() {
|
||||||
log.info("任务调度开始");
|
log.info("任务调度开始");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
xxz-job:
|
xxz-job:
|
||||||
app-name: springboot-quartz-test
|
app-name: springboot-quartz-test
|
||||||
|
admin-address: http://127.0.0.1:30030
|
||||||
|
|
||||||
spring:
|
spring:
|
||||||
main:
|
main:
|
||||||
|
|||||||
Reference in New Issue
Block a user