From 9f97cab38f6726a789859a77d83772e92a8d48b3 Mon Sep 17 00:00:00 2001
From: zkh <1650697374@qq.com>
Date: Thu, 16 Apr 2026 12:19:51 +0800
Subject: [PATCH] =?UTF-8?q?feat(log):=20=E6=89=A9=E5=B1=95=E6=97=A5?=
=?UTF-8?q?=E5=BF=97=E6=9C=8D=E5=8A=A1=E6=94=AF=E6=8C=81=E6=93=8D=E4=BD=9C?=
=?UTF-8?q?=E6=97=A5=E5=BF=97=E4=B8=8A=E4=B8=8B=E6=96=87?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 在 ConsoleLogService 中新增 log(LogContext) 方法实现
- 更新 ILogService 接口添加 LogContext 参数的日志方法并提供默认实现
- 在 LogConfig 中添加 LogAspect 切面的异常处理和日志上下文构建功能
- 新增 LogContext 记录类用于封装完整的操作日志信息
- 在 zkh-log 模块中添加 jakarta.servlet-api 依赖以获取请求信息
- 更新所有模块的版本号从 1.5.11 到 1.5.12
---
pom.xml | 2 +-
zkh-common/pom.xml | 2 +-
zkh-data/pom.xml | 2 +-
zkh-file/pom.xml | 2 +-
zkh-log/pom.xml | 6 +-
.../java/vip/jcfd/log/ConsoleLogService.java | 22 +++-
.../main/java/vip/jcfd/log/ILogService.java | 13 ++-
.../main/java/vip/jcfd/log/LogContext.java | 27 +++++
.../java/vip/jcfd/log/config/LogConfig.java | 101 +++++++++++++-----
zkh-web/pom.xml | 2 +-
10 files changed, 143 insertions(+), 36 deletions(-)
create mode 100644 zkh-log/src/main/java/vip/jcfd/log/LogContext.java
diff --git a/pom.xml b/pom.xml
index d415a58..5c4e1f8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
vip.jcfd
zkh-framework
- 1.5.11
+ 1.5.12
pom
ZKH Framework
A Java framework for ZKH applications
diff --git a/zkh-common/pom.xml b/zkh-common/pom.xml
index 79922b5..c21dbcb 100644
--- a/zkh-common/pom.xml
+++ b/zkh-common/pom.xml
@@ -6,7 +6,7 @@
vip.jcfd
zkh-framework
- 1.5.11
+ 1.5.12
zkh-common
diff --git a/zkh-data/pom.xml b/zkh-data/pom.xml
index 90ca717..43fb7cf 100644
--- a/zkh-data/pom.xml
+++ b/zkh-data/pom.xml
@@ -6,7 +6,7 @@
vip.jcfd
zkh-framework
- 1.5.11
+ 1.5.12
zkh-data
diff --git a/zkh-file/pom.xml b/zkh-file/pom.xml
index 172d76c..3093cee 100644
--- a/zkh-file/pom.xml
+++ b/zkh-file/pom.xml
@@ -6,7 +6,7 @@
vip.jcfd
zkh-framework
- 1.5.11
+ 1.5.12
zkh-file
diff --git a/zkh-log/pom.xml b/zkh-log/pom.xml
index 49c9b9f..4495c37 100644
--- a/zkh-log/pom.xml
+++ b/zkh-log/pom.xml
@@ -6,7 +6,7 @@
vip.jcfd
zkh-framework
- 1.5.11
+ 1.5.12
zkh-log
@@ -14,6 +14,10 @@
Logging utilities for ZKH framework
+
+ jakarta.servlet
+ jakarta.servlet-api
+
org.springframework.boot
spring-boot-starter-aop
diff --git a/zkh-log/src/main/java/vip/jcfd/log/ConsoleLogService.java b/zkh-log/src/main/java/vip/jcfd/log/ConsoleLogService.java
index 9a669e6..81ed51e 100644
--- a/zkh-log/src/main/java/vip/jcfd/log/ConsoleLogService.java
+++ b/zkh-log/src/main/java/vip/jcfd/log/ConsoleLogService.java
@@ -5,10 +5,22 @@ import org.slf4j.LoggerFactory;
import org.springframework.security.core.Authentication;
public class ConsoleLogService implements ILogService {
- private final Logger logger = LoggerFactory.getLogger(ConsoleLogService.class);
+ private final Logger logger = LoggerFactory.getLogger(ConsoleLogService.class);
- @Override
- public void log(String message, Authentication authentication) {
- logger.debug("{} {}", authentication.getName(), message);
- }
+ @Override
+ public void log(String message, Authentication authentication) {
+ String operator = authentication != null ? authentication.getName() : "anonymous";
+ logger.debug("{} {}", operator, message);
+ }
+
+ @Override
+ public void log(LogContext context) {
+ if (context.status() == LogContext.SUCCESS) {
+ logger.debug("[操作日志] {} {} {} {} {}", context.operator(), context.httpMethod(),
+ context.requestUrl(), context.ip(), context.message());
+ } else {
+ logger.warn("[操作日志] {} {} {} {} {} 错误: {}", context.operator(), context.httpMethod(),
+ context.requestUrl(), context.ip(), context.message(), context.errorMessage());
+ }
+ }
}
diff --git a/zkh-log/src/main/java/vip/jcfd/log/ILogService.java b/zkh-log/src/main/java/vip/jcfd/log/ILogService.java
index e230005..32f8a7f 100644
--- a/zkh-log/src/main/java/vip/jcfd/log/ILogService.java
+++ b/zkh-log/src/main/java/vip/jcfd/log/ILogService.java
@@ -4,5 +4,16 @@ import org.springframework.security.core.Authentication;
public interface ILogService {
- void log(String message, Authentication authentication);
+ /**
+ * 记录日志(旧接口,保持向后兼容)
+ */
+ void log(String message, Authentication authentication);
+
+ /**
+ * 记录日志(新接口,带完整上下文)
+ */
+ default void log(LogContext context) {
+ // 默认实现:降级到旧接口
+ log(context.message(), null);
+ }
}
diff --git a/zkh-log/src/main/java/vip/jcfd/log/LogContext.java b/zkh-log/src/main/java/vip/jcfd/log/LogContext.java
new file mode 100644
index 0000000..1e362cc
--- /dev/null
+++ b/zkh-log/src/main/java/vip/jcfd/log/LogContext.java
@@ -0,0 +1,27 @@
+package vip.jcfd.log;
+
+/**
+ * 日志上下文,包含操作日志的完整信息
+ */
+public record LogContext(
+ String message,
+ String operator,
+ String requestUrl,
+ String httpMethod,
+ String ip,
+ int status,
+ String errorMessage
+) {
+ /** 操作状态:成功 */
+ public static final int SUCCESS = 0;
+ /** 操作状态:失败 */
+ public static final int FAIL = 1;
+
+ public static LogContext success(String message, String operator, String requestUrl, String httpMethod, String ip) {
+ return new LogContext(message, operator, requestUrl, httpMethod, ip, SUCCESS, null);
+ }
+
+ public static LogContext fail(String message, String operator, String requestUrl, String httpMethod, String ip, String errorMessage) {
+ return new LogContext(message, operator, requestUrl, httpMethod, ip, FAIL, errorMessage);
+ }
+}
diff --git a/zkh-log/src/main/java/vip/jcfd/log/config/LogConfig.java b/zkh-log/src/main/java/vip/jcfd/log/config/LogConfig.java
index 0c475b5..b1a9c5a 100644
--- a/zkh-log/src/main/java/vip/jcfd/log/config/LogConfig.java
+++ b/zkh-log/src/main/java/vip/jcfd/log/config/LogConfig.java
@@ -1,7 +1,9 @@
package vip.jcfd.log.config;
+import jakarta.servlet.http.HttpServletRequest;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
+import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
@@ -12,39 +14,90 @@ import org.springframework.core.annotation.Order;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
import vip.jcfd.log.ConsoleLogService;
import vip.jcfd.log.ILogService;
+import vip.jcfd.log.LogContext;
import vip.jcfd.log.annotation.Log;
@Configuration("_logConfiguration")
public class LogConfig {
- @Bean("_defaultLogService")
- @ConditionalOnMissingBean
- @Order
- public ILogService defaultLogService() {
- return new ConsoleLogService();
- }
+ @Bean("_defaultLogService")
+ @ConditionalOnMissingBean
+ @Order
+ public ILogService defaultLogService() {
+ return new ConsoleLogService();
+ }
- @Aspect
- @Component
- public static class LogAspect {
- private final ILogService logService;
+ @Aspect
+ @Component
+ public static class LogAspect {
+ private final ILogService logService;
- public LogAspect(ILogService logService) {
- this.logService = logService;
- }
+ public LogAspect(ILogService logService) {
+ this.logService = logService;
+ }
- @Pointcut("@annotation(vip.jcfd.log.annotation.Log)")
- public void logAspect() {
- }
+ @Pointcut("@annotation(vip.jcfd.log.annotation.Log)")
+ public void logAspect() {
+ }
- @AfterReturning(value = "logAspect()")
- public void afterReturning(JoinPoint joinPoint) {
- MethodSignature signature = (MethodSignature) joinPoint.getSignature();
- Log log = signature.getMethod().getAnnotation(Log.class);
- Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
- logService.log(log.value(), authentication);
- }
- }
+ @AfterReturning(value = "logAspect()")
+ public void afterReturning(JoinPoint joinPoint) {
+ LogContext context = buildLogContext(joinPoint, null);
+ logService.log(context);
+ }
+
+ @AfterThrowing(value = "logAspect()", throwing = "ex")
+ public void afterThrowing(JoinPoint joinPoint, Exception ex) {
+ LogContext context = buildLogContext(joinPoint, ex.getMessage());
+ logService.log(context);
+ }
+
+ private LogContext buildLogContext(JoinPoint joinPoint, String errorMessage) {
+ MethodSignature signature = (MethodSignature) joinPoint.getSignature();
+ Log log = signature.getMethod().getAnnotation(Log.class);
+
+ Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+ String operator = authentication != null ? authentication.getName() : "anonymous";
+
+ String requestUrl = "";
+ String httpMethod = "";
+ String ip = "";
+
+ ServletRequestAttributes attributes =
+ (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
+ if (attributes != null) {
+ HttpServletRequest request = attributes.getRequest();
+ requestUrl = request.getRequestURI();
+ httpMethod = request.getMethod();
+ ip = getClientIp(request);
+ }
+
+ if (errorMessage != null) {
+ return LogContext.fail(log.value(), operator, requestUrl, httpMethod, ip, errorMessage);
+ }
+ return LogContext.success(log.value(), operator, requestUrl, httpMethod, ip);
+ }
+
+ private String getClientIp(HttpServletRequest request) {
+ String ip = request.getHeader("X-Forwarded-For");
+ if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
+ ip = request.getHeader("Proxy-Client-IP");
+ }
+ if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
+ ip = request.getHeader("WL-Proxy-Client-IP");
+ }
+ if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
+ ip = request.getRemoteAddr();
+ }
+ // X-Forwarded-For 可能包含多个 IP,取第一个
+ if (ip != null && ip.contains(",")) {
+ ip = ip.split(",")[0].trim();
+ }
+ return ip;
+ }
+ }
}
diff --git a/zkh-web/pom.xml b/zkh-web/pom.xml
index 5687107..748412e 100644
--- a/zkh-web/pom.xml
+++ b/zkh-web/pom.xml
@@ -7,7 +7,7 @@
vip.jcfd
zkh-framework
- 1.5.11
+ 1.5.12
zkh-web