您现在的位置是:首页 > 文章详情

springboot+aop切点记录请求和响应信息

日期:2018-11-06点击:564

本篇主要分享的是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的文件,其配置信息如:

<?xml version="1.0" encoding="UTF-8"?> <!-- ~ Author:shenniu003 ~ Copyright (c) 2018. --> <configuration debug="false" scan="true" scanPeriod="1 seconds"> <springProperty scope="context" name="appname" source="logging.logback.appname"/> <springProperty scope="context" name="logLevel" source="logging.logback.level"/> <springProperty scope="context" name="logPath" source="logging.logback.path"/> <property name="logPathAll" value="${logPath}/${appname}.log"/> <contextName>logback</contextName> <appender name="console" class="ch.qos.logback.core.ConsoleAppender"> <!-- <filter class="ch.qos.logback.classic.filter.ThresholdFilter" > <level>WARN</level> </filter>--> <encoder> <pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern> </encoder> </appender> <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${logPathAll}</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>${logPathAll}.%d{yyyy-MM-dd}.zip</fileNamePattern> </rollingPolicy> <encoder> <pattern>%date %level [%thread] %logger{36} [%file : %line] %msg%n </pattern> </encoder> </appender> <root level="${logLevel}"> <appender-ref ref="console"/> <appender-ref ref="file"/> </root> </configuration>

然后application.yml的配置信息如:

logging: config: classpath:logback-spring.xml logback: level: info #info ,debug path: /home/app/data/applogs/weblog appname: web

此刻日志和公共的aop记录类都完成了,我们需要创建个测试用例,其代码如:

 @PostMapping("/addUser") public ResponseEntity<MoStudent> addUser(@RequestBody MoStudent moStudent) throws Exception { moStudent.setNumber(UUID.randomUUID().toString()); // throw new Exception("错误了"); return new ResponseEntity<>(moStudent, HttpStatus.OK); }

最后,通过postman模拟post请求,能够得到如下的日志结果:
image


上面的方式切入点是所有方法,所有方法都记录日志可能有是不是需求想要的,此时可以通过注解的方式来标记想记录日志的方法;

先来创建个日志注解:

@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface LogAnnotation { /** * 描述 * * @return */ String des() default ""; }

同样再来创建注解的切入点:

 //匹配方法上包含此注解的方法 private final String annotationPointCut = "@annotation(com.platform.Aop.LogAnnotation)"; //注解切点 @Pointcut(value = annotationPointCut) public void logAnnotation() { }

再通过@Around注解绑定具体的操作方法:

 @Around(value = "logAnnotation()") public Object aroundAnnotation(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(); Method method = methodSignature.getMethod(); LogAnnotation logAnnotation = method.getAnnotation(LogAnnotation.class); if (logAnnotation != null && !logAnnotation.des().isEmpty()) { sbLog.append(String.format("说明:%s\r\n", logAnnotation.des())); } sbLog.append(String.format("方法:%s\r\n", method.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; }

这个方法里需要注意的是注解方式相比第一种其实就多了如下几行代码:

 Method method = methodSignature.getMethod(); LogAnnotation logAnnotation = method.getAnnotation(LogAnnotation.class); if (logAnnotation != null && !logAnnotation.des().isEmpty()) { sbLog.append(String.format("说明:%s\r\n", logAnnotation.des())); }

下面是注解测试用例:

 @LogAnnotation(des = "注解记录日志") @PostMapping("/addUser01") public ResponseEntity<MoStudent> addUser01(@RequestBody MoStudent moStudent) throws Exception { moStudent.setNumber(UUID.randomUUID().toString()); return new ResponseEntity<>(moStudent, HttpStatus.OK); }

image


如下是LogAspect.java的所有代码:

/* * Author:shenniu003 * Copyright (c) 2018. */ package com.platform.Aop; import com.alibaba.fastjson.JSON; import org.aspectj.lang.ProceedingJoinPoint; 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 java.lang.reflect.Method; /** * Created by Administrator on 2018/11/5. * springboot+aop切点记录请求和响应信息 */ @Component @Aspect public class LogAspect { //切点入口 Controller包下面所有类的所有方法 private final String pointcut = "execution(* com.platform.Controller..*(..))"; //匹配方法上包含此注解的方法 private final String annotationPointCut = "@annotation(com.platform.Aop.LogAnnotation)"; private Logger logger = LoggerFactory.getLogger(LogAspect.class); //切点 @Pointcut(value = pointcut) public void log() { } @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; } //注解切点 @Pointcut(value = annotationPointCut) public void logAnnotation() { } @Around(value = "logAnnotation()") public Object aroundAnnotation(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(); Method method = methodSignature.getMethod(); LogAnnotation logAnnotation = method.getAnnotation(LogAnnotation.class); if (logAnnotation != null && !logAnnotation.des().isEmpty()) { sbLog.append(String.format("说明:%s\r\n", logAnnotation.des())); } sbLog.append(String.format("方法:%s\r\n", method.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; } }
原文链接:https://yq.aliyun.com/articles/665722
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章