本篇主要分享的是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.</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) .
--> <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{} - %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{} [%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请求,能够得到如下的日志结果:

  

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

 @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);
}

  如下是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;
}
}

springboot+aop切点记录请求和响应信息的更多相关文章

  1. Spring Boot使用AOP在控制台打印请求、响应信息

    AOP称为面向切面编程,在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等. AOP简介 AOP全称Aspect Oriented Programming,面向切面,AOP主要实现的 ...

  2. openresty(完整版)Lua拦截请求与响应信息日志收集及基于cjson和redis动态路径以及Prometheus监控(转)

    直接上文件 nginx.conf #运行用户和组,缺省为nobody,若改为别的用户和组,则需要先创建用户和组 #user wls81 wls; #开启进程数,一般与CPU核数等同 worker_pr ...

  3. nginx log记录请求的头信息

    记录访问的log,为了在出现特殊情况时,方便检查出现问题的地方.log_format accesslog ‘$remote_addr – $remote_user [$time_local] “$re ...

  4. 第14.14节 爬虫实战准备:csdn博文点赞过程http请求和响应信息分析

    如果要对csdn博文点赞,首先要登录CSDN,然后打开一篇需要点赞的文章,如<第14.1节 通过Python爬取网页的学习步骤>按<第14.3节 使用google浏览器获取网站访问的 ...

  5. 使用RestTemplate,显示请求信息,响应信息

    使用RestTemplate,显示请求信息,响应信息 这里不讲怎么用RestTemplate具体细节用法,就是一个学习中的过程记录 一个简单的例子 public class App { public ...

  6. Fiddler如何自动修改请求和响应包

    Charles的Map功能可以将某个请求进行重定向,用重定向的内容响应请求的内容.这个功能非常方便.在抓包过程当中,有时候为了调试方便,需要将线上的服务定位到内网.比如我们线上的服务器域名为 api. ...

  7. springboot aop 自定义注解方式实现完善日志记录(完整源码)

    版权声明:本文为博主原创文章,欢迎转载,转载请注明作者.原文超链接 一:功能简介 本文主要记录如何使用aop切面的方式来实现日志记录功能. 主要记录的信息有: 操作人,方法名,参数,运行时间,操作类型 ...

  8. springboot aop 自定义注解方式实现一套完善的日志记录(完整源码)

    https://www.cnblogs.com/wenjunwei/p/9639909.html https://blog.csdn.net/tyrant_800/article/details/78 ...

  9. Spring Boot中使用AOP记录请求日志

    这周看别人写的springboot后端代码中有使用AOP记录请求日志,以前没接触过,因此学习下. 一.AOP简介 AOP为Aspect Oriented Programming的缩写,意为:面向切面编 ...

随机推荐

  1. JSON数据格式转换

    json格式 (JavaScipt Object Notation):是一种数据交换格式!json语法规则:01.对象表现形式 key:value 键值对02.如果有多个数据,之间使用逗号隔开 k1: ...

  2. 借助HTML中的特殊符号在markdown中打印出来

    转自:https://blog.csdn.net/html5_/article/details/21639475 HTML中的特殊符号 原创 2014年03月20日 18:35:23 标签: HTML ...

  3. 【二分贪心】Bzoj3969 [WF2013] Low Power

    Description 有n个机器,每个机器有2个芯片,每个芯片可以放k个电池. 每个芯片能量是k个电池的能量的最小值. 两个芯片的能量之差越小,这个机器就工作的越好. 现在有2nk个电池,已知它们的 ...

  4. 集成支付宝SDK流程

    5.2 SDK集成流程 5.2.1 iOS 解压接口压缩文件(文件名是 WS_MOBILE_PAY_SDK_BASE.zip),找到iOS的压缩文件(文件名是支付宝移动支付SDK 标准版(iOS).z ...

  5. 【毕业原版】-《巴斯大学毕业证书》Bath一模一样原件

    ☞巴斯大学毕业证书[微/Q:865121257◆WeChat:CC6669834]UC毕业证书/联系人Alice[查看点击百度快照查看][留信网学历认证&博士&硕士&海归&am ...

  6. setContentType与setCharacterEncoding的区别

    setCharacterEncoding只是设置字符的编码方式 setContentType除了可以设置字符的编码方式还能设置文档内容的类型 1.setCharacterEncoding respon ...

  7. 深入浅出java常量池

    理论 jvm虚拟内存分布:      程序计数器是jvm执行程序的流水线,存放一些跳转指令.      本地方法栈是jvm调用操作系统方法所使用的栈.      虚拟机栈是jvm执行java代码所使用 ...

  8. 转载 python实例手册

    python实例手册 #encoding:utf8# 设定编码-支持中文 0说明 手册制作: 雪松 更新日期: 2013-12-19 欢迎系统运维加入Q群: 198173206 # 加群请回答问题 请 ...

  9. Mendeley使用小技巧

    合并重复论文 在导入论文时,可能出现新导入的一篇论文是自己之前看过的,但是可能因为某些原因,如来源不是同一个网址,arxiv 和 ICCV,两篇相同内容的文献同时存在. Mendeley 提供一个方法 ...

  10. asp.net core系列 61 Ocelot 构建服务发现简单示例

    一.概述 Ocelot允许指定服务发现提供程序,如Consul或Eureka. 这二个中间件是用来实现:服务治理或秒服务发现,服务发现查找Ocelot正在转发请求的下游服务的主机和端口.目前Ocelo ...