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