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

摘要:
本篇主要分享的是springboot中结合aop方式来记录请求参数和响应的数据信息;这里主要讲解两种切入点方式,一种方法切入,一种注解切入;首先创建个springboot测试工程并通过maven添加如下依赖:˂!

本篇主要分享的是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 voidlog() {
    }

这里的execution(com.platform.Controller..(..))主要的意思是:切入点入口是Controller包下面所有类的所有方法;再来通过@Around环绕注解方法里面做请求参数和响应信息的记录,如下代码:

    @Around(value = "log()")
    publicObject around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        Object result = null;
        StringBuilder sbLog = new StringBuilder("");
        try{
            sbLog.append(String.format("类名:%s
", proceedingJoinPoint.getTarget().getClass().getName()));
            MethodSignature methodSignature =(MethodSignature) proceedingJoinPoint.getSignature();
            sbLog.append(String.format("方法:%s
", methodSignature.getMethod().getName()));
            Object[] args =proceedingJoinPoint.getArgs();
            for(Object o : args) {
                sbLog.append(String.format("参数:%s
", JSON.toJSON(o)));
            }
            long startTime =System.currentTimeMillis();
            result =proceedingJoinPoint.proceed();
            long endTime =System.currentTimeMillis();
            sbLog.append(String.format("返回:%s
", 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());
        }
        returnresult;
    }

此刻主要代码就完成了,再来我们配置下日志的记录方式;首先在 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请求,能够得到如下的日志结果:

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

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

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 voidlogAnnotation() {
7     }

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

1     @Around(value = "logAnnotation()")
2     publicObject aroundAnnotation(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
3         Object result = null;
4         StringBuilder sbLog = new StringBuilder("");
5         try{
6             sbLog.append(String.format("类名:%s
", 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
", logAnnotation.des()));
13 }
14             sbLog.append(String.format("方法:%s
", method.getName()));
15 
16             Object[] args =proceedingJoinPoint.getArgs();
17             for(Object o : args) {
18                 sbLog.append(String.format("参数:%s
", 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
", 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         returnresult;
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
", 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     }

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

如下是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 classLogAspect {
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 voidlog() {
37 }
38 
39     @Around(value = "log()")
40     publicObject around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
41         Object result = null;
42         StringBuilder sbLog = new StringBuilder("");
43         try{
44             sbLog.append(String.format("类名:%s
", proceedingJoinPoint.getTarget().getClass().getName()));
45 
46             MethodSignature methodSignature =(MethodSignature) proceedingJoinPoint.getSignature();
47             sbLog.append(String.format("方法:%s
", methodSignature.getMethod().getName()));
48 
49             Object[] args =proceedingJoinPoint.getArgs();
50             for(Object o : args) {
51                 sbLog.append(String.format("参数:%s
", 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
", 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         returnresult;
65 }
66 
67     //注解切点
68     @Pointcut(value =annotationPointCut)
69     public voidlogAnnotation() {
70 }
71 
72     @Around(value = "logAnnotation()")
73     publicObject aroundAnnotation(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
74         Object result = null;
75         StringBuilder sbLog = new StringBuilder("");
76         try{
77             sbLog.append(String.format("类名:%s
", 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
", logAnnotation.des()));
84 }
85             sbLog.append(String.format("方法:%s
", method.getName()));
86 
87             Object[] args =proceedingJoinPoint.getArgs();
88             for(Object o : args) {
89                 sbLog.append(String.format("参数:%s
", 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
", 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         returnresult;
103 }
104 }
View Code

免责声明:文章转载自《springboot+aop切点记录请求和响应信息》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇13个JavaScript图表(JS图表)图形绘制插件【转】几种任务调度的 Java 实现方法与比较Timer,ScheduledExecutor,Quartz,JCronTab下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

C#操作access和SQL server数据库代码实例

    在C#的学习中,操作数据库是比较常用的技术,而access和sql server 数据库的操作却有着不同。那么,有哪些不同呢?              首先,需要引用不同的类。因为有着不同的数据引擎。     access:using System.Data.OleDb;     sql server:using System.Data.SqlC...

Shiro

1.shiro简介 官网介绍主要实现四个功能: Authentication: Sometimes referred to as ‘login’, this is the act of proving a user is who they say they are. Authorization: The process of access control...

上传永久图文素材-公共方法

package com.epalmpay.util;import com.alibaba.fastjson.JSON;import com.riversoft.weixin.common.oauth2.AccessToken;import net.sf.json.JSONObject;import org.apache.http.HttpEntity;im...

spring-session之一:简介、使用及实现原理

一、背景 http session(企业)一直都是我们做集群时需要解决的一个难题,我们知道HttpSession是通过Servlet容器创建和管理的,像Tomcat/Jetty都是保存在内存中的。而如果我们把web服务器搭建成分布式的集群,然后利用LVS或Nginx做负载均衡,那么来自同一用户的Http请求将有可能被分发到两个不同的web站点中去。那么问题...

1.golang数据类型,转换,变量类型检查,生命周期、闭包,打印方法,指针简介

golang是强类型,静态语言 1.golang 数据类型 布尔类型 true/false var b bool ,在golang底层bool不是1/0表示的 数值类型 :var i int =3 / var i:=3 数字在计算机内部是以二进制的方式存储的,二进制位就是一系列布尔值,取值要么为1,要么为0. 1位表示1或0,对于4位整数可以表示16个不同...

Java如何正确的将数值转化为ArrayList?

Java中使用工具类Arrays.asList()看似可以把一个数组转为List,但实际使用时有两个坑:1、它是泛型方法,传入的参数必须是对象数组,当传入一个原生数据类型数组时,Arrays.asList() 的真正得到的参数就不是数组中的元素,而是数组对象本身。比如传入int[] intArray={1,2,3},它返回的list只有一个元素就是int...