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