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

 本篇主要分享的是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); 欢迎工作一到五年的Java工程师朋友们加入Java群: 891219277
群内提供免费的Java架构学习资料(里面有高可用、高并发、高性能及分布式、Jvm性能调优、Spring源码,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多个知识点的架构资料)合理利用自己每一分每一秒的时间来学习提升自己,不要再用"没有时间“来掩饰自己思想上的懒惰!趁年轻,使劲拼,给未来的自己一个交代!

6 }
复制代码

转载于:https://blog.51cto.com/14084556/2335046

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值