LogAspect.java 3.39 KB
package vion.advice;

import cn.dev33.satoken.stp.StpUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.dromara.hutool.core.lang.Opt;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.core.util.ObjUtil;
import org.dromara.hutool.http.server.servlet.ServletUtil;
import org.slf4j.MDC;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import vion.utils.ip.IPUtil;
import vion.vo.UserVO;

/**
 * @author vion
 * @date 2024/1/17
 */
@Component
@RequiredArgsConstructor
@Aspect
@Slf4j
public class LogAspect {

    private final ObjectMapper objectMapper;

    @Pointcut("execution(* vion.controller..*.*(..))")
    public void logPointcut() {
    }

    @Before("logPointcut()")
    public void doBefore(JoinPoint joinPoint) throws JsonProcessingException {
        // 登录等接口,无需登录可访问,根据 token 获取当前用户会抛未登录的异常,需捕获进行处理
        var username = Opt.ofTry(() -> (UserVO) StpUtil.getTokenSession().get("curLoginUser"))
                .map(UserVO::getUsername)
                .orElse("Unknown");

        var attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (ObjUtil.isNull(attributes)) {
            return;
        }
        var request = attributes.getRequest();

        request.setAttribute("startTime", System.currentTimeMillis());

        MDC.put("requestId", (String) request.getAttribute("requestId"));
        var ip = ServletUtil.getClientIP(request);
        log.info("Request URL:{}, Method:{}, IP:{}, {}, Operator:{}, Args:{}, Body:{}",
                request.getRequestURI(),
                request.getMethod(),
                ip,
                IPUtil.getIp(ip),
                username,
                objectMapper.writeValueAsString(request.getParameterMap()),
                StrUtil.replaceChars(ServletUtil.getBody(request), " \r\n", "")
        );
    }

    @AfterReturning(pointcut = "logPointcut()", returning = "result")
    public void doAfterReturning(JoinPoint joinPoint, Object result) throws JsonProcessingException {
        var attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (ObjUtil.isNull(attributes)) {
            return;
        }
        var request = attributes.getRequest();

        var startTime = (Long) request.getAttribute("startTime");
        var responseTime = System.currentTimeMillis() - startTime;

        if (result instanceof ResponseEntity) {
            log.info("Response time: {} ms. File download completed.", responseTime);
            return;
        }
        var resStr = objectMapper.writeValueAsString(result);
        if (resStr.length() > 1000) {
            resStr = resStr.substring(0, 1000);
        }
        log.info("Response time: {} ms. Return value: {}",
                responseTime,
                resStr);
        MDC.remove("requestId");
    }

}