统一日志切面

需求:打印系统的controller的请求日志和返回结果,以及接口耗时,方便后续排查问题;

可以使用filter来做,也可以使用切面,倾向于使用切面;

代码如下:

@Aspect
@Component
public class WebLogAspect {

    private static final Logger logger = LoggerFactory.getLogger(WebLogAspect.class);

    /**
     * 请求参数/返回结果的日志打印最大长度
     */
    private final static int RESPONSE_LOG_MAX_LENGTH = 2000;

    /**
     * 以 iface 包下定义的所有请求为切入点
     */
    @Pointcut("(@within(org.springframework.stereotype.Controller) || @within(org.springframework.web.bind.annotation.RestController))" +
            "&& within(com.xxx.*)"+
            "   &&! @annotation(org.springframework.scheduling.annotation.Async)  ")
    public void webLog() {
    }

    /**
     * 在切点之前织入
     *
     * @param joinPoint
     * @throws Throwable
     */
    @Before("webLog()")
    public void doBefore(JoinPoint joinPoint) throws Throwable {
        // 开始打印请求日志
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();

        StringBuilder responseContext = !ObjectUtils.isEmpty(joinPoint.getArgs()) ?
                new StringBuilder(JsonUtil.parseObjToJsonStr(joinPoint.getArgs())) :
                new StringBuilder(Strings.EMPTY);
        // 打印请求相关参数
        logger.info("request URL:{}, Class Method:{}.{}, IP:{}, Args:{}", request.getRequestURL().toString()
                , joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName(),
                request.getRemoteAddr(), checkLengthAndCut(responseContext));
    }

    /**
     * 在切点之后织入
     *
     * @throws Throwable
     */
    @After("webLog()")
    public void doAfter() throws Throwable {
    }

    /**
     * 环绕
     *
     * @param proceedingJoinPoint
     * @return
     * @throws Throwable
     */
    @Around("webLog()")
    public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        Object result = proceedingJoinPoint.proceed();
        if (result != null) {
            StringBuilder stringBuilder = new StringBuilder(JsonUtil.parseObjToJsonStr(result));
            long timeSpend = System.currentTimeMillis() - startTime;
            logger.info("Response Time-Consuming:{} ms,content : {}", timeSpend, checkLengthAndCut(stringBuilder));
        }
        return result;
    }

    /**
     * 判断长度并截取
     *
     * @param stringBuilder
     * @return
     */
    private String checkLengthAndCut(StringBuilder stringBuilder) {
        if (Objects.isNull(stringBuilder)) {
            return Strings.EMPTY;
        }
        if (stringBuilder.length() > RESPONSE_LOG_MAX_LENGTH) {
            return stringBuilder.substring(0, RESPONSE_LOG_MAX_LENGTH);
        } else {
            return stringBuilder.toString();
        }
    }

你可能感兴趣的:(日志,切面)