SpringBoot集成AOP实现每个接口请求参数和返回参数并记录每个接口请求时间

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: SpringBoot集成AOP实现每个接口请求参数和返回参数并记录每个接口请求时间

代码主要目的是controller方法进行日志记录,记录请求的内容、调用的方法、参数以及响应的内容和请求处理的时间。

1.介绍

AOP(Aspect-Oriented Programming,面向切面编程)是Spring框架中的一个重要特性,允许开发者定义跨多个对象的横切关注点。

在Spring Boot中,AOP的使用几个步骤:

  1. 定义Aspect:Aspect是包含一些advice(通知)的类。通知是实际执行的代码,它可以是一个方法或者一个lambda表达式。在Aspect中,你可以定义前置通知(Before)、后置通知(After)、返回通知(AfterReturning)、异常通知(AfterThrowing)等。
  2. 配置AspectJ自动代理
  3. 定义Pointcut表达式:Pointcut表达式定义了通知何时执行。你可以通过定义方法签名、类名、包名等来定义Pointcut表达式。
package com.up.cloud.core.aspect;
 
import cn.hutool.json.JSONUtil;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
 
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
 
/**
 * @author liu pei
 * @date 2023年11月24日 下午7:12
 * @Description:
 */
@Aspect
@Component
public class AccessLogAspect {
    private static final Logger log = LoggerFactory.getLogger(AccessLogAspect.class);
 
    /**
     * 起始时间的时间戳
     */
    private static final ThreadLocal<Long> START_TIME = new ThreadLocal<>();
 
    @Pointcut("execution(public * com.up.cloud.*.controller..*.*(..)) || execution(public * com.up.cloud.server.*.controller..*.*(..))")
    public void invokeLog() {
        // do something
    }
 
    @Before("invokeLog()")
    public void doBefore(JoinPoint joinPoint) {
        // 接收到请求,记录请求内容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        // 记录下请求内容
        //String args = Arrays.toString(joinPoint.getArgs());
        StringUtils.join(joinPoint.getArgs(),"");
        log.info(" Request URL : [{}, {}]", request.getMethod(), request.getRequestURL());
        log.info(" Class : [{}] , Method : [{}()]", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());
        log.info(" Request Param : {}", JSONUtil.toJsonStr(joinPoint.getArgs()));
        START_TIME.set(System.currentTimeMillis());
 
    }
 
    @AfterReturning(returning = "ret", pointcut = "invokeLog()")
    public void doAfterReturning(Object ret) {
        // 处理完请求,返回内容
        String jsonStr = JSONUtil.parseObj(ret).toString();
        log.info(" Response Body : {}", jsonStr.length() > 500 ? jsonStr.substring(0, 499) : jsonStr);
        log.info(" Response Time : {} ms ", (System.currentTimeMillis() - START_TIME.get()));
 
        START_TIME.remove();
    }
}

2.代码解释:

在AspectJ的AOP(面向切面编程)中,execution是一个特殊的Pointcut Designator (PDC)。它用于匹配方法的执行。
 
在给定的代码中:
 
java
@Pointcut("execution(public * com.up.cloud.*.controller..*.*(..)) || execution(public * com.up.cloud.server.*.controller..*.*(..))")  
public void invokeLog() {  
    // do something  
}
意思是匹配com.up.cloud`包及其子包下的所有public方法的执行。
其中:
 
 
*:表示方法名,第一个*表示方法名的第一个字符可以是任何字符,
第二个*表示方法名的第二个字符也可以是任何字符,
第三个*表示方法名的第三个字符可以是任何字符。
所以,.*(...)可以匹配任何方法名。
com.up.cloud.*.controller..*:表示类名。
第一个*表示com.up.cloud下的任意子包名,
第二个*表示该子包下的任意类名,第三个和第四个*分别表示类名的第二和第三个字符可以是任意字符。
所以,.controller..*可以匹配所有以controller结尾的类名。
这个Pointcut会匹配所有在com.up.cloud和com.up.cloud.server包及其子包下的
public controller类的方法执行。
 
简单地说,execution表示匹配某个方法的执行。

3.整体代码介绍

用于记录请求和响应的日志。

  1. 定义AspectAccessLogAspect 是一个Aspect,它包含了前置通知(Before)、后置通知(AfterReturning)功能。
  2. Pointcut定义:通过 @Pointcut 注解定义了一个切入点表达式,用于匹配com.up.cloudcom.up.cloud.server包下的所有public controller方法。
  3. 前置通知(Before)
  • @Before("invokeLog()"):在匹配到切入点的方法执行之前,执行前置通知的方法。
  • doBefore 方法中,首先获取了当前的请求信息,并记录了请求的URL、调用的类和方法以及请求参数。
  • 同时,还记录了当前的时间戳,用于后续计算请求处理时间。
  1. 后置通知(AfterReturning)
  • @AfterReturning(returning = "ret", pointcut = "invokeLog()"):在匹配到切入点的方法执行之后且在返回结果之前,执行后置通知的方法。
  • doAfterReturning 方法中,首先将返回的结果转换为JSON字符串并记录下来。
  • 计算并记录了请求处理的时间。
  • 最后清除了之前记录的起始时间。
  1. 日志记录:使用SLF4J的Logger来记录日志,记录了请求的URL、方法、参数以及响应的内容和请求处理的时间。
  2. 线程局部变量:使用 ThreadLocal 来存储起始时间,这样每个线程的起始时间都是独立的,不会互相干扰。

代码主要目的是对controller方法进行日志记录,记录请求的内容、调用的方法、参数以及响应的内容和请求处理的时间。

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
1月前
|
Java API 数据安全/隐私保护
(工作经验)优雅实现接口权限校验控制:基于自定义注解、AOP与@ConditionalOnProperty配置开关的通用解决方案
(工作经验)优雅实现接口权限校验控制:基于自定义注解、AOP与@ConditionalOnProperty配置开关的通用解决方案
58 1
|
1月前
|
Java Maven Docker
gitlab-ci 集成 k3s 部署spring boot 应用
gitlab-ci 集成 k3s 部署spring boot 应用
|
13天前
|
XML Java 数据库连接
SpringBoot集成Flowable:打造强大的工作流管理系统
在企业级应用开发中,工作流管理是一个核心组件,它能够帮助我们定义、执行和管理业务流程。Flowable是一个开源的工作流和业务流程管理(BPM)平台,它提供了强大的工作流引擎和建模工具。结合SpringBoot,我们可以快速构建一个高效、灵活的工作流管理系统。本文将探讨如何将Flowable集成到SpringBoot应用中,并展示其强大的功能。
50 1
|
23天前
|
JSON Java API
springboot集成ElasticSearch使用completion实现补全功能
springboot集成ElasticSearch使用completion实现补全功能
24 1
|
13天前
|
XML 存储 Java
SpringBoot集成Flowable:构建强大的工作流引擎
在企业级应用开发中,工作流管理是核心功能之一。Flowable是一个开源的工作流引擎,它提供了BPMN 2.0规范的实现,并且与SpringBoot框架完美集成。本文将探讨如何使用SpringBoot和Flowable构建一个强大的工作流引擎,并分享一些实践技巧。
37 0
|
1月前
|
前端开发 Java 程序员
springboot 学习十五:Spring Boot 优雅的集成Swagger2、Knife4j
这篇文章是关于如何在Spring Boot项目中集成Swagger2和Knife4j来生成和美化API接口文档的详细教程。
100 1
|
1月前
|
存储 数据可视化 JavaScript
可视化集成API接口请求+变量绑定+源码输出
可视化集成API接口请求+变量绑定+源码输出
46 4
|
1月前
|
JSON NoSQL Java
springBoot:jwt&redis&文件操作&常见请求错误代码&参数注解 (九)
该文档涵盖JWT(JSON Web Token)的组成、依赖、工具类创建及拦截器配置,并介绍了Redis的依赖配置与文件操作相关功能,包括文件上传、下载、删除及批量删除的方法。同时,文档还列举了常见的HTTP请求错误代码及其含义,并详细解释了@RequestParam与@PathVariable等参数注解的区别与用法。
|
2月前
|
缓存 前端开发 Java
springboot 的单体服务 字典参数转译
本文介绍了如何在Spring Boot项目中使用缓存来管理字典参数,并确保前后端数据一致性。首先,通过`@EnableCaching`启用缓存功能,接着创建一个自定义的字典缓存类`DicCache`。然后,通过配置类将`DicCache`添加到`cacheManager`中。此外,对字典服务进行改造,使用`@CachePut`和`@CacheEvict`注解保证数据一致性。最后,实现自定义注解`@DicSerializer`和序列化处理类`DictSerializerHandel`,用于在序列化过程中自动转换字典值。通过这种方式,可最小化代码改动并提高系统性能。
springboot 的单体服务 字典参数转译
|
1月前
|
存储 前端开发 Java
Spring Boot 集成 MinIO 与 KKFile 实现文件预览功能
本文详细介绍如何在Spring Boot项目中集成MinIO对象存储系统与KKFileView文件预览工具,实现文件上传及在线预览功能。首先搭建MinIO服务器,并在Spring Boot中配置MinIO SDK进行文件管理;接着通过KKFileView提供文件预览服务,最终实现文档管理系统的高效文件处理能力。
275 11

热门文章

最新文章

下一篇
无影云桌面