|
|
|
|
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());
|
|
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|