1. import java.lang.reflect.Modifier;
  2.  
  3. import javassist.ClassClassPath;
  4. import javassist.ClassPool;
  5. import javassist.CtClass;
  6. import javassist.CtMethod;
  7. import javassist.bytecode.CodeAttribute;
  8. import javassist.bytecode.LocalVariableAttribute;
  9. import javassist.bytecode.MethodInfo;
  10.  
  11. import org.apache.commons.lang.ArrayUtils;
  12. import org.aspectj.lang.ProceedingJoinPoint;
  13. import org.aspectj.lang.annotation.Around;
  14. import org.aspectj.lang.annotation.Aspect;
  15. import org.aspectj.lang.annotation.Pointcut;
  16. import org.slf4j.Logger;
  17. import org.slf4j.LoggerFactory;
  18.  
  19. import com.alibaba.fastjson.JSON;
  20.  
  21. /**@Description
  22. 哪个资方需要输出日志,自己到**-config工程下的spring-commons.xml配置
  23. <!-- 日志打印 -->
  24. <bean id="aopLog" class="com.XXXXXXX.AopLog"/>
  25. * @author : 陈惟鲜 danger
  26. * @Date : 2018年8月9日 下午5:59:55
  27. *
  28. */
  29. @Aspect
  30. public class AopLog {
  31.  
  32. private Logger logger = LoggerFactory.getLogger(getClass());
  33. /**拦截所有controller包下的方法*/
  34. @Pointcut("execution(* com.sinaif.king..controller..*.*(..))")
  35. private void controllerMethod(){}//定义一个切入点
  36.  
  37. /**拦截所有service包下的方法*/
  38. @Pointcut("execution(* com.sinaif.king..service..*.*(..))")
  39. private void serviceMethod(){}//定义一个切入点
  40.  
  41. // // 1、前置通知: 在目标方法开始之前执行(就是要告诉该方法要在哪个类哪个方法前执行)
  42. // @Before("controllerMethod() || serviceMethod()")
  43. // public void beforeMethod(JoinPoint joinPoint) {
  44. // String methodName = joinPoint.getSignature().getName();
  45. // String className = joinPoint.getTarget().getClass().getName();
  46. // String msgInfo = "【" + className + "." + methodName + "】";
  47. // logger.info(msgInfo + "......start..........");
  48. // }
  49. //
  50. // // 2、后置通知:在目标方法执行后(无论是否发生异常),执行的通知
  51. // // 注意,在后置通知中还不能访问目标执行的结果!!!,执行结果需要到返回通知里访问
  52. // @After("controllerMethod() || serviceMethod()")
  53. // public void afterMethod(JoinPoint joinPoint) {
  54. // String className = joinPoint.getTarget().getClass().getName();
  55. // String methodName = joinPoint.getSignature().getName();
  56. // String msgInfo = "【" + className + "." + methodName + "】";
  57. // logger.info(msgInfo + "...............end.");
  58. // }
  59.  
  60. /**
  61. * @Description : 日志打印
  62. * @author : 陈惟鲜 danger
  63. * @Date : 2018年8月8日 下午5:29:47
  64. * @param point
  65. * @return
  66. * @throws Throwable
  67. */
  68. @Around("controllerMethod() || serviceMethod()")
  69. public Object doAround(ProceedingJoinPoint point) throws Throwable {
  70. String msgInfo = "@aop["+point.getSignature().getDeclaringTypeName()+"."+point.getSignature().getName()+"]"; // 所在的类.方法
  71. String requestStr = getRequestParam(point);
  72. requestStr = parameterHandle(requestStr, 10000);
  73. logger.info(msgInfo + "start.输入参数:" + requestStr);
  74. long startTime = System.currentTimeMillis();// 开始时间
  75. Object result = null;
  76. try{
  77. // 执行完方法的返回值:调用proceed()方法,就会触发切入点方法执行
  78. result = point.proceed();// result的值就是被拦截方法的返回值
  79. }catch(Exception e){
  80. throw e;
  81. }finally{
  82. long handleTime = System.currentTimeMillis()-startTime;// 开始时间
  83. String responseStr = result==null?"无": JSON.toJSONString(result);
  84. responseStr = parameterHandle(responseStr, 10000);
  85.  
  86. StringBuffer endString = new StringBuffer(100);
  87. endString.append(msgInfo).append("end.");
  88. endString.append("耗时(" + handleTime + "ms)");
  89. endString.append("输出参数:").append(responseStr);
  90.  
  91. logger.info(endString.toString());
  92. }
  93. return result;
  94. }
  95.  
  96. /**
  97. * @Description : 参数处理,超过指定长度字符的,只显示1000...
  98. * @author : 陈惟鲜 danger
  99. * @Date : 2018年8月10日 上午11:44:11
  100. * @param paramStr
  101. * @param strlength
  102. * @return
  103. */
  104. private String parameterHandle(String paramStr, int strlength){
  105. if (paramStr.length() > strlength){
  106. paramStr = paramStr.substring(0, 1000) + "...";
  107. }
  108. if (paramStr.length() > 10){
  109. paramStr = "[" + paramStr + "]";
  110. }
  111. return paramStr;
  112. }
  113.  
  114. /***
  115. * @Description : 获取请求参数
  116. * @author : 陈惟鲜 danger
  117. * @Date : 2018年8月9日 下午3:47:08
  118. * @param point
  119. * @return
  120. */
  121. private String getRequestParam(ProceedingJoinPoint point){
  122. String class_name = point.getTarget().getClass().getName();
  123. String method_name = point.getSignature().getName();
  124. /**
  125. * 获取方法的参数值数组。
  126. */
  127. Object[] methodArgs = point.getArgs();
  128.  
  129. String[] paramNames = null;
  130. // 结果
  131. String requestStr = "";
  132. /**
  133. * 获取方法参数名称
  134. */
  135. try {
  136. paramNames = getFieldsName(class_name, method_name);
  137. requestStr = logParam(paramNames, methodArgs);
  138. } catch (Exception e) {
  139. requestStr = "获取参数失败";
  140. }
  141. return requestStr;
  142. }
  143.  
  144. /**
  145. * 使用javassist来获取方法参数名称
  146. * @param class_name 类名
  147. * @param method_name 方法名
  148. * @return
  149. * @throws Exception
  150. */
  151. private String[] getFieldsName(String class_name, String method_name) throws Exception {
  152. Class<?> clazz = Class.forName(class_name);
  153. String clazz_name = clazz.getName();
  154. ClassPool pool = ClassPool.getDefault();
  155. ClassClassPath classPath = new ClassClassPath(clazz);
  156. pool.insertClassPath(classPath);
  157.  
  158. CtClass ctClass = pool.get(clazz_name);
  159. CtMethod ctMethod = ctClass.getDeclaredMethod(method_name);
  160. MethodInfo methodInfo = ctMethod.getMethodInfo();
  161. CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
  162. LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag);
  163. if(attr == null){
  164. return null;
  165. }
  166. String[] paramsArgsName = new String[ctMethod.getParameterTypes().length];
  167. int pos = Modifier.isStatic(ctMethod.getModifiers()) ? 0 : 1;
  168. for (int i=0;i<paramsArgsName.length;i++){
  169. paramsArgsName[i] = attr.variableName(i + pos);
  170. }
  171. return paramsArgsName;
  172. }
  173.  
  174. /**
  175. * 判断是否为基本类型:包括String
  176. * @param clazz clazz
  177. * @return true:是; false:不是
  178. */
  179. private boolean isPrimite(Class<?> clazz){
  180. if (clazz.isPrimitive() || clazz == String.class){
  181. return true;
  182. }else {
  183. return false;
  184. }
  185. }
  186.  
  187. /**
  188. * 打印方法参数值 基本类型直接打印,非基本类型需要重写toString方法
  189. * @param paramsArgsName 方法参数名数组
  190. * @param paramsArgsValue 方法参数值数组
  191. */
  192. private String logParam(String[] paramsArgsName,Object[] paramsArgsValue){
  193. if(ArrayUtils.isEmpty(paramsArgsName) || ArrayUtils.isEmpty(paramsArgsValue)){
  194. return "";
  195. }
  196. StringBuffer buffer = new StringBuffer();
  197. for (int i=0;i<paramsArgsValue.length;i++){
  198. //参数名
  199. String name = paramsArgsName[i];
  200. //参数值
  201. Object value = paramsArgsValue[i];
  202. buffer.append(name +" = ");
  203. if(isPrimite(value.getClass())){
  204. buffer.append(value + " ,");
  205. }else {
  206. buffer.append(value.toString() + " ,");
  207. }
  208. }
  209. return buffer.toString();
  210. }
  211. }

通过AOP拦截打印日志,出入参数的更多相关文章

  1. Spring Boot- 设置拦截打印日志

    import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Aspect; import org.aspe ...

  2. AOP与Filter拦截请求打印日志实用例子

    相信各位同道在写代码的时候,肯定会写一些日志打印,因为这对往后的运维而言,至关重要的. 那么我们请求一个restfull接口的时候,哪些信息是应该被日志记录的呢? 以下做了一个基本的简单例子,这里只是 ...

  3. Spring Boot 中使用自定义注解,AOP 切面打印出入参日志及Dubbo链路追踪透传traceId

    一.使用背景 开发排查系统问题用得最多的手段就是查看系统日志,在分布式环境中一般使用 ELK 来统一收集日志,但是在并发大时使用日志定位问题还是比较麻烦,由于大量的其他用户/其他线程的日志也一起输出穿 ...

  4. Spring Boot AOP之对请求的参数入参与返回结果进行拦截处理

    Spring Boot AOP之对请求的参数入参与返回结果进行拦截处理   本文链接:https://blog.csdn.net/puhaiyang/article/details/78146620 ...

  5. 用AOP拦截自定义注解并获取注解属性与上下文参数(基于Springboot框架)

    目录 自定义注解 定义切面 获取上下文信息JoinPoint ProceedingJoinPoint 定义测试方法 测试结果 小结 AOP可以用于日志的设计,这样话就少不了要获取上下文的信息,博主在设 ...

  6. Spring Boot 2.x(十一):AOP实战--打印接口日志

    接口日志有啥用 在我们日常的开发过程中,我们可以通过接口日志去查看这个接口的一些详细信息.比如客户端的IP,客户端的类型,响应的时间,请求的类型,请求的接口方法等等,我们可以对这些数据进行统计分析,提 ...

  7. springboot aop + logback + 统一异常处理 打印日志

    1.src/resources路径下新建logback.xml 控制台彩色日志打印 info日志和异常日志分不同文件存储 每天自动生成日志 结合myibatis方便日志打印(debug模式) < ...

  8. AOP拦截日志报错llegalStateException: It is illegal to call this method if the current request is not in asynchronous mode

    原文链接:https://my.oschina.net/mengzhang6/blog/2395893 关于一次AOP拦截入参记录日志报错的梳理总结 将服务发布到tomcat中后,观察服务的运行状态以 ...

  9. SpringBoot自定义注解、AOP打印日志

    前言 在SpringBoot中使用自定义注解.aop切面打印web请求日志.主要是想把controller的每个request请求日志收集起来,调用接口.执行时间.返回值这几个重要的信息存储到数据库里 ...

随机推荐

  1. [DEBUG] ubuntu pip安装成功却无法import

    我的pip经常出问题,我也不知道为啥..今天搞啥啥坏=.= 问题: pip自动安装显示成功,在交互环境下却无法import ==========================踩坑========== ...

  2. Python--字典的一些用法dict.items()

    1.dict.items() 例子1: 以列表返回可遍历的(键, 值) 元组数组. dict = {'Name': 'Runoob', 'Age': 7} print ("Value : % ...

  3. pandas数据结构之基础运算笔记

    import pandas as pd import numpy as np s = pd.Series([1,3,5,6,8],index=list('acefh')) s.index # 读取行索 ...

  4. MySQL的explain语句分析

    +----+-------------+-------+------------+------+---------------+-----+---------+------+------+------ ...

  5. 18-MySQL DBA笔记-MySQL Server调优

    第18章 MySQL Server调优 本章将为读者介绍针对MySQL Server的优化,这也是DBA最熟悉的领域之一.首先我们介绍MySQL的主要参数,然后,讲述常见硬件资源的优化.我们假设读者已 ...

  6. WebSocket协议探究(二)

    一 复习和目标 1 复习 协议概述: WebSocket内置消息定界并且全双工通信 WebSocket使用HTTP进行协议协商,协商成功使用TCP连接进行传输数据 WebScoket数据格式支持二进制 ...

  7. win8系统安装.net Framework3.5

    Win8 离线安装 .Net Framework 3.5(工具+方法)(支持Win8.1) 微软在最新的 Win8 / Win8.1 系统中没有集成 .NET 3.5,如果安装的话,必须是在线安装,甚 ...

  8. Linux每隔1秒kill掉cpu大于50%的进程

    1.新建/test/killcpu.sh shell脚本 并授予权限0755#!/bin/bashps axf -o "pid %cpu" | awk '{if($2>=50 ...

  9. 记一次Git提交报错的问题

    通常代码版本控制的步骤是: 在代码版本控制平台新建一个仓库 clone远程仓库到本地 开始编码,然后是一系列add,commit,push 我的步骤是: 在远程代码版本管理平台新建一个仓库 在本地新建 ...

  10. MVC框架+vue+elementUI

    用自动化构建做的vue项目,因为是动态加载数据,在SEO优化时一直不如意,于是我们换了框架,用MVC框架,做成静态页面,但是原来的代码都是用vue和elementUI,为了快速的复用原来的代码,于是在 ...