AOP并发情况下打印请求信息

AOP打印参数在并发情况下会出现请求信息线程串行的问题,经改造如下:

package com.example.aspect;

import com.alibaba.fastjson2.JSON;
import com.pacific.external.callback.util.CurrentContextUtils;
import org.apache.commons.lang.ArrayUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;


/**
 * ClassName HttpAspect
 *
 * @Description AOP 日志打印
 * @Author mingtian
 * @Date 2022/5/13 13:18
 * @Version 1.0
 */
@Aspect
@Component
public class HttpAspect {
    /**
     * 打印日志
     */
    protected Logger logger = LoggerFactory.getLogger(HttpAspect.class);

    /**
     * 跨行
     */
    private static final String LINE_SEPARATOR = System.lineSeparator();

    /**
     * 要处理的方法,包名+类名+方法名
     */
    @Pointcut("execution(* com.example.controller..*.*(..))")
    public void cut() {
    }

    /**
     * //在调用上面 @Pointcut标注的方法前执行以下方法
     *
     * @param joinPoint
     */
    @Before("cut()")
    public void doBefore(JoinPoint joinPoint) {
        logger.info("------------------------ Start ----------------------------");
        HttpServletRequest request = CurrentContextUtils.getCurrentRequestInfo();
        Signature signature = joinPoint.getSignature();
        StringBuilder requestInfo = new StringBuilder(32);
        // 打印请求参数
        requestInfo.append(LINE_SEPARATOR);
        requestInfo.append("Request MethodType:").append(request.getMethod()).append(LINE_SEPARATOR);
        requestInfo.append("Request IP:").append(request.getRemoteAddr()).append(LINE_SEPARATOR);
        requestInfo.append("Request Url:").append(request.getRequestURL().toString()).append(LINE_SEPARATOR);
        requestInfo.append("Request Class.Methods:").append(signature.getDeclaringTypeName()).append(".").append(signature.getName()).append(LINE_SEPARATOR);
        Object[] args = joinPoint.getArgs();
        // 序列化时过滤掉request和response
        List<Object> logArgs = streamOf(args).filter(arg -> (!(arg instanceof HttpServletRequest) && !(arg instanceof HttpServletResponse)))
                .collect(Collectors.toList());
        String argStr = JSON.toJSONString(logArgs);
        requestInfo.append("Request Param:").append(argStr).append(LINE_SEPARATOR);
        logger.info("requestInfo:{}", requestInfo);
    }

    /**
     * 判断参数类型是否是文件
     *
     * @param signature
     * @return
     */
    public boolean checkParamType(Signature signature) {
        MethodSignature methodSignature = (MethodSignature) signature;
        Class<?>[] parameterTypes = methodSignature.getParameterTypes();
        logger.info("parameterTypes:{}", (Object) parameterTypes);
        for (Class<?> cla : parameterTypes) {
            if (isFile(cla)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 过滤工具类
     *
     * @param array
     * @param <T>
     * @return
     */
    public static <T> Stream<T> streamOf(T[] array) {
        return ArrayUtils.isEmpty(array) ? Stream.empty() : Arrays.stream(array);
    }

    /**
     * 调用方法以何种方式结束,都会执行
     */
    @After("cut()")
    public void doAfter() {

    }

    /**
     * //在调用上面 @Pointcut标注的方法后执行。用于获取返回值
     *
     * @param obj
     */
    @AfterReturning(returning = "obj", pointcut = "cut()")
    public void doAfterReturning(Object obj) {
        logger.info("Response Result:{}", JSON.toJSONString(obj));
        logger.info("------------------------ End ----------------------------" + LINE_SEPARATOR);
    }

    /**
     * 文件上传字段不打印
     *
     * @param clazz
     * @return
     */
    private boolean isFile(Class<?> clazz) {
        if (MultipartFile.class.isAssignableFrom(clazz)) {
            return true;
        }
        return (clazz.isArray()) && (MultipartFile.class.isAssignableFrom(clazz.getComponentType()));
    }
}

 获取当前线程工具类:

package com.example.util;

import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @Description: CurrentContextUtils  获取当前线程方法
 * @Author: mingtian
 * @CreateDate: 2022/5/13 13:12
 * @Version: 1.0
 */
public class CurrentContextUtils {

    /**
     * 返回当前线程上下文request信息
     *
     * @return
     */
    public static HttpServletRequest getCurrentRequestInfo() {
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        return servletRequestAttributes.getRequest();
    }

    /**
     * 返回当前线程上下文response信息
     *
     * @return
     */
    public static HttpServletResponse getCurrentResponseInfo() {
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        return servletRequestAttributes.getResponse();
    }
}

 

posted @ 2022-05-13 15:16  明天,你好啊  阅读(111)  评论(0编辑  收藏  举报