package com.example.demo.RabbitMQ; import com.example.demo.Util.SecurityUtils; import com.example.demo.config.RabbitMQConfig; import com.example.demo.config.interfac.Log; import com.example.demo.domain.DTO.OperationLogDTO; import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.servlet.http.HttpServletRequest; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import java.time.LocalDateTime; // com.example.demo.aspect.LogAspect.java @Aspect @Component @Slf4j public class LogAspect { @Autowired private RabbitTemplate rabbitTemplate; @Around("@annotation(com.example.demo.config.interfac.Log)") public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable { long startTime = System.currentTimeMillis(); MethodSignature signature = (MethodSignature) joinPoint.getSignature(); String methodName = signature.getName(); String className = signature.getDeclaringTypeName(); Object[] args = joinPoint.getArgs(); Log logAnnotation = signature.getMethod().getAnnotation(Log.class); String action = logAnnotation.value(); // ✅ 使用 Spring Security 获取真实用户 String username = SecurityUtils.getCurrentUsername(); Integer userId = SecurityUtils.getCurrentUserId(); // 添加空值检查 if (userId == null) { log.warn("无法获取当前用户ID,使用默认值 -1"); userId = -1; // 或者使用其他默认值 } String ip = getClientIp(); ObjectMapper mapper = new ObjectMapper(); String argsJson = "[]"; try { argsJson = mapper.writeValueAsString(args); } catch (Exception e) { argsJson = "serialize failed"; } Object result; try { result = joinPoint.proceed(); } catch (Exception e) { log.error("方法执行异常: {}", e.getMessage()); throw e; } long duration = System.currentTimeMillis() - startTime; // ✅ 构造日志消息 DTO OperationLogDTO logDTO = new OperationLogDTO(); logDTO.setUserId(userId); logDTO.setUsername(username); logDTO.setAction(action); logDTO.setIp(ip); logDTO.setMethod(methodName); logDTO.setArgs(argsJson); logDTO.setCreateTime(LocalDateTime.now()); System.out.println(logDTO); // ✅ 发送消息到 RabbitMQ(不等待) try { rabbitTemplate.convertAndSend(RabbitMQConfig.LOG_EXCHANGE, "log.save", logDTO); log.info("📩 日志消息已发送到 RabbitMQ: {}", action); } catch (Exception e) { log.error("发送日志消息到 RabbitMQ 失败", e); } log.info("✅ AOP 拦截完成: {} 执行 [{}] 耗时 {}ms", username, action, duration); return result; } private String getClientIp() { try { HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest(); 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(); } return ip.split(",")[0].trim(); // 多代理时取第一个 } catch (Exception e) { return "unknown"; } } }