SpringBoot AOP统一处理Web请求日志

news/2024/11/14 23:37:57/

SpringBoot AOP统一处理Web请求日志

  • 引入依赖:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency>
  • 新建过滤器 WebLogAspect.java
    • 使用 @Aspect 注解修饰:说明当前类 是一个切面类。
    • 使用 @Component注解修饰:标记 切面类 为组件,这样 IOC 容器 会为其实例化和管理(< bean>)
  • 定义切面方法:webLog() 方法名随意
    • 使用环绕通知 @Around(“execution(public * com.daxiong.mall.Controller..(…))”) 注解修饰指定 切面范围。
@Around("execution(public * com.daxiong.mall.controller.*.*(..))")
public Object webLog(ProceedingJoinPoint pjp) {}
  • 记录请求 URL:
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
log.info("URL : " + request.getRequestURL().toString());
  • 请求类型:
log.info("HTTP_METHOD : " + request.getMethod());
  • IP 地址:
    • 若是本地 localhost,则会返回 ipv6 0:0:0:0:0:0:0:1
log.info("IP : " + request.getRemoteAddr());
  • 记录请求的 类以及方法:
    • 使用 环绕通知的 ProceedingJoinPoint 参数。
log.info("CLASS_METHOD : " + pjp.getSignature().getDeclaringTypeName() + "." + pjp.getSignature().getName());
  • 记录请求参数:
log.info("ARGS : " + Arrays.toString(pjp.getArgs()));
  • 执行方法,处理请求
Object res = pjp.proceed(pjp.getArgs());
  • 记录响应结果
    • 使用 jackson 将帝乡转换为 json 格式。
log.info("RESPONSE : " + new ObjectMapper().writeValueAsString(res));

全部:

/*** 打印请求和响应信息*/
@Aspect
@Component
public class WebLogAspect {private final Logger log = LoggerFactory.getLogger(WebLogAspect.class);@Around("execution(public * com.daxiong.mall.controller.*.*(..))")public Object webLog(ProceedingJoinPoint pjp) throws Throwable {log.info("========================新的请求========================");// 收到请求,记录请求内容ServletRequestAttributes attributes =(ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletRequest request = attributes.getRequest();log.info("URL : " + request.getRequestURL().toString());log.info("HTTP_METHOD : " + request.getMethod());// 若是 localhost,则会返回 0:0:0:0:0:0:0:1log.info("IP : " + request.getRemoteAddr());log.info("CLASS_METHOD : " + pjp.getSignature().getDeclaringTypeName() + "." + pjp.getSignature().getName());log.info("ARGS : " + Arrays.toString(pjp.getArgs()));// 执行方法,处理请求Object res = pjp.proceed(pjp.getArgs());// 记录响应log.info("RESPONSE : " + new ObjectMapper().writeValueAsString(res));return res;}
}

http://www.ppmy.cn/news/21345.html

相关文章

【面向对象】构造函数与析构函数详解

构造函数与析构函数详解 文章目录构造函数类型参考博客&#x1f60a;点此到文末惊喜↩︎ 构造函数 类型 默认构造函数&#xff08;缺省构造函数&#xff09; 一个类中只能出现一个默认构造函数在调用时&#xff0c;不需要传入实参。因为默认构造函数通常是无参的或所有形参都…

【Node.js实战】一文带你开发博客项目之Express重构(博客的增删查改、morgan写日志)

个人简介 &#x1f440;个人主页&#xff1a; 前端杂货铺 &#x1f64b;‍♂️学习方向&#xff1a; 主攻前端方向&#xff0c;也会涉及到服务端 &#x1f4c3;个人状态&#xff1a; 在校大学生一枚&#xff0c;已拿多个前端 offer&#xff08;秋招&#xff09; &#x1f680;未…

BIMCC4.0数仓基本概念

基本概念 文章目录基本概念基本思维数据对象字段视图关联关系验证行为事件表单字段字典基本思维 数据化思维:一切皆数据&#xff0c;包括对象、字段、视图、行为、事件&#xff0c;都是数据&#xff0c;这是信息化系统的基础抽象思维: 数据化了它就不再是实体&#xff0c;它是…

LeetCode刷题系列 -- 1080. 根到叶路径上的不足节点

给定一棵二叉树的根 root&#xff0c;请你考虑它所有 从根到叶的路径&#xff1a;从根到任何叶的路径。&#xff08;所谓一个叶子节点&#xff0c;就是一个没有子节点的节点&#xff09;假如通过节点 node 的每种可能的 “根-叶” 路径上值的总和全都小于给定的 limit&#xff…

运动耳机有必要买吗、口碑最好的运动耳机品牌排行

冬天绝对是个减肥的好季节&#xff0c;因为这个季节天气比较冷&#xff0c;我们在运动过程中消耗的热量也就会更多&#xff0c;因此选择一款不错的运动耳机来用坚持就显得尤为重要了。这款运动耳机要能稳定在耳朵上&#xff0c;还要具备防水功能&#xff0c;同时音质上也要有保…

Qt StyleSheet介绍

文章目录前言纠错技巧可以使用 , 号来同时指明多个同一类型控件的样式表qss注释前言 本文主要以这篇博客为基础。添加一些自己使用的心得和使用样式表的一些技巧 纠错 ID选择器这里类型选择器可以省略&#xff0c;因为每个控件的objectName是不一样的&#xff0c;所以无需指定…

(02)Cartographer源码无死角解析-(53) 2D后端优化→位姿图优化理论讲解、

讲解关于slam一系列文章汇总链接:史上最全slam从零开始&#xff0c;针对于本栏目讲解(02)Cartographer源码无死角解析-链接如下: (02)Cartographer源码无死角解析- (00)目录_最新无死角讲解&#xff1a;https://blog.csdn.net/weixin_43013761/article/details/127350885 文末…

算法leetcode|34. 在排序数组中查找元素的第一个和最后一个位置(rust重拳出击)

文章目录34. 在排序数组中查找元素的第一个和最后一个位置&#xff1a;样例 1&#xff1a;样例 2&#xff1a;样例 3&#xff1a;提示&#xff1a;分析&#xff1a;题解&#xff1a;rustgoccpythonjava34. 在排序数组中查找元素的第一个和最后一个位置&#xff1a; 给你一个按…