springboot+aop切点记录请求和响应信息
2018-11-09 02:37:53来源:博客园 阅读 ()
本篇主要分享的是springboot中结合aop方式来记录请求参数和响应的数据信息;这里主要讲解两种切入点方式,一种方法切入,一种注解切入;首先创建个springboot测试工程并通过maven添加如下依赖:
<!-- AOP --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> <!--阿里 FastJson依赖--> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.44</version> </dependency>
先来说方法的切点方式,需要创建个名为LogAspect的组件类,然后用@Aspect注解修饰组件类,再通过设置方法切入点方式做公共日志记录,如下创建切入点:
//切点入口 Controller包下面所有类的所有方法 private final String pointcut = "execution(* com.platform.Controller..*(..))"; //切点 @Pointcut(value = pointcut) public void log() { }
这里的execution( com.platform.Controller..(..))主要的意思是:切入点入口是Controller包下面所有类的所有方法;再来通过@Around环绕注解方法里面做请求参数和响应信息的记录,如下代码:
@Around(value = "log()") public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { Object result = null; StringBuilder sbLog = new StringBuilder("\n"); try { sbLog.append(String.format("类名:%s\r\n", proceedingJoinPoint.getTarget().getClass().getName())); MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature(); sbLog.append(String.format("方法:%s\r\n", methodSignature.getMethod().getName())); Object[] args = proceedingJoinPoint.getArgs(); for (Object o : args) { sbLog.append(String.format("参数:%s\r\n", JSON.toJSON(o))); } long startTime = System.currentTimeMillis(); result = proceedingJoinPoint.proceed(); long endTime = System.currentTimeMillis(); sbLog.append(String.format("返回:%s\r\n", JSON.toJSON(result))); sbLog.append(String.format("耗时:%ss", endTime - startTime)); } catch (Exception ex) { sbLog.append(String.format("异常:%s", ex.getMessage())); } finally { logger.info(sbLog.toString()); } return result; }
此刻主要代码就完成了,再来我们配置下日志的记录方式;首先在 resources目录增加名为logback-spring.xml的文件,其配置信息如:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!-- 3 ~ Author:shenniu003 4 ~ Copyright (c) 2018. 5 --> 6 7 <configuration debug="false" scan="true" scanPeriod="1 seconds"> 8 9 <springProperty scope="context" name="appname" source="logging.logback.appname"/> 10 <springProperty scope="context" name="logLevel" source="logging.logback.level"/> 11 <springProperty scope="context" name="logPath" source="logging.logback.path"/> 12 13 <property name="logPathAll" value="${logPath}/${appname}.log"/> 14 15 <contextName>logback</contextName> 16 17 <appender name="console" class="ch.qos.logback.core.ConsoleAppender"> 18 <!-- <filter class="ch.qos.logback.classic.filter.ThresholdFilter" > 19 <level>WARN</level> 20 </filter>--> 21 <encoder> 22 <pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern> 23 </encoder> 24 </appender> 25 26 <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender"> 27 <file>${logPathAll}</file> 28 <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> 29 <fileNamePattern>${logPathAll}.%d{yyyy-MM-dd}.zip</fileNamePattern> 30 </rollingPolicy> 31 <encoder> 32 <pattern>%date %level [%thread] %logger{36} [%file : %line] %msg%n 33 </pattern> 34 </encoder> 35 </appender> 36 37 <root level="${logLevel}"> 38 <appender-ref ref="console"/> 39 <appender-ref ref="file"/> 40 </root> 41 42 </configuration>
然后application.yml的配置信息如:
1 logging: 2 config: classpath:logback-spring.xml 3 logback: 4 level: info #info ,debug 5 path: /home/app/data/applogs/weblog 6 appname: web
此刻日志和公共的aop记录类都完成了,我们需要创建个测试用例,其代码如:
1 @PostMapping("/addUser") 2 public ResponseEntity<MoStudent> addUser(@RequestBody MoStudent moStudent) throws Exception { 3 moStudent.setNumber(UUID.randomUUID().toString()); 4 // throw new Exception("错误了"); 5 return new ResponseEntity<>(moStudent, HttpStatus.OK); 6 }
最后,通过postman模拟post请求,能够得到如下的日志结果:
上面的方式切入点是所有方法,所有方法都记录日志可能有是不是需求想要的,此时可以通过注解的方式来标记想记录日志的方法;先来创建个日志注解:
1 @Target(ElementType.METHOD) 2 @Retention(RetentionPolicy.RUNTIME) 3 @Documented 4 public @interface LogAnnotation { 5 /** 6 * 描述 7 * 8 * @return 9 */ 10 String des() default ""; 11 }
同样再来创建注解的切入点:
1 //匹配方法上包含此注解的方法 2 private final String annotationPointCut = "@annotation(com.platform.Aop.LogAnnotation)"; 3 4 //注解切点 5 @Pointcut(value = annotationPointCut) 6 public void logAnnotation() { 7 }
再通过@Around注解绑定具体的操作方法:
1 @Around(value = "logAnnotation()") 2 public Object aroundAnnotation(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { 3 Object result = null; 4 StringBuilder sbLog = new StringBuilder("\n"); 5 try { 6 sbLog.append(String.format("类名:%s\r\n", proceedingJoinPoint.getTarget().getClass().getName())); 7 8 MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature(); 9 Method method = methodSignature.getMethod(); 10 LogAnnotation logAnnotation = method.getAnnotation(LogAnnotation.class); 11 if (logAnnotation != null && !logAnnotation.des().isEmpty()) { 12 sbLog.append(String.format("说明:%s\r\n", logAnnotation.des())); 13 } 14 sbLog.append(String.format("方法:%s\r\n", method.getName())); 15 16 Object[] args = proceedingJoinPoint.getArgs(); 17 for (Object o : args) { 18 sbLog.append(String.format("参数:%s\r\n", JSON.toJSON(o))); 19 } 20 21 long startTime = System.currentTimeMillis(); 22 result = proceedingJoinPoint.proceed(); 23 long endTime = System.currentTimeMillis(); 24 sbLog.append(String.format("返回:%s\r\n", JSON.toJSON(result))); 25 sbLog.append(String.format("耗时:%ss", endTime - startTime)); 26 } catch (Exception ex) { 27 sbLog.append(String.format("异常:%s", ex.getMessage())); 28 } finally { 29 logger.info(sbLog.toString()); 30 } 31 return result; 32 }
这个方法里需要注意的是注解方式相比第一种其实就多了如下几行代码:
1 Method method = methodSignature.getMethod(); 2 LogAnnotation logAnnotation = method.getAnnotation(LogAnnotation.class); 3 if (logAnnotation != null && !logAnnotation.des().isEmpty()) { 4 sbLog.append(String.format("说明:%s\r\n", logAnnotation.des())); 5 }
下面是注解测试用例:
1 @LogAnnotation(des = "注解记录日志") 2 @PostMapping("/addUser01") 3 public ResponseEntity<MoStudent> addUser01(@RequestBody MoStudent moStudent) throws Exception { 4 moStudent.setNumber(UUID.randomUUID().toString()); 5 return new ResponseEntity<>(moStudent, HttpStatus.OK); 6 }
如下是LogAspect.java的所有代码:
1 /* 2 * Author:shenniu003 3 * Copyright (c) 2018. 4 */ 5 6 package com.platform.Aop; 7 8 import com.alibaba.fastjson.JSON; 9 import org.aspectj.lang.ProceedingJoinPoint; 10 import org.aspectj.lang.annotation.*; 11 import org.aspectj.lang.reflect.MethodSignature; 12 import org.slf4j.Logger; 13 import org.slf4j.LoggerFactory; 14 import org.springframework.stereotype.Component; 15 16 import java.lang.reflect.Method; 17 18 /** 19 * Created by Administrator on 2018/11/5. 20 * springboot+aop切点记录请求和响应信息 21 */ 22 @Component 23 @Aspect 24 public class LogAspect { 25 26 //切点入口 Controller包下面所有类的所有方法 27 private final String pointcut = "execution(* com.platform.Controller..*(..))"; 28 29 //匹配方法上包含此注解的方法 30 private final String annotationPointCut = "@annotation(com.platform.Aop.LogAnnotation)"; 31 32 private Logger logger = LoggerFactory.getLogger(LogAspect.class); 33 34 //切点 35 @Pointcut(value = pointcut) 36 public void log() { 37 } 38 39 @Around(value = "log()") 40 public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { 41 Object result = null; 42 StringBuilder sbLog = new StringBuilder("\n"); 43 try { 44 sbLog.append(String.format("类名:%s\r\n", proceedingJoinPoint.getTarget().getClass().getName())); 45 46 MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature(); 47 sbLog.append(String.format("方法:%s\r\n", methodSignature.getMethod().getName())); 48 49 Object[] args = proceedingJoinPoint.getArgs(); 50 for (Object o : args) { 51 sbLog.append(String.format("参数:%s\r\n", JSON.toJSON(o))); 52 } 53 54 long startTime = System.currentTimeMillis(); 55 result = proceedingJoinPoint.proceed(); 56 long endTime = System.currentTimeMillis(); 57 sbLog.append(String.format("返回:%s\r\n", JSON.toJSON(result))); 58 sbLog.append(String.format("耗时:%ss", endTime - startTime)); 59 } catch (Exception ex) { 60 sbLog.append(String.format("异常:%s", ex.getMessage())); 61 } finally { 62 logger.info(sbLog.toString()); 63 } 64 return result; 65 } 66 67 //注解切点 68 @Pointcut(value = annotationPointCut) 69 public void logAnnotation() { 70 } 71 72 @Around(value = "logAnnotation()") 73 public Object aroundAnnotation(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { 74 Object result = null; 75 StringBuilder sbLog = new StringBuilder("\n"); 76 try { 77 sbLog.append(String.format("类名:%s\r\n", proceedingJoinPoint.getTarget().getClass().getName())); 78 79 MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature(); 80 Method method = methodSignature.getMethod(); 81 LogAnnotation logAnnotation = method.getAnnotation(LogAnnotation.class); 82 if (logAnnotation != null && !logAnnotation.des().isEmpty()) { 83 sbLog.append(String.format("说明:%s\r\n", logAnnotation.des())); 84 } 85 sbLog.append(String.format("方法:%s\r\n", method.getName())); 86 87 Object[] args = proceedingJoinPoint.getArgs(); 88 for (Object o : args) { 89 sbLog.append(String.format("参数:%s\r\n", JSON.toJSON(o))); 90 } 91 92 long startTime = System.currentTimeMillis(); 93 result = proceedingJoinPoint.proceed(); 94 long endTime = System.currentTimeMillis(); 95 sbLog.append(String.format("返回:%s\r\n", JSON.toJSON(result))); 96 sbLog.append(String.format("耗时:%ss", endTime - startTime)); 97 } catch (Exception ex) { 98 sbLog.append(String.format("异常:%s", ex.getMessage())); 99 } finally { 100 logger.info(sbLog.toString()); 101 } 102 return result; 103 } 104 }
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- JAVA 每次从List中取出100条记录 2020-05-27
- 初识JAVA(学习记录) 2020-05-19
- 错题记录——关于Java中private的用法(类与封装) 2020-05-16
- 坚持学习,坚持写博客,记录学习的点点滴滴,先从学习JAVA开 2020-05-16
- Spring Batch 读 10 万条记录,写到 MongoDB 2020-05-11
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash