Compare commits

...
3 Commits
Author SHA1 Message Date
zkh 9f97cab38f feat(log): 扩展日志服务支持操作日志上下文
- 在 ConsoleLogService 中新增 log(LogContext) 方法实现
- 更新 ILogService 接口添加 LogContext 参数的日志方法并提供默认实现
- 在 LogConfig 中添加 LogAspect 切面的异常处理和日志上下文构建功能
- 新增 LogContext 记录类用于封装完整的操作日志信息
- 在 zkh-log 模块中添加 jakarta.servlet-api 依赖以获取请求信息
- 更新所有模块的版本号从 1.5.11 到 1.5.12
2026-04-16 12:19:51 +08:00
zkh 9e75d3b392 chore(version): 更新框架版本号
- 将 zkh-framework 父项目版本从 1.5.10 升级到 1.5.11
- 同步更新 zkh-common 模块依赖版本至 1.5.11
- 同步更新 zkh-data 模块依赖版本至 1.5.11
- 同步更新 zkh-file 模块依赖版本至 1.5.11
- 同步更新 zkh-log 模块依赖版本至 1.5.11
- 同步更新 zkh-web 模块依赖版本至 1.5.11
2026-02-24 11:25:41 +08:00
zkh 42228c63a5 refactor(error): 优化全局异常处理器配置
- 移除未使用的 HttpStatus 和 ResponseStatus 注解导入
- 简化 RestControllerAdvice 注解配置,移除不必要的 bean 名称参数
- 保持原有的全局异常处理功能不变
- 提高代码简洁性和可读性
2026-02-24 11:23:55 +08:00
11 changed files with 144 additions and 39 deletions
+1 -1
View File
@@ -6,7 +6,7 @@
<groupId>vip.jcfd</groupId> <groupId>vip.jcfd</groupId>
<artifactId>zkh-framework</artifactId> <artifactId>zkh-framework</artifactId>
<version>1.5.10</version> <version>1.5.12</version>
<packaging>pom</packaging> <packaging>pom</packaging>
<name>ZKH Framework</name> <name>ZKH Framework</name>
<description>A Java framework for ZKH applications</description> <description>A Java framework for ZKH applications</description>
+1 -1
View File
@@ -6,7 +6,7 @@
<parent> <parent>
<groupId>vip.jcfd</groupId> <groupId>vip.jcfd</groupId>
<artifactId>zkh-framework</artifactId> <artifactId>zkh-framework</artifactId>
<version>1.5.10</version> <version>1.5.12</version>
</parent> </parent>
<artifactId>zkh-common</artifactId> <artifactId>zkh-common</artifactId>
+1 -1
View File
@@ -6,7 +6,7 @@
<parent> <parent>
<groupId>vip.jcfd</groupId> <groupId>vip.jcfd</groupId>
<artifactId>zkh-framework</artifactId> <artifactId>zkh-framework</artifactId>
<version>1.5.10</version> <version>1.5.12</version>
</parent> </parent>
<artifactId>zkh-data</artifactId> <artifactId>zkh-data</artifactId>
+1 -1
View File
@@ -6,7 +6,7 @@
<parent> <parent>
<groupId>vip.jcfd</groupId> <groupId>vip.jcfd</groupId>
<artifactId>zkh-framework</artifactId> <artifactId>zkh-framework</artifactId>
<version>1.5.10</version> <version>1.5.12</version>
</parent> </parent>
<artifactId>zkh-file</artifactId> <artifactId>zkh-file</artifactId>
+5 -1
View File
@@ -6,7 +6,7 @@
<parent> <parent>
<groupId>vip.jcfd</groupId> <groupId>vip.jcfd</groupId>
<artifactId>zkh-framework</artifactId> <artifactId>zkh-framework</artifactId>
<version>1.5.10</version> <version>1.5.12</version>
</parent> </parent>
<artifactId>zkh-log</artifactId> <artifactId>zkh-log</artifactId>
@@ -14,6 +14,10 @@
<description>Logging utilities for ZKH framework</description> <description>Logging utilities for ZKH framework</description>
<dependencies> <dependencies>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId> <artifactId>spring-boot-starter-aop</artifactId>
@@ -9,6 +9,18 @@ public class ConsoleLogService implements ILogService {
@Override @Override
public void log(String message, Authentication authentication) { public void log(String message, Authentication authentication) {
logger.debug("{} {}", authentication.getName(), message); 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());
}
} }
} }
@@ -4,5 +4,16 @@ import org.springframework.security.core.Authentication;
public interface ILogService { public interface ILogService {
/**
* 记录日志(旧接口,保持向后兼容)
*/
void log(String message, Authentication authentication); void log(String message, Authentication authentication);
/**
* 记录日志(新接口,带完整上下文)
*/
default void log(LogContext context) {
// 默认实现:降级到旧接口
log(context.message(), null);
}
} }
@@ -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);
}
}
@@ -1,7 +1,9 @@
package vip.jcfd.log.config; package vip.jcfd.log.config;
import jakarta.servlet.http.HttpServletRequest;
import org.aspectj.lang.JoinPoint; import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature; import org.aspectj.lang.reflect.MethodSignature;
@@ -12,8 +14,11 @@ import org.springframework.core.annotation.Order;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component; 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.ConsoleLogService;
import vip.jcfd.log.ILogService; import vip.jcfd.log.ILogService;
import vip.jcfd.log.LogContext;
import vip.jcfd.log.annotation.Log; import vip.jcfd.log.annotation.Log;
@Configuration("_logConfiguration") @Configuration("_logConfiguration")
@@ -41,10 +46,58 @@ public class LogConfig {
@AfterReturning(value = "logAspect()") @AfterReturning(value = "logAspect()")
public void afterReturning(JoinPoint joinPoint) { 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(); MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Log log = signature.getMethod().getAnnotation(Log.class); Log log = signature.getMethod().getAnnotation(Log.class);
Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
logService.log(log.value(), authentication); 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;
} }
} }
} }
+1 -1
View File
@@ -7,7 +7,7 @@
<parent> <parent>
<groupId>vip.jcfd</groupId> <groupId>vip.jcfd</groupId>
<artifactId>zkh-framework</artifactId> <artifactId>zkh-framework</artifactId>
<version>1.5.10</version> <version>1.5.12</version>
</parent> </parent>
<artifactId>zkh-web</artifactId> <artifactId>zkh-web</artifactId>
@@ -4,13 +4,11 @@ import jakarta.validation.ConstraintViolationException;
import jakarta.validation.ValidationException; import jakarta.validation.ValidationException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException; import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult; import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError; import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.resource.NoResourceFoundException; import org.springframework.web.servlet.resource.NoResourceFoundException;
import vip.jcfd.common.core.BizException; import vip.jcfd.common.core.BizException;
@@ -19,7 +17,7 @@ import vip.jcfd.common.core.R;
import java.util.List; import java.util.List;
@RestControllerAdvice("_globalExceptionHandler") @RestControllerAdvice
public class GlobalExceptionHandler { public class GlobalExceptionHandler {
private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class); private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);