初始化项目
This commit is contained in:
20
xtools-app-common/xtools-app-common-log/pom.xml
Normal file
20
xtools-app-common/xtools-app-common-log/pom.xml
Normal 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>
|
||||
@@ -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>
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user