You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
113 lines
4.1 KiB
113 lines
4.1 KiB
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";
|
|
}
|
|
}
|
|
}
|