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.

117 lines
4.6 KiB

package com.project.operation.aop;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.project.base.domain.result.Result;
import com.project.ding.domain.dto.LoginDTO;
import com.project.ding.utils.JwtUtils;
import com.project.operation.annotation.OperationLog;
import com.project.operation.application.impl.OperationLogApplicationService;
import com.project.operation.domain.dto.OperationLogDTO;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
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.lang.reflect.Method;
/**
* 操作日志AOP切面
*/
@Slf4j
@Aspect
@Component
@RequiredArgsConstructor
public class OperationLogAspect {
@Autowired
private JwtUtils jwtUtils;
@Autowired
private OperationLogApplicationService operationLogApplicationService;
private final ThreadLocal<OperationLogDTO> operationLogDTOThreadLocal = new ThreadLocal<>();
//定义切点,拦截所有添加@OperationLog注解的方法
@Pointcut("@annotation(com.project.operation.annotation.OperationLog)")
public void pointcutOperationLog() {}
//环绕通知,在方法执行前后拦截,收集日志
@Around("pointcutOperationLog()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
//获取开始时间
long startTime = System.currentTimeMillis();
OperationLogDTO operationLogDTO = new OperationLogDTO();
//获取客户端IP和操作用户
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (requestAttributes != null) {
HttpServletRequest request = requestAttributes.getRequest();
operationLogDTO.setClientIp(request.getRemoteAddr());
String header = request.getHeader("Authorization");
if (StringUtils.isNotBlank(header) && header.startsWith("Bearer ")) {
String token = header.substring(7);
String userId = jwtUtils.parseToken(token).getSubject();
operationLogDTO.setCreatorId(Long.parseLong(userId));
}
}
//获取方法信息
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
// 方法全路径:包名+类名+方法名
operationLogDTO.setMethod(method.getDeclaringClass().getName() + "." + method.getName());
//获取操作信息
OperationLog annotation = method.getAnnotation(OperationLog.class);
operationLogDTO.setModule(annotation.module());
7 months ago
operationLogDTO.setAction(annotation.action());
operationLogDTO.setDescription(annotation.description());
Object businessResult;
try {
operationLogDTOThreadLocal.set(operationLogDTO);
businessResult = joinPoint.proceed();
operationLogDTO.setResult(0);
}catch (Exception e){
operationLogDTO.setResult(1);
operationLogDTO.setException(e.getMessage());
throw e;
}finally {
operationLogDTO.setCostTime(System.currentTimeMillis() - startTime);
//保存日志
operationLogApplicationService.saveOperationLog(operationLogDTO);
}
return businessResult;
}
@AfterReturning(returning = "result",pointcut = "pointcutOperationLog()")
public void afterReturning(Object result) throws Throwable {
OperationLogDTO operationLogDTO = operationLogDTOThreadLocal.get();
if (operationLogDTO == null) {
return; // 无上下文,直接返回
}
try {
//获取当前登陆用户
if(operationLogDTO.getMethod().contains("getToken") && result instanceof Result){
LoginDTO data = ((Result<LoginDTO>) result).getData();
String userId = jwtUtils.parseToken(data.getToken()).getSubject();
operationLogDTO.setCreatorId(Long.parseLong(userId));
}
}finally {
operationLogDTOThreadLocal.remove();
}
}
}