aop 打印请求信息

 

execution()介绍

execution()是最常用的切点函数,其语法如下所示:

 整个表达式可以分为五个部分:

 1、execution(): 表达式主体,可以扫描控制层的接口、某个注解、或者其他需要扫描的类。

 2、第一个*号:表示返回类型,*号表示所有的类型,比如public,protect,private等。

 3、包名:表示需要拦截的包名,后面的两个句点表示当前包和当前包的所有子包,com.demo.service.impl包、子孙包下所有类的方法。

4、第二个*号:表示子包名,*号表示所有子包。

5、第三个*号:表示类名,*号表示所有子包下的类。

6、*(..):最后这个星号表示方法名,*号表示所有的方法,后面括弧里面表示方法的参数,两个句点表示任何参数。

package com.pacific.rsp.port.manager.aspect;
  2 
  3 import com.alibaba.fastjson.JSON;
  4 import com.alibaba.fastjson.JSONObject;
  5 import org.apache.commons.lang.ArrayUtils;
  6 import org.aspectj.lang.JoinPoint;
  7 import org.aspectj.lang.Signature;
  8 import org.aspectj.lang.annotation.*;
  9 import org.aspectj.lang.reflect.MethodSignature;
 10 import org.slf4j.Logger;
 11 import org.slf4j.LoggerFactory;
 12 import org.springframework.stereotype.Component;
 13 import org.springframework.web.context.request.RequestContextHolder;
 14 import org.springframework.web.context.request.ServletRequestAttributes;
 15 import org.springframework.web.multipart.MultipartFile;
 16 
 17 import javax.servlet.http.HttpServletRequest;
 18 import javax.servlet.http.HttpServletResponse;
 19 import java.util.Arrays;
 20 import java.util.List;
 21 import java.util.stream.Collectors;
 22 import java.util.stream.Stream;
 23 
 24 
 25 /**
 26  * @Description: aop 打印日志
 27  * @Author: mingtian
 28  * @CreateDate: 2020/5/11 15:52
 29  * @Version: 1.0
 30  */
 31 @Aspect
 32 @Component
 33 public class HttpAspect {
 34     /**
 35      * 打印日志
 36      */
 37     protected Logger logger = LoggerFactory.getLogger(HttpAspect.class);
 38 
 39     /**
 40      * 跨行
 41      */
 42     private static final String LINE_SEPARATOR = System.lineSeparator();
 43 
 44     /**
 45      * 要处理的方法,包名+类名+方法名
 46      */
 47     @Pointcut("execution(* com.example.web.controller..*.*(..))")
 48     public void cut() {
 49     }
 50 
 51 
 52     /**
 53      * //在调用上面 @Pointcut标注的方法前执行以下方法
 54      *
 55      * @param joinPoint
 56      */
 57     @Before("cut()")
 58     public void doBefore(JoinPoint joinPoint) {
 59         logger.info("------------------------ Start ----------------------------");
 60         ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
 61         HttpServletRequest request = attributes.getRequest();
 62         Signature signature = joinPoint.getSignature();
 63         // 记录下请求内容
 64         logger.info("Request MethodType:{}", request.getMethod());
 65         logger.info("Request IP:{}", request.getRemoteAddr());
 66         logger.info("Request Url:{}", request.getRequestURL().toString());
 67         logger.info("Request Class and Methods:{}.{}", signature.getDeclaringTypeName(), signature.getName());
 68         boolean result = checkParamType(signature);
 69         if (result) {
 70             logger.info("文件格式不打印参数信息");
 71             return;
 72         }
 73         Object[] args = joinPoint.getArgs();
 74         //序列化时过滤掉request和response
 75         List<Object> logArgs = streamOf(args).filter(arg -> (!(arg instanceof HttpServletRequest) && !(arg instanceof HttpServletResponse)))
 76                 .collect(Collectors.toList());
 77         String argStr = JSON.toJSONString(logArgs);
 78         logger.info("Request Args:{}", argStr);
 79     }
 80 
 81     /**
 82      * 判断参数类型是否是文件
 83      *
 84      * @param signature
 85      * @return
 86      */
 87     public boolean checkParamType(Signature signature) {
 88         MethodSignature methodSignature = (MethodSignature) signature;
 89         Class[] parameterTypes = methodSignature.getParameterTypes();
 90         logger.info("parameterTypes:{}", parameterTypes);
 91         for (Class cla : parameterTypes) {
 92             if (isFile(cla)) {
 93                 return true;
 94             }
 95         }
 96         return false;
 97     }
 98 
 99     /**
100      * 过滤工具类
101      *
102      * @param array
103      * @param <T>
104      * @return
105      */
106     public static <T> Stream<T> streamOf(T[] array) {
107         return ArrayUtils.isEmpty(array) ? Stream.empty() : Arrays.asList(array).stream();
108     }
109 
110     /**
111      * 调用方法以何种方式结束,都会执行
112      */
113     @After("cut()")
114     public void doAfter() {
115 
116     }
117 
118     /**
119      * //在调用上面 @Pointcut标注的方法后执行。用于获取返回值
120      *
121      * @param obj
122      */
123     @AfterReturning(returning = "obj", pointcut = "cut()")
124     public void doAfterReturning(Object obj) {
125         // 处理完请求,返回相应参数
126         logger.info("Response Result:{}", JSONObject.toJSONString(obj));
127         logger.info("------------------------ End ----------------------------" + LINE_SEPARATOR);
128     }
129 
130     /**
131      * 文件上传字段不打印
132      *
133      * @param clazz
134      * @return
135      */
136     private boolean isFile(Class clazz) {
137         if (MultipartFile.class.isAssignableFrom(clazz)) {
138             return true;
139         }
140         if ((clazz.isArray()) && (MultipartFile.class.isAssignableFrom(clazz.getComponentType()))) {
141             return true;
142         }
143         return false;
144     }
145 }

 

 并发情况下打印参数导致线程串行问题,参考文章:

https://www.cnblogs.com/ming-blogs/p/16266819.html

posted @ 2019-12-22 14:09  明天,你好啊  阅读(316)  评论(0编辑  收藏  举报