init
This commit is contained in:
35
ruoyi-modules/ruoyi-job/pom.xml
Normal file
35
ruoyi-modules/ruoyi-job/pom.xml
Normal file
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<groupId>org.dromara</groupId>
|
||||
<artifactId>ruoyi-modules</artifactId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>ruoyi-job</artifactId>
|
||||
|
||||
<description>
|
||||
任务调度
|
||||
</description>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- 通用工具-->
|
||||
<dependency>
|
||||
<groupId>org.dromara</groupId>
|
||||
<artifactId>ruoyi-common-json</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 调度模块 -->
|
||||
<dependency>
|
||||
<groupId>org.dromara</groupId>
|
||||
<artifactId>ruoyi-common-job</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package org.dromara.job.entity;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 账单数据传输对象。
|
||||
*
|
||||
* @param billId 账单 ID
|
||||
* @param billChannel 账单渠道
|
||||
* @param billDate 账单日期
|
||||
* @param billAmount 账单金额
|
||||
*/
|
||||
public record BillDTO(
|
||||
Long billId,
|
||||
String billChannel,
|
||||
String billDate,
|
||||
BigDecimal billAmount
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
package org.dromara.job;
|
||||
@@ -0,0 +1,45 @@
|
||||
package org.dromara.job.snailjob;
|
||||
|
||||
import com.aizuda.snailjob.client.job.core.annotation.JobExecutor;
|
||||
import com.aizuda.snailjob.client.job.core.dto.JobArgs;
|
||||
import com.aizuda.snailjob.common.log.SnailJobLog;
|
||||
import com.aizuda.snailjob.model.dto.ExecuteResult;
|
||||
import org.dromara.common.core.utils.DateUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.json.utils.JsonUtils;
|
||||
import org.dromara.job.entity.BillDTO;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* DAG工作流任务-模拟支付宝账单任务
|
||||
* <a href="https://juejin.cn/post/7487860254114644019"></a>
|
||||
*
|
||||
* @author 老马
|
||||
*/
|
||||
@Component
|
||||
@JobExecutor(name = "alipayBillTask")
|
||||
public class AlipayBillTask {
|
||||
|
||||
/**
|
||||
* 执行支付宝账单模拟任务,并将结果写入工作流上下文。
|
||||
*
|
||||
* @param jobArgs 任务执行参数
|
||||
* @return 执行结果
|
||||
* @throws InterruptedException 任务被中断时抛出
|
||||
*/
|
||||
public ExecuteResult jobExecute(JobArgs jobArgs) throws InterruptedException {
|
||||
// 设置清算日期
|
||||
String settlementDate = (String) jobArgs.getWfContext().get("settlementDate");
|
||||
if (StringUtils.equals(settlementDate, "sysdate")) {
|
||||
settlementDate = DateUtils.now();
|
||||
}
|
||||
BillDTO billDTO = new BillDTO(23456789L, "alipay", settlementDate, new BigDecimal("2345.67"));
|
||||
// 把billDTO对象放入上下文进行传递
|
||||
jobArgs.appendContext("alipay", JsonUtils.toJsonString(billDTO));
|
||||
SnailJobLog.REMOTE.info("上下文: {}", jobArgs.getWfContext());
|
||||
return ExecuteResult.success(billDTO);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package org.dromara.job.snailjob;
|
||||
|
||||
import com.aizuda.snailjob.client.job.core.annotation.JobExecutor;
|
||||
import com.aizuda.snailjob.client.job.core.dto.JobArgs;
|
||||
import com.aizuda.snailjob.common.log.SnailJobLog;
|
||||
import com.aizuda.snailjob.model.dto.ExecuteResult;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.json.utils.JsonUtils;
|
||||
import org.dromara.job.entity.BillDTO;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* DAG工作流任务-模拟汇总账单任务
|
||||
* <a href="https://juejin.cn/post/7487860254114644019"></a>
|
||||
*
|
||||
* @author 老马
|
||||
*/
|
||||
@Component
|
||||
@JobExecutor(name = "summaryBillTask")
|
||||
public class SummaryBillTask {
|
||||
|
||||
/**
|
||||
* 汇总工作流上下文中的微信与支付宝账单金额。
|
||||
*
|
||||
* @param jobArgs 任务执行参数
|
||||
* @return 汇总执行结果
|
||||
* @throws InterruptedException 任务被中断时抛出
|
||||
*/
|
||||
public ExecuteResult jobExecute(JobArgs jobArgs) throws InterruptedException {
|
||||
// 获得微信账单
|
||||
BigDecimal wechatAmount = BigDecimal.valueOf(0);
|
||||
String wechat = (String) jobArgs.getWfContext("wechat");
|
||||
if (StringUtils.isNotBlank(wechat)) {
|
||||
BillDTO wechatBillDTO = JsonUtils.parseObject(wechat, BillDTO.class);
|
||||
wechatAmount = wechatBillDTO.billAmount();
|
||||
}
|
||||
// 获得支付宝账单
|
||||
BigDecimal alipayAmount = BigDecimal.valueOf(0);
|
||||
String alipay = (String) jobArgs.getWfContext("alipay");
|
||||
if (StringUtils.isNotBlank(alipay)) {
|
||||
BillDTO alipayBillDTO = JsonUtils.parseObject(alipay, BillDTO.class);
|
||||
alipayAmount = alipayBillDTO.billAmount();
|
||||
}
|
||||
// 汇总账单
|
||||
BigDecimal totalAmount = wechatAmount.add(alipayAmount);
|
||||
SnailJobLog.REMOTE.info("总金额: {}", totalAmount);
|
||||
return ExecuteResult.success(totalAmount);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package org.dromara.job.snailjob;
|
||||
|
||||
import com.aizuda.snailjob.client.job.core.annotation.JobExecutor;
|
||||
import com.aizuda.snailjob.client.job.core.dto.JobArgs;
|
||||
import com.aizuda.snailjob.common.core.util.JsonUtil;
|
||||
import com.aizuda.snailjob.common.log.SnailJobLog;
|
||||
import com.aizuda.snailjob.model.dto.ExecuteResult;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 正常任务
|
||||
* <a href="https://juejin.cn/post/7418074037392293914"></a>
|
||||
*
|
||||
* @author 老马
|
||||
*/
|
||||
@Component
|
||||
@JobExecutor(name = "testJobExecutor")
|
||||
public class TestAnnoJobExecutor {
|
||||
|
||||
/**
|
||||
* 执行示例注解任务。
|
||||
*
|
||||
* @param jobArgs 任务参数
|
||||
* @return 执行结果
|
||||
*/
|
||||
public ExecuteResult jobExecute(JobArgs jobArgs) {
|
||||
SnailJobLog.LOCAL.info("testJobExecutor. jobArgs:{}", JsonUtil.toJsonString(jobArgs));
|
||||
SnailJobLog.REMOTE.info("testJobExecutor. jobArgs:{}", JsonUtil.toJsonString(jobArgs));
|
||||
return ExecuteResult.success("测试成功");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package org.dromara.job.snailjob;
|
||||
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import com.aizuda.snailjob.client.job.core.annotation.JobExecutor;
|
||||
import com.aizuda.snailjob.client.job.core.dto.JobArgs;
|
||||
import com.aizuda.snailjob.common.log.SnailJobLog;
|
||||
import com.aizuda.snailjob.model.dto.ExecuteResult;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 广播任务
|
||||
* <a href="https://juejin.cn/post/7422948006150438950"></a>
|
||||
*
|
||||
* @author 老马
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@JobExecutor(name = "testBroadcastJob")
|
||||
public class TestBroadcastJob {
|
||||
|
||||
/**
|
||||
* 客户端端口。
|
||||
*/
|
||||
@Value("${snail-job.port}")
|
||||
private int clientPort;
|
||||
|
||||
/**
|
||||
* 执行广播任务示例,随机模拟成功或失败。
|
||||
*
|
||||
* @param jobArgs 任务执行参数
|
||||
* @return 执行结果
|
||||
*/
|
||||
public ExecuteResult jobExecute(JobArgs jobArgs) {
|
||||
int randomInt = RandomUtil.randomInt(100);
|
||||
log.info("随机数: {}", randomInt);
|
||||
SnailJobLog.REMOTE.info("随机数: {},客户端端口:{}", randomInt, clientPort);
|
||||
if (randomInt < 50) {
|
||||
throw new RuntimeException("随机数小于50,收集日志任务执行失败");
|
||||
}
|
||||
// 获得jobArgs 中传入的相加的两个数
|
||||
return ExecuteResult.success("随机数大于50,收集日志任务执行成功");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package org.dromara.job.snailjob;
|
||||
|
||||
import com.aizuda.snailjob.client.job.core.dto.JobArgs;
|
||||
import com.aizuda.snailjob.client.job.core.executor.AbstractJobExecutor;
|
||||
import com.aizuda.snailjob.model.dto.ExecuteResult;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author opensnail
|
||||
* @date 2024-05-17
|
||||
*/
|
||||
@Component
|
||||
public class TestClassJobExecutor extends AbstractJobExecutor {
|
||||
|
||||
/**
|
||||
* 执行测试类任务。
|
||||
*
|
||||
* @param jobArgs 任务参数
|
||||
* @return 任务执行结果
|
||||
*/
|
||||
@Override
|
||||
protected ExecuteResult doJobExecute(JobArgs jobArgs) {
|
||||
return ExecuteResult.success("TestJobExecutor测试成功");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package org.dromara.job.snailjob;
|
||||
|
||||
import cn.hutool.core.thread.ThreadUtil;
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import com.aizuda.snailjob.client.job.core.MapHandler;
|
||||
import com.aizuda.snailjob.client.job.core.annotation.JobExecutor;
|
||||
import com.aizuda.snailjob.client.job.core.annotation.MapExecutor;
|
||||
import com.aizuda.snailjob.client.job.core.dto.MapArgs;
|
||||
import com.aizuda.snailjob.common.log.SnailJobLog;
|
||||
import com.aizuda.snailjob.model.dto.ExecuteResult;
|
||||
import org.dromara.common.core.utils.StreamUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
/**
|
||||
* Map任务 动态分配 只分片不关注结果
|
||||
* <a href="https://juejin.cn/post/7446362500478894106"></a>
|
||||
*
|
||||
* @author 老马
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
@Component
|
||||
@JobExecutor(name = "testMapJobAnnotation")
|
||||
public class TestMapJobAnnotation {
|
||||
|
||||
/**
|
||||
* 根 Map 任务,将示例数据拆分为多个分片任务。
|
||||
*
|
||||
* @param mapArgs Map 任务参数
|
||||
* @param mapHandler 分片调度处理器
|
||||
* @return 分片调度结果
|
||||
*/
|
||||
@MapExecutor
|
||||
public ExecuteResult doJobMapExecute(MapArgs mapArgs, MapHandler mapHandler) {
|
||||
// 生成1~200数值并分片
|
||||
int partitionSize = 50;
|
||||
List<Integer> sourceList = IntStream.rangeClosed(1, 200).boxed().toList();
|
||||
List<List<Integer>> partition = StreamUtils.groupByKey(sourceList, i -> (i - 1) / partitionSize)
|
||||
.values()
|
||||
.stream()
|
||||
.toList();
|
||||
SnailJobLog.REMOTE.info("端口:{}完成分配任务", SpringUtil.getProperty("server.port"));
|
||||
return mapHandler.doMap(partition, "doCalc");
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行单个分片的累加计算。
|
||||
*
|
||||
* @param mapArgs 分片任务参数
|
||||
* @return 分片计算结果
|
||||
*/
|
||||
@MapExecutor(taskName = "doCalc")
|
||||
public ExecuteResult doCalc(MapArgs mapArgs) {
|
||||
List<Integer> sourceList = (List<Integer>) mapArgs.getMapResult();
|
||||
// 遍历sourceList的每一个元素,计算出一个累加值partitionTotal
|
||||
int partitionTotal = sourceList.stream().mapToInt(i -> i).sum();
|
||||
// 打印日志到服务器
|
||||
ThreadUtil.sleep(3, TimeUnit.SECONDS);
|
||||
SnailJobLog.REMOTE.info("端口:{},partitionTotal:{}", SpringUtil.getProperty("server.port"), partitionTotal);
|
||||
return ExecuteResult.success(partitionTotal);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package org.dromara.job.snailjob;
|
||||
|
||||
import cn.hutool.core.thread.ThreadUtil;
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import com.aizuda.snailjob.client.job.core.MapHandler;
|
||||
import com.aizuda.snailjob.client.job.core.annotation.JobExecutor;
|
||||
import com.aizuda.snailjob.client.job.core.annotation.MapExecutor;
|
||||
import com.aizuda.snailjob.client.job.core.annotation.ReduceExecutor;
|
||||
import com.aizuda.snailjob.client.job.core.dto.MapArgs;
|
||||
import com.aizuda.snailjob.client.job.core.dto.ReduceArgs;
|
||||
import com.aizuda.snailjob.common.log.SnailJobLog;
|
||||
import com.aizuda.snailjob.model.dto.ExecuteResult;
|
||||
import org.dromara.common.core.utils.StreamUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
/**
|
||||
* MapReduce任务 动态分配 分片后合并结果
|
||||
* <a href="https://juejin.cn/post/7448551286506913802"></a>
|
||||
*
|
||||
* @author 老马
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
@Component
|
||||
@JobExecutor(name = "testMapReduceAnnotation1")
|
||||
public class TestMapReduceAnnotation1 {
|
||||
|
||||
/**
|
||||
* 根 Map 任务,将示例数据拆分为多个分片任务。
|
||||
*
|
||||
* @param mapArgs Map 任务参数
|
||||
* @param mapHandler 分片调度处理器
|
||||
* @return 分片调度结果
|
||||
*/
|
||||
@MapExecutor
|
||||
public ExecuteResult rootMapExecute(MapArgs mapArgs, MapHandler mapHandler) {
|
||||
int partitionSize = 50;
|
||||
List<Integer> sourceList = IntStream.rangeClosed(1, 200).boxed().toList();
|
||||
List<List<Integer>> partition = StreamUtils.groupByKey(sourceList, i -> (i - 1) / partitionSize)
|
||||
.values()
|
||||
.stream()
|
||||
.toList();
|
||||
SnailJobLog.REMOTE.info("端口:{}完成分配任务", SpringUtil.getProperty("server.port"));
|
||||
return mapHandler.doMap(partition, "doCalc");
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行单个分片的累加计算。
|
||||
*
|
||||
* @param mapArgs 分片任务参数
|
||||
* @return 分片计算结果
|
||||
*/
|
||||
@MapExecutor(taskName = "doCalc")
|
||||
public ExecuteResult doCalc(MapArgs mapArgs) {
|
||||
List<Integer> sourceList = (List<Integer>) mapArgs.getMapResult();
|
||||
// 遍历sourceList的每一个元素,计算出一个累加值partitionTotal
|
||||
int partitionTotal = sourceList.stream().mapToInt(i -> i).sum();
|
||||
// 打印日志到服务器
|
||||
ThreadUtil.sleep(3, TimeUnit.SECONDS);
|
||||
SnailJobLog.REMOTE.info("端口:{},partitionTotal:{}", SpringUtil.getProperty("server.port"), partitionTotal);
|
||||
return ExecuteResult.success(partitionTotal);
|
||||
}
|
||||
|
||||
/**
|
||||
* 汇总所有 Map 分片的计算结果。
|
||||
*
|
||||
* @param reduceArgs Reduce 任务参数
|
||||
* @return 汇总结果
|
||||
*/
|
||||
@ReduceExecutor
|
||||
public ExecuteResult reduceExecute(ReduceArgs reduceArgs) {
|
||||
int reduceTotal = reduceArgs.getMapResult().stream().mapToInt(i -> Integer.parseInt((String) i)).sum();
|
||||
SnailJobLog.REMOTE.info("端口:{},reduceTotal:{}", SpringUtil.getProperty("server.port"), reduceTotal);
|
||||
return ExecuteResult.success(reduceTotal);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package org.dromara.job.snailjob;
|
||||
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import com.aizuda.snailjob.client.job.core.annotation.JobExecutor;
|
||||
import com.aizuda.snailjob.client.job.core.dto.JobArgs;
|
||||
import com.aizuda.snailjob.common.log.SnailJobLog;
|
||||
import com.aizuda.snailjob.model.dto.ExecuteResult;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 静态分片 根据服务端任务参数分片
|
||||
* <a href="https://juejin.cn/post/7426232375703896101"></a>
|
||||
*
|
||||
* @author 老马
|
||||
*/
|
||||
@Component
|
||||
@JobExecutor(name = "testStaticShardingJob")
|
||||
public class TestStaticShardingJob {
|
||||
|
||||
/**
|
||||
* 执行静态分片任务示例。
|
||||
*
|
||||
* @param jobArgs 任务执行参数
|
||||
* @return 执行结果
|
||||
*/
|
||||
public ExecuteResult jobExecute(JobArgs jobArgs) {
|
||||
String jobParams = Convert.toStr(jobArgs.getJobParams());
|
||||
SnailJobLog.LOCAL.info("开始执行分片任务,参数:{}", jobParams);
|
||||
// 获得jobArgs 中传入的开始id和结束id
|
||||
String[] split = jobParams.split(",");
|
||||
Long fromId = Long.parseLong(split[0]);
|
||||
Long toId = Long.parseLong(split[1]);
|
||||
// 模拟数据库操作,对范围id,进行加密处理
|
||||
try {
|
||||
SnailJobLog.REMOTE.info("开始对id范围:{}进行加密处理", fromId + "-" + toId);
|
||||
Thread.sleep(3000);
|
||||
SnailJobLog.REMOTE.info("对id范围:{}进行加密处理完成", fromId + "-" + toId);
|
||||
} catch (InterruptedException e) {
|
||||
return ExecuteResult.failure("任务执行失败");
|
||||
}
|
||||
return ExecuteResult.success("执行分片任务完成");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package org.dromara.job.snailjob;
|
||||
|
||||
import com.aizuda.snailjob.client.job.core.annotation.JobExecutor;
|
||||
import com.aizuda.snailjob.client.job.core.dto.JobArgs;
|
||||
import com.aizuda.snailjob.common.log.SnailJobLog;
|
||||
import com.aizuda.snailjob.model.dto.ExecuteResult;
|
||||
import org.dromara.common.core.utils.DateUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.json.utils.JsonUtils;
|
||||
import org.dromara.job.entity.BillDTO;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* DAG工作流任务-模拟微信账单任务
|
||||
* <a href="https://juejin.cn/post/7487860254114644019"></a>
|
||||
*
|
||||
* @author 老马
|
||||
*/
|
||||
@Component
|
||||
@JobExecutor(name = "wechatBillTask")
|
||||
public class WechatBillTask {
|
||||
|
||||
/**
|
||||
* 执行微信账单模拟任务,并将结果写入工作流上下文。
|
||||
*
|
||||
* @param jobArgs 任务执行参数
|
||||
* @return 执行结果
|
||||
* @throws InterruptedException 任务被中断时抛出
|
||||
*/
|
||||
public ExecuteResult jobExecute(JobArgs jobArgs) throws InterruptedException {
|
||||
// 从上下文中获得清算日期并设置,如果上下文中清算日期
|
||||
// 是sysdate设置为当前日期;否则取管理页面设置的值
|
||||
String settlementDate = (String) jobArgs.getWfContext().get("settlementDate");
|
||||
if (StringUtils.equals(settlementDate, "sysdate")) {
|
||||
settlementDate = DateUtils.now();
|
||||
}
|
||||
BillDTO billDTO = new BillDTO(123456789L, "wechat", settlementDate, new BigDecimal("1234.56"));
|
||||
// 把billDTO对象放入上下文进行传递
|
||||
jobArgs.appendContext("wechat", JsonUtils.toJsonString(billDTO));
|
||||
SnailJobLog.REMOTE.info("上下文: {}", jobArgs.getWfContext());
|
||||
return ExecuteResult.success(billDTO);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user