初始化项目

This commit is contained in:
2026-04-21 16:12:04 +08:00
parent 4541af2c63
commit f9d96473da
443 changed files with 36365 additions and 19 deletions

26
xtools-app-common/pom.xml Normal file
View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.xujun</groupId>
<artifactId>xtools-app</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>xtools-app-common</artifactId>
<packaging>pom</packaging>
<!-- 子模块 -->
<modules>
<module>xtools-app-common-cache</module>
<module>xtools-app-common-call</module>
<module>xtools-app-common-jar</module>
<module>xtools-app-common-job</module>
<module>xtools-app-common-log</module>
<module>xtools-app-common-mq</module>
<module>xtools-app-common-sentinel</module>
<module>xtools-app-common-task</module>
</modules>
</project>

View File

@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.xujun</groupId>
<artifactId>xtools-app-common</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>xtools-app-common-cache</artifactId>
<!-- 依赖 -->
<dependencies>
<!-- xtools begin -->
<!-- xtools-extend -->
<dependency>
<groupId>org.xujun</groupId>
<artifactId>xtools-extend</artifactId>
</dependency>
<!-- xtools-boot-log -->
<dependency>
<groupId>org.xujun</groupId>
<artifactId>xtools-boot-log</artifactId>
</dependency>
<!-- xtools-boot-cache-redis -->
<dependency>
<groupId>org.xujun</groupId>
<artifactId>xtools-boot-cache-redis</artifactId>
</dependency>
<!-- xtools end -->
<!-- aop -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,73 @@
package xtools.app.common.cache.aop;
import com.alibaba.fastjson2.JSONObject;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import xtools.boot.api.model.dto.log.LogTrack;
import xtools.boot.log.LogBus;
import xtools.boot.log.enums.LogBusBaseType;
import xtools.boot.log.holder.LogTrackHolder;
import xtools.core.enums.LogLevel;
import java.util.Objects;
/**
* <p>Title : RedisServiceAop</p>
* <p>Description : RedisServiceAop</p>
* <p>DevelopTools : Idea_x64_v2026.1</p>
* <p>DevelopSystem : macOS Sequoia 15.7.5</p>
* <p>Company : org.xujun</p>
*
* @author : XuJun
* @version : 1.0.0
* @date : 2026/2/11 14:07
*/
@Aspect
@Component
public class RedisServiceAop {
/**
* 方法切面
*/
@Pointcut("execution(* xtools.boot.cache.redis.base.RedisService.*(..))")
public void methods() {
}
/**
* 调用记录
*
* @param joinPoint 切点
* @return 调用结果
* @throws Throwable 异常信息
*/
@Around("methods()")
public Object logMethodCall(ProceedingJoinPoint joinPoint) throws Throwable {
LogTrack logTrack = LogTrackHolder.getDefNull();
if (Objects.isNull(logTrack)) {
return joinPoint.proceed();
}
long startTime = System.currentTimeMillis();
String method = joinPoint.getSignature().getName();
Object[] args = joinPoint.getArgs();
Exception err = null;
Object result = null;
try {
result = joinPoint.proceed();
return result;
} catch (Exception e) {
err = e;
throw e;
} finally {
long endTime = System.currentTimeMillis();
JSONObject logData = JSONObject.of("method", method, "args", args, "result", result, "execTime", endTime - startTime);
LogBus.init(err == null ? LogLevel.INFO : LogLevel.ERROR, LogBusBaseType.REDIS, logTrack)
.data(logData)
.error(err)
.save();
}
}
}

View File

@@ -0,0 +1,107 @@
package xtools.app.common.cache.enums;
import xtools.boot.cache.redis.enums.BaseCacheEnum;
import xtools.core.extend.TemplateUtils;
/**
* <p>Title : AppCache</p>
* <p>Description : AppCache</p>
* <p>DevelopTools : Idea_x64_v2026.1</p>
* <p>DevelopSystem : macOS Sequoia 15.7.5</p>
* <p>Company : org.xujun</p>
*
* @author : XuJun
* @version : 1.0.0
* @date : 2026/2/4 16:27
*/
public enum AppCache implements BaseCacheEnum {
// uid加密SM2
UID_SM2("uid:{}:sm2", 5 * 60L),
// uid验证码
UID_CAPTCHA("uid:{}:captcha", 60L),
// SYS 授权用户信息
AUTH_SYS_USER("auth:sys:user:", 60 * 60L),
// SYS 授权 URI
AUTH_SYS_URI("auth:sys:uri", -1L),
// CLOUD 授权 TOKEN
AUTH_CLOUD_TOKEN("auth:cloud:token", 60L),
// MQ消息错误次数
MQ_MSG_ERR_COUNT("mq:msg:err:", 60L),
// JOB锁
LOCK_JOB("lock:job:", 5 * 60L),
// 风控IP
RISK_IP("risk:ip:", -1L),
// 风控URI
RISK_URI("risk:uri:", -1L),
// 系统参数缓存
SYS_CACHE_PARAM("sys:cache:param:", -1L),
// 系统JAR包缓存
SYS_CACHE_JAR("sys:cache:jar:", -1L),
// 地址缓存
SYS_CACHE_ADDR("sys:cache:addr:", 60 * 60L),
// 天气缓存
SYS_CACHE_HOME_WEATHER("sys:cache:home:weather:", 30 * 60L),
;
/**
* 系统缓存前缀
*/
private final static String SYS_CACHE_PREFIX = "xtools-app:";
/**
* key
*/
private final String key;
/**
* 超时时间
*/
private final Long expireTime;
/**
* 构造方法
*
* @param key 缓存 key
* @param expireTime 过期时间
*/
AppCache(String key, Long expireTime) {
this.key = key;
this.expireTime = expireTime;
}
/**
* 获取缓存 key
*
* @param param 参数
* @return 缓存 key
*/
public String key(Object... param) {
return SYS_CACHE_PREFIX + TemplateUtils.format(key, param);
}
/**
* 获取缓存 key
*
* @return 缓存 key
*/
@Override
public String key() {
return SYS_CACHE_PREFIX + key;
}
/**
* 获取缓存过期时间
*
* @return 缓存过期时间
*/
@Override
public Long expireTime() {
return expireTime;
}
}

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.xujun</groupId>
<artifactId>xtools-app-common</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>xtools-app-common-call</artifactId>
<!-- 依赖 -->
<dependencies>
<!-- xtools begin -->
<!-- xtools-cloud-call -->
<dependency>
<groupId>org.xujun</groupId>
<artifactId>xtools-cloud-call</artifactId>
</dependency>
<!-- xtools end -->
<!-- 项目模块 begin -->
<dependency>
<groupId>org.xujun</groupId>
<artifactId>xtools-app-common-cache</artifactId>
</dependency>
<!-- 项目模块 end -->
</dependencies>
</project>

View File

@@ -0,0 +1,87 @@
package xtools.app.common.call;
import jakarta.annotation.Resource;
import org.jspecify.annotations.NonNull;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpRequest;
import org.springframework.stereotype.Component;
import xtools.app.common.cache.enums.AppCache;
import xtools.base.config.BaseParams;
import xtools.boot.api.constant.BootCommonConstant;
import xtools.boot.cache.redis.base.RedisService;
import xtools.boot.core.holder.CommonHolder;
import xtools.cloud.call.interceptor.CallInterceptor;
import xtools.core.CollectionUtils;
import xtools.core.UuidUtils;
import java.util.Map;
/**
* <p>Title : SysCallInterceptor</p>
* <p>Description : SysCallInterceptor</p>
* <p>DevelopTools : Idea_x64_v2026.1</p>
* <p>DevelopSystem : macOS Sequoia 15.7.5</p>
* <p>Company : org.xujun</p>
*
* @author : XuJun
* @version : 1.0.0
* @date : 2026/2/27 14:55
*/
@Component
public class SysCallInterceptor implements CallInterceptor, BaseParams {
/**
* 缓存参数
*/
private static final AppCache CACHE_PARAM = AppCache.AUTH_CLOUD_TOKEN;
@Resource
private RedisService redisService;
/**
* 请求之前
*
* @param request 请求
*/
@Override
public void before(@NonNull HttpRequest request) {
// 设置微服务认证信息
setCloudToken(request);
Map<String, Object> commonMap = CommonHolder.get();
// 传递请求头信息
setHeaders(request, commonMap);
}
/**
* 设置微服务认证信息
*
* @param request 请求
*/
private void setCloudToken(@NonNull HttpRequest request) {
// 设置微服务认证信息
String token = UuidUtils.get();
redisService.hashPut(CACHE_PARAM.key(), token, CP_NUM0, CACHE_PARAM.expireTime());
request.getHeaders().add(BootCommonConstant.CLOUD_TOKEN, token);
}
/**
* 设置请求头
*
* @param request 请求
* @param commonMap 公共参数
*/
private void setHeaders(@NonNull HttpRequest request, Map<String, Object> commonMap) {
// 传递请求头信息
if (CollectionUtils.isEmpty(commonMap)) {
return;
}
HttpHeaders headers = request.getHeaders();
if (commonMap.get(BootCommonConstant.AUTHORIZATION) instanceof String authorization) {
headers.add(BootCommonConstant.AUTHORIZATION, authorization);
}
if (commonMap.get(BootCommonConstant.UID) instanceof String uid) {
headers.add(BootCommonConstant.UID, uid);
}
}
}

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.xujun</groupId>
<artifactId>xtools-app-common</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>xtools-app-common-jar</artifactId>
<!-- 依赖 -->
<dependencies>
<!-- xtools begin -->
<!-- xtools-boot-log -->
<dependency>
<groupId>org.xujun</groupId>
<artifactId>xtools-boot-log</artifactId>
</dependency>
<!-- xtools end -->
<!-- 项目模块 begin -->
<dependency>
<groupId>org.xujun</groupId>
<artifactId>xtools-app-common-cache</artifactId>
</dependency>
<!-- 项目模块 end -->
</dependencies>
</project>

View File

@@ -0,0 +1,71 @@
package xtools.app.common.jar.init;
import jakarta.annotation.Resource;
import org.jspecify.annotations.NonNull;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import xtools.app.common.cache.enums.AppCache;
import xtools.base.config.BaseParams;
import xtools.boot.cache.redis.base.RedisService;
import xtools.boot.core.utils.JarUtils;
import xtools.boot.log.LogBus;
import xtools.boot.log.enums.LogBusBaseType;
import xtools.boot.log.holder.LogTrackHolder;
import xtools.core.CollectionUtils;
import xtools.core.enums.LogLevel;
import java.util.List;
/**
* <p>Title : InitJar</p>
* <p>Description : InitJar</p>
* <p>DevelopTools : Idea_x64_v2026.1</p>
* <p>DevelopSystem : macOS Sequoia 15.7.5</p>
* <p>Company : org.xujun</p>
*
* @author : XuJun
* @version : 1.0.0
* @date : 2026/2/2 14:13
*/
@Component
@Order(BaseParams.CP_NUM200)
public class InitJar implements ApplicationRunner {
/**
* 应用名称
*/
@Value("${spring.application.name:xtools-app}")
private String name;
@Resource
private RedisService redisService;
@Override
public void run(@NonNull ApplicationArguments args) {
ScopedValue.where(LogTrackHolder.getScoped(), LogTrackHolder.newMain()).run(() -> {
try {
init();
} catch (Exception e) {
LogBus.init(LogLevel.ERROR, LogBusBaseType.OTHER).title("初始化Jar异常").error(e).save();
}
});
}
/**
* 初始化
*/
private void init() {
List<String> jarNameList = JarUtils.getJarName();
if (CollectionUtils.isEmpty(jarNameList)) {
return;
}
String key = AppCache.SYS_CACHE_JAR.key() + name;
redisService.set(key, jarNameList);
}
}

View File

@@ -0,0 +1,52 @@
package xtools.app.common.jar.utils;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import xtools.app.common.cache.enums.AppCache;
import xtools.base.config.BaseParams;
import xtools.boot.cache.redis.utils.RedisUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
/**
* <p>Title : RunJarUtils</p>
* <p>Description : RunJarUtils</p>
* <p>DevelopTools : Idea_x64_v2026.1</p>
* <p>DevelopSystem : macOS Sequoia 15.7.5</p>
* <p>Company : org.xujun</p>
*
* @author : XuJun
* @version : 1.0.0
* @date : 2026/2/18 21:11
*/
public class RunJarUtils implements BaseParams {
/**
* 缓存参数
*/
private static final AppCache CACHE_PARAM = AppCache.SYS_CACHE_JAR;
/**
* 获取运行中的Jar
*/
public static List<JSONObject> get() {
String cacheKey = AppCache.SYS_CACHE_JAR.key();
Set<String> keys = RedisUtils.get().getByPattern(cacheKey + CP_ASTERISK);
List<JSONObject> dataList = new ArrayList<>();
for (String key : keys) {
JSONArray cacheData = RedisUtils.get().get(key, JSONArray.class);
if (Objects.isNull(cacheData) || cacheData.isEmpty()) {
continue;
}
JSONObject data = new JSONObject();
data.put("name", key.replace(cacheKey, CP_EMPTY));
data.put("jars", cacheData);
dataList.add(data);
}
return dataList;
}
}

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.xujun</groupId>
<artifactId>xtools-app-common</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>xtools-app-common-job</artifactId>
<!-- 依赖 -->
<dependencies>
<!-- 项目模块 begin -->
<dependency>
<groupId>org.xujun</groupId>
<artifactId>xtools-app-common-cache</artifactId>
</dependency>
<!-- 项目模块 end -->
</dependencies>
</project>

View File

@@ -0,0 +1,133 @@
package xtools.app.common.job.base;
import xtools.app.common.cache.enums.AppCache;
import xtools.base.config.BaseParams;
import xtools.boot.cache.redis.base.RedisService;
import xtools.boot.cache.redis.utils.RedisUtils;
import xtools.boot.core.interfaces.JobInterface;
import xtools.boot.log.LogBus;
import xtools.boot.log.enums.LogBusBaseType;
import xtools.boot.log.holder.LogTrackHolder;
import xtools.core.UuidUtils;
import xtools.core.enums.LogLevel;
import xtools.core.extend.CheckUtils;
import xtools.core.time.InstantUtils;
import java.time.Instant;
import java.util.Objects;
/**
* <p>Title : BaseJob</p>
* <p>Description : BaseJob</p>
* <p>DevelopTools : Idea_x64_v2026.1</p>
* <p>DevelopSystem : macOS Sequoia 15.7.5</p>
* <p>Company : org.xujun</p>
*
* @author : XuJun
* @version : 1.0.0
* @date : 2026/2/23 17:36
*/
public abstract class BaseJob implements Runnable, BaseParams, JobInterface {
/**
* 锁参数
*/
private static final AppCache LOCK_PARAM = AppCache.LOCK_JOB;
/**
* 运行作业
*/
@Override
public void run() {
ScopedValue.where(LogTrackHolder.getScoped(), LogTrackHolder.newMain()).run(this::exec);
}
/**
* 执行作业
*/
private void exec() {
// 获取执行的class名称
String className = getClass().getSimpleName();
// 标题
String title = "[" + className + "]";
// 获取本次作业名称
String jobName = null;
// 获取redis服务
RedisService redisService = null;
// 锁
boolean locked = false;
try {
// 记录日志
LogBus.init(LogLevel.INFO, LogBusBaseType.JOB).title(title + "开始执行").save();
jobName = className + CP_LINE + InstantUtils.format(Instant.now(), "yyyyMMddHHmmssSSS") + CP_LINE + UuidUtils.get();
redisService = RedisUtils.get();
// 获取超时时间
Long expireTime = expireTime();
if (!CheckUtils.id(expireTime)) {
expireTime = LOCK_PARAM.expireTime();
}
// 加锁
locked = redisService.tryLock(LOCK_PARAM.key() + className, jobName, expireTime);
if (!locked) {
LogBus.init(LogLevel.INFO, LogBusBaseType.JOB).title(title + "已存在").save();
return;
}
runJob();
} catch (Exception e) {
LogBus.init(LogLevel.ERROR, LogBusBaseType.JOB).title(title + "运行异常").error(e).save();
} finally {
if (Objects.nonNull(redisService) && locked) {
boolean released = redisService.releaseLock(LOCK_PARAM.key() + className, jobName);
if (!released) {
LogBus.init(LogLevel.ERROR, LogBusBaseType.JOB).title(title + "锁释放异常").save();
} else {
LogBus.init(LogLevel.INFO, LogBusBaseType.JOB).title(title + "执行成功").save();
}
}
}
}
/**
* 执行任务
*/
@Override
public void execute() {
// 标题
String title = "[" + getClass().getSimpleName() + "]";
ScopedValue.where(LogTrackHolder.getScoped(), LogTrackHolder.newMain()).run(() -> {
Exception e = null;
try {
// 记录日志
LogBus.init(LogLevel.INFO, LogBusBaseType.JOB).title(title + "开始执行").save();
runJob();
} catch (Exception ex) {
e = ex;
} finally {
if (Objects.nonNull(e)) {
LogBus.init(LogLevel.ERROR, LogBusBaseType.JOB).title(title + "运行异常").error(e).save();
} else {
LogBus.init(LogLevel.INFO, LogBusBaseType.JOB).title(title + "执行成功").save();
}
}
});
}
/**
* 获取锁超时时间
*
* @return 锁超时时间
*/
public Long expireTime() {
return null;
}
/**
* 运行作业
*
* @throws Exception 运行异常
*/
public abstract void runJob() throws Exception;
}

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.xujun</groupId>
<artifactId>xtools-app-common</artifactId>
<version>1.0.0</version>
</parent>
<packaging>pom</packaging>
<artifactId>xtools-app-common-log</artifactId>
<!-- 子模块 -->
<modules>
<module>xtools-app-common-log-bus</module>
<module>xtools-app-common-log-filter</module>
</modules>
</project>

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.xujun</groupId>
<artifactId>xtools-app-common-log</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>xtools-app-common-log-bus</artifactId>
<!-- 依赖 -->
<dependencies>
<!-- xtools begin -->
<!-- xtools-boot-log -->
<dependency>
<groupId>org.xujun</groupId>
<artifactId>xtools-boot-log</artifactId>
</dependency>
<!-- xtools end -->
<!-- 项目模块 begin -->
<dependency>
<groupId>org.xujun</groupId>
<artifactId>xtools-app-common-mq</artifactId>
</dependency>
<!-- 项目模块 end -->
</dependencies>
</project>

View File

@@ -0,0 +1,71 @@
package xtools.app.common.log.bus.enums;
import xtools.boot.api.enums.BaseEnum;
import xtools.boot.log.interfaces.LogBusType;
/**
* <p>Title : SysLogType</p>
* <p>Description : SysLogType</p>
* <p>DevelopTools : Idea_x64_v2026.1</p>
* <p>DevelopSystem : macOS Sequoia 15.7.5</p>
* <p>Company : org.xujun</p>
*
* @author : XuJun
* @version : 1.0.0
* @date : 2026/2/3 11:26
*/
public enum SysLogType implements LogBusType {
;
/**
* 编码
**/
private final int code;
/**
* 说明
**/
private final String desc;
/**
* 初始化方法
*
* @param code Code
* @param desc 说明
*/
SysLogType(int code, String desc) {
this.code = code;
this.desc = desc;
}
/**
* 获取所有枚举
*
* @return 所有枚举
*/
@Override
public BaseEnum[] all() {
return values();
}
/**
* 获取枚举编码
*
* @return 枚举编码
*/
@Override
public int code() {
return code + BASE_CODE;
}
/**
* 获取枚举说明
*
* @return 枚举说明
*/
@Override
public String desc() {
return desc;
}
}

View File

@@ -0,0 +1,54 @@
package xtools.app.common.log.bus.handle;
import org.springframework.stereotype.Component;
import xtools.app.common.log.bus.service.LogBusService;
import xtools.app.common.mq.enums.RabbitMqEnums;
import xtools.boot.core.utils.SpringContextUtils;
import xtools.boot.log.interfaces.LogBusInterface;
import xtools.boot.log.model.dto.LogBody;
import xtools.boot.mq.base.utils.MqBus;
import java.util.Objects;
/**
* <p>Title : LogBusHandle</p>
* <p>Description : LogBusHandle</p>
* <p>DevelopTools : Idea_x64_v2026.1</p>
* <p>DevelopSystem : macOS Sequoia 15.7.5</p>
* <p>Company : org.xujun</p>
*
* @author : XuJun
* @version : 1.0.0
* @date : 2026/2/3 17:01
*/
@Component
public class LogBusHandle implements LogBusInterface {
/**
* 日志服务
*/
private static LogBusService logBusService;
/**
* 是否使用本地服务
*/
private static Boolean localService;
/**
* 保存日志
*
* @param logBody 日志
*/
@Override
public void save(LogBody logBody) {
if (Objects.isNull(localService)) {
logBusService = SpringContextUtils.getBeanDefNull(LogBusService.class);
localService = Objects.nonNull(logBusService);
}
if (localService) {
logBusService.saveLog(logBody);
} else {
MqBus.push(RabbitMqEnums.SYS_LOG, logBody);
}
}
}

View File

@@ -0,0 +1,25 @@
package xtools.app.common.log.bus.service;
import xtools.boot.log.model.dto.LogBody;
/**
* <p>Title : LogBusService</p>
* <p>Description : LogBusService</p>
* <p>DevelopTools : Idea_x64_v2026.1</p>
* <p>DevelopSystem : macOS Sequoia 15.7.5</p>
* <p>Company : org.xujun</p>
*
* @author : XuJun
* @version : 1.0.0
* @date : 2026/2/7 19:41
*/
public interface LogBusService {
/**
* 保存日志
*
* @param logBody 日志
*/
void saveLog(LogBody logBody);
}

View File

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.xujun</groupId>
<artifactId>xtools-app-common-log</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>xtools-app-common-log-filter</artifactId>
<!-- 依赖 -->
<dependencies>
<!-- xtools begin -->
<!-- xtools-extend -->
<dependency>
<groupId>org.xujun</groupId>
<artifactId>xtools-extend</artifactId>
</dependency>
<!-- xtools-web -->
<dependency>
<groupId>org.xujun</groupId>
<artifactId>xtools-web</artifactId>
</dependency>
<!-- xtools-boot-web-filter -->
<dependency>
<groupId>org.xujun</groupId>
<artifactId>xtools-boot-web-filter</artifactId>
</dependency>
<!-- xtools end -->
<!-- 项目模块 begin -->
<!-- xtools-app-common-log-bus -->
<dependency>
<groupId>org.xujun</groupId>
<artifactId>xtools-app-common-log-bus</artifactId>
</dependency>
<!-- 项目模块 end -->
<!-- fastjson2 -->
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,177 @@
package xtools.app.common.log.filter;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.jspecify.annotations.NonNull;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.util.ContentCachingRequestWrapper;
import org.springframework.web.util.ContentCachingResponseWrapper;
import xtools.app.common.log.whitelist.HttpLogWhitelist;
import xtools.base.config.BaseParams;
import xtools.boot.api.constant.BootCommonConstant;
import xtools.boot.core.utils.PathPatternUtils;
import xtools.boot.core.utils.SpringContextUtils;
import xtools.boot.log.LogBus;
import xtools.boot.log.enums.LogBusBaseType;
import xtools.boot.web.filter.base.BaseFilter;
import xtools.core.CollectionUtils;
import xtools.core.enums.LogLevel;
import xtools.web.HeaderUtils;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
/**
* <p>Title : HttpLogFilter</p>
* <p>Description : HttpLogFilter</p>
* <p>DevelopTools : Idea_x64_v2026.1</p>
* <p>DevelopSystem : macOS Sequoia 15.7.5</p>
* <p>Company : org.xujun</p>
*
* @author : XuJun
* @version : 1.0.0
* @date : 2026/1/6 16:37
*/
@Component
public class HttpLogFilter extends BaseFilter implements Ordered, BaseParams {
/**
* 日志白名单
*/
private static final Set<String> LOG_WHITE_LIST = new HashSet<>();
/**
* 响应体白名单
*/
private static final Set<String> RESP_WHITE_LIST = new HashSet<>();
/**
* 缓存大小
*/
private static final int DEFAULT_CACHE_LIMIT = 1024 * 1024;
@Override
public int getOrder() {
return CP_NUM200;
}
@Override
protected void initFilterBean() throws ServletException {
super.initFilterBean();
Collection<HttpLogWhitelist> beanList = SpringContextUtils.getBeanList(HttpLogWhitelist.class);
if (CollectionUtils.isEmpty(beanList)) {
return;
}
beanList.forEach(item -> {
LOG_WHITE_LIST.addAll(item.ignoreLog());
RESP_WHITE_LIST.addAll(item.ignoreResp());
});
}
@Override
protected void doFilterInternal(
@NonNull HttpServletRequest request,
@NonNull HttpServletResponse response,
@NonNull FilterChain filterChain
) throws ServletException, IOException {
long startTime = System.currentTimeMillis();
// 获取访问 uri
String uri = HeaderUtils.getUri(request);
if (PathPatternUtils.match(LOG_WHITE_LIST, uri)) {
filterChain.doFilter(request, response);
return;
}
// 获取请求日志
JSONObject log = getRequestLog(request);
// 记录请求日志
LogBus.init(LogLevel.INFO, LogBusBaseType.HTTP_REQUEST).data(log).save();
// 包装请求和响应
ContentCachingRequestWrapper requestWrapper = new ContentCachingRequestWrapper(request, DEFAULT_CACHE_LIMIT);
ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper(response);
// 处理请求
filterChain.doFilter(requestWrapper, responseWrapper);
// 获取请求参数
Object reqParam = getContent(requestWrapper.getContentAsByteArray());
log.put("reqBody", reqParam);
// 处理异常日志
LogLevel level = LogLevel.INFO;
if (!PathPatternUtils.match(RESP_WHITE_LIST, uri)) {
// 获取响应内容
Object respData = getContent(responseWrapper.getContentAsByteArray());
log.put("respData", respData);
if (respData instanceof JSONObject respJson) {
Boolean success = respJson.getBoolean("success");
if (Objects.equals(success, false)) {
level = LogLevel.ERROR;
}
}
}
long endTime = System.currentTimeMillis();
log.put("execTime", endTime - startTime);
// 将内容复制回原始响应
responseWrapper.copyBodyToResponse();
// 记录响应日志
LogBus.init(level, LogBusBaseType.HTTP_RESPONSE).data(log).save();
}
/**
* 获取内容
*
* @param content 内容
* @return 内容
*/
@NonNull
private Object getContent(byte[] content) {
if (Objects.isNull(content) || content.length == CP_NUM0) {
return "empty";
}
String data = new String(content, StandardCharsets.UTF_8);
try {
return JSONObject.parseObject(data);
} catch (Exception e) {
// ignore
}
try {
return JSONArray.parse(data);
} catch (Exception e) {
// ignore
}
return data;
}
/**
* 获取请求日志
*
* @param request 请求
* @return 请求日志
*/
public JSONObject getRequestLog(HttpServletRequest request) {
// 基础日志信息
JSONObject log = new JSONObject();
log.put("uri", HeaderUtils.getUri(request));
log.put("method", request.getMethod());
log.put("query", HeaderUtils.getQuery(request));
log.put("params", HeaderUtils.getParamsToString(request));
log.put("userAgent", HeaderUtils.getUserAgent(request));
log.put("referer", HeaderUtils.getReferer(request));
log.put("ip", HeaderUtils.getIp(request));
log.put(BootCommonConstant.UID, HeaderUtils.getRequestParam(request, BootCommonConstant.UID));
log.put(BootCommonConstant.AUTHORIZATION, HeaderUtils.getRequestParam(request, BootCommonConstant.AUTHORIZATION));
return log;
}
}

View File

@@ -0,0 +1,36 @@
package xtools.app.common.log.whitelist;
import java.util.Set;
/**
* <p>Title : HttpLogWhitelist</p>
* <p>Description : HttpLogWhitelist</p>
* <p>DevelopTools : Idea_x64_v2026.1</p>
* <p>DevelopSystem : macOS Sequoia 15.7.5</p>
* <p>Company : org.xujun</p>
*
* @author : XuJun
* @version : 1.0.0
* @date : 2026/4/2 14:36
*/
public interface HttpLogWhitelist {
/**
* 添加日志白名单
*
* @return 日志白名单
*/
default Set<String> ignoreLog() {
return Set.of();
}
/**
* 添加响应体白名单
*
* @return 响应体白名单
*/
default Set<String> ignoreResp() {
return Set.of();
}
}

View File

@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.xujun</groupId>
<artifactId>xtools-app-common</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>xtools-app-common-mq</artifactId>
<!-- 依赖 -->
<dependencies>
<!-- xtools begin -->
<!-- xtools-boot-mq-base -->
<dependency>
<groupId>org.xujun</groupId>
<artifactId>xtools-boot-mq-base</artifactId>
</dependency>
<!-- xtools-boot-mq-rabbit -->
<dependency>
<groupId>org.xujun</groupId>
<artifactId>xtools-boot-mq-rabbit</artifactId>
</dependency>
<!-- xtools end -->
<!-- 项目模块 begin -->
<dependency>
<groupId>org.xujun</groupId>
<artifactId>xtools-app-common-cache</artifactId>
</dependency>
<!-- 项目模块 end -->
</dependencies>
</project>

View File

@@ -0,0 +1,65 @@
package xtools.app.common.mq.enums;
import xtools.boot.mq.base.enums.MqEnums;
/**
* <p>Title : RabbitMqEnums</p>
* <p>Description : RabbitMqEnums</p>
* <p>DevelopTools : Idea_x64_v2026.1</p>
* <p>DevelopSystem : macOS Sequoia 15.7.5</p>
* <p>Company : org.xujun</p>
*
* @author : XuJun
* @version : 1.0.0
* @date : 2026/2/5 16:46
*/
public enum RabbitMqEnums implements MqEnums {
// 系统日志
SYS_LOG("sys.log", false),
// 系统任务
SYS_TASK("sys.task", true),
;
/**
* 队列名称
*/
private final String queue;
/**
* 是否保存日志
*/
private final boolean saveLog;
/**
* 构造方法
*
* @param queue 队列名称
* @param saveLog 是否保存日志
*/
RabbitMqEnums(String queue, boolean saveLog) {
this.queue = queue;
this.saveLog = saveLog;
}
/**
* 获取队列名称
*
* @return 队列名称
*/
@Override
public String queue() {
return queue;
}
/**
* 是否保存日志
*
* @return 是否保存日志
*/
@Override
public boolean saveLog() {
return saveLog;
}
}

View File

@@ -0,0 +1,57 @@
package xtools.app.common.mq.handle;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import xtools.app.common.cache.enums.AppCache;
import xtools.base.config.BaseParams;
import xtools.boot.cache.redis.base.RedisService;
import xtools.boot.mq.base.handle.BaseErrorHandle;
import xtools.extend.encrypt.Sm3Utils;
/**
* <p>Title : MqErrorHandle</p>
* <p>Description : MqErrorHandle</p>
* <p>DevelopTools : Idea_x64_v2026.1</p>
* <p>DevelopSystem : macOS Sequoia 15.7.5</p>
* <p>Company : org.xujun</p>
*
* @author : XuJun
* @version : 1.0.0
* @date : 2026/2/12 10:53
*/
@Slf4j
@Component
public class MqErrorHandle implements BaseErrorHandle, BaseParams {
/**
* 缓存参数
*/
private static final AppCache CACHE_PARAM = AppCache.MQ_MSG_ERR_COUNT;
@Resource
private RedisService redisService;
/**
* 消息处理错误异常(需要消息队列重推消息,抛出异常即可)
*
* @param message 消息内容
* @param exception 异常信息
*/
@Override
public void messageHandle(String message, Exception exception) {
String cacheKey = CACHE_PARAM.key() + Sm3Utils.encryptToString(message);
Long incr = redisService.incr(cacheKey);
redisService.expire(cacheKey, CACHE_PARAM.expireTime());
if (incr >= CP_NUM3) {
redisService.del(cacheKey);
} else {
try {
Thread.sleep(CP_NUM1000);
} catch (InterruptedException e) {
log.error("消息处理异常,等待失败", e);
}
throw new RuntimeException(exception);
}
}
}

View File

@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.xujun</groupId>
<artifactId>xtools-app-common</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>xtools-app-common-sentinel</artifactId>
<!-- 依赖 -->
<dependencies>
<!-- xtools begin -->
<!-- xtools-web -->
<dependency>
<groupId>org.xujun</groupId>
<artifactId>xtools-web</artifactId>
</dependency>
<!-- xtools end -->
<!-- 项目模块 begin -->
<!-- xtools-app-common-log-bus -->
<dependency>
<groupId>org.xujun</groupId>
<artifactId>xtools-app-common-log-bus</artifactId>
</dependency>
<!-- 项目模块 end -->
<!-- xtools-cloud-alibaba-sentinel -->
<dependency>
<groupId>org.xujun</groupId>
<artifactId>xtools-cloud-alibaba-sentinel</artifactId>
</dependency>
<!-- servlet-api -->
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,62 @@
package xtools.app.common.sentinel;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.fastjson2.JSONObject;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import xtools.boot.log.LogBus;
import xtools.boot.log.enums.LogBusBaseType;
import xtools.cloud.alibaba.sentinel.handler.CustomBlockExceptionHandler;
import xtools.core.enums.LogLevel;
import xtools.web.HeaderUtils;
/**
* <p>Title : SysBlockExceptionHandler</p>
* <p>Description : SysBlockExceptionHandler</p>
* <p>DevelopTools : Idea_x64_v2026.1</p>
* <p>DevelopSystem : Windows11</p>
* <p>Company : org.xujun</p>
*
* @author : XuJun
* @version : 1.0.0
* @date : 2026/4/14 21:54
*/
@Component
public class SysBlockExceptionHandler implements CustomBlockExceptionHandler {
/**
* 自定义Sentinel阻塞异常处理器
*
* @param request HttpServletRequest
* @param response HttpServletResponse
* @param resourceName 资源名称
* @param e BlockException
* @return 是否默认写出提示信息
*/
@Override
public boolean handle(
HttpServletRequest request,
HttpServletResponse response,
String resourceName,
BlockException e
) {
// 日志数据
JSONObject log = new JSONObject();
// IP
log.put("ip", HeaderUtils.getIp(request));
// URI
log.put("uri", HeaderUtils.getAllUri(request));
// 用户标识
log.put("userAgent", HeaderUtils.getUserAgent(request));
// 请求参数
log.put("params", HeaderUtils.getParams(request));
// 请求来源
log.put("referer", HeaderUtils.getReferer(request));
// 规则数据
log.put("rule", e.getRule());
// 保存日志
LogBus.init(LogLevel.WARN, LogBusBaseType.SENTINEL).error(e).data(log).save();
return true;
}
}

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.xujun</groupId>
<artifactId>xtools-app-common</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>xtools-app-common-task</artifactId>
<!-- 依赖 -->
<dependencies>
<!-- xtools begin -->
<!-- xtools-boot-task -->
<dependency>
<groupId>org.xujun</groupId>
<artifactId>xtools-boot-task</artifactId>
</dependency>
<!-- xtools end -->
<!-- 项目模块 begin -->
<dependency>
<groupId>org.xujun</groupId>
<artifactId>xtools-app-common-mq</artifactId>
</dependency>
<!-- 项目模块 end -->
</dependencies>
</project>

View File

@@ -0,0 +1,93 @@
package xtools.app.common.task.enums;
import xtools.boot.api.enums.BaseEnum;
import xtools.boot.task.interfaces.BaseTaskType;
/**
* <p>Title : TaskType</p>
* <p>Description : TaskType</p>
* <p>DevelopTools : Idea_x64_v2026.1</p>
* <p>DevelopSystem : macOS Sequoia 15.7.5</p>
* <p>Company : org.xujun</p>
*
* @author : XuJun
* @version : 1.0.0
* @date : 2026/2/15 10:29
*/
public enum TaskType implements BaseTaskType {
// 其他任务
OTHER(10, "其他任务"),
// 删除系统日志
DEL_SYS_LOG(20, "删除系统日志"),
// 删除系统文件
DEL_SYS_FILE(30, "删除系统文件"),
;
/**
* 编码
*/
private final int code;
/**
* 说明
*/
private final String desc;
/**
* 初始化方法
*
* @param code Code
* @param desc 说明
*/
TaskType(int code, String desc) {
this.code = code;
this.desc = desc;
}
/**
* 判断枚举值类型
*
* @param code 枚举值
* @return 枚举值类型
*/
public static TaskType valueOf(int code) {
for (TaskType type : values()) {
if (type.code == code) {
return type;
}
}
throw new IllegalArgumentException("unknown code, code=" + code);
}
/**
* 获取所有枚举
*
* @return 所有枚举
*/
@Override
public BaseEnum[] all() {
return values();
}
/**
* 获取枚举编码
*
* @return 枚举编码
*/
@Override
public int code() {
return code;
}
/**
* 获取枚举说明
*
* @return 枚举说明
*/
@Override
public String desc() {
return desc;
}
}

View File

@@ -0,0 +1,32 @@
package xtools.app.common.task.handle;
import org.springframework.stereotype.Component;
import xtools.app.common.mq.enums.RabbitMqEnums;
import xtools.boot.mq.base.utils.MqBus;
import xtools.boot.task.interfaces.TaskBusInterface;
import xtools.boot.task.model.dto.TaskInfo;
/**
* <p>Title : TaskBusHandle</p>
* <p>Description : TaskBusHandle</p>
* <p>DevelopTools : Idea_x64_v2026.1</p>
* <p>DevelopSystem : macOS Sequoia 15.7.5</p>
* <p>Company : org.xujun</p>
*
* @author : XuJun
* @version : 1.0.0
* @date : 2026/2/15 10:31
*/
@Component
public class TaskBusHandle implements TaskBusInterface {
/**
* 保存任务
*
* @param taskInfo 任务
*/
@Override
public void save(TaskInfo taskInfo) {
MqBus.push(RabbitMqEnums.SYS_TASK, taskInfo);
}
}