package com.project.operation.aop; import cn.hutool.core.util.EnumUtil; 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 com.project.operation.domain.enums.ModuleEnum; import com.project.operation.domain.service.impl.description.DescriptionManager; 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; @Autowired private DescriptionManager descriptionManager; private final ThreadLocal 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()); ModuleEnum moduleEnum = ModuleEnum.findByValue(annotation.module()); if(moduleEnum != null){ descriptionManager.process(moduleEnum.name(),joinPoint.getArgs(),operationLogDTO,method.getName()); }else{ 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("login") && result instanceof Result){ LoginDTO data = ((Result) result).getData(); String userId = jwtUtils.parseToken(data.getToken()).getSubject(); operationLogDTO.setCreatorId(Long.parseLong(userId)); } }finally { operationLogDTOThreadLocal.remove(); } } }