Spring AOP记录接口访问日志

Spring AOP记录接口访问日志

  • 介绍
  • 应用范围
  • 组成
    • 通知(Advice)
    • 连接点(JoinPoint)
    • 切点(Pointcut)
    • 切面(Aspect)
    • 引入(Introduction)
    • 织入(Weaving)
  • Spring Aop
    • 相关注解
    • 切点表达式
  • 实现接口日志记录
    • 添加日志信息封装类WebLog
    • 添加切面类WebLogAspect
    • 进行接口测试
  • 源码地址

介绍

AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

应用范围

后端接口设计时是需要考虑登录认证,除了注册、登录和注销等特殊操作外,其他的请求都需要进行校验是否登录、登录身份认证,普通的方式是每个controller都得重复编写登录认证的接口,若后面进行功能扩展,重复的代码就增加,不利于维护,所以aop就发挥作用了。
除了统⼀的用户登录判断之外,AOP 还可以实现:

  • 统⼀⽇志记录
  • 统⼀⽅法执⾏时间统计
  • 统⼀返回格式
  • 统⼀异常处理
  • 事务开启和提交

也就是说使用 AOP 可以扩充多个对象的某个能力,所以 AOP 可以说是 OOP(Object Oriented Programming,⾯向对象编程)的补充和完善。

组成

通知(Advice)

通知描述了切面要完成的工作以及何时执行

  • 前置通知(Before):在目标方法调用前调用通知功能;
  • 后置通知(After):在目标方法调用之后调用通知功能,不关心方法的返回结果;
  • 返回通知(AfterReturning):在目标方法成功执行之后调用通知功能;
  • 异常通知(AfterThrowing):在目标方法抛出异常后调用通知功能;
  • 环绕通知(Around):通知包裹了目标方法,在目标方法调用之前和之后执行自定义的行为。

连接点(JoinPoint)

通知功能被应用的时机。比如接口方法被调用的时候就是日志切面的连接点。

切点(Pointcut)

切点定义了通知功能被应用的范围。比如日志切面的应用范围就是所有接口,即所有controller层的接口方法。

切面(Aspect)

切面是通知和切点的结合,定义了何时、何地应用通知功能。

引入(Introduction)

在无需修改现有类的情况下,向现有的类添加新方法或属性。

织入(Weaving)

把切面应用到目标对象并创建新的代理对象的过程。

Spring Aop

相关注解

@Aspect:用于定义切面
@Before:通知方法会在目标方法调用之前执行
@After:通知方法会在目标方法返回或抛出异常后执行
@AfterReturning:通知方法会在目标方法返回后执行
@AfterThrowing:通知方法会在目标方法抛出异常后执行
@Around:通知方法会将目标方法封装起来
@Pointcut:定义切点表达式

切点表达式

指定了通知被应用的范围,表达式格式:

execution(方法修饰符 返回类型 方法所属的包.类名.方法名称(方法参数)
//com.macro.mall.tiny.controller包中所有类的public方法都应用切面里的通知
execution(public * com.macro.mall.tiny.controller.*.*(..))
//com.macro.mall.tiny.service包及其子包下所有类中的所有方法都应用切面里的通知
execution(* com.macro.mall.tiny.service..*.*(..))
//com.macro.mall.tiny.service.PmsBrandService类中的所有方法都应用切面里的通知
execution(* com.macro.mall.tiny.service.PmsBrandService.*(..))

实现接口日志记录

添加日志信息封装类WebLog

用于封装需要记录的日志信息,包括操作的描述、时间、消耗时间、url、请求参数和返回结果等信息。

/*** Controller层的日志封装类*/
public class WebLog {/*** 操作描述*/private String description;/*** 操作用户*/private String username;/*** 操作时间*/private Long startTime;/*** 消耗时间*/private Integer spendTime;/*** 根路径*/private String basePath;/*** URI*/private String uri;/*** URL*/private String url;/*** 请求类型*/private String method;/*** IP地址*/private String ip;/*** 请求参数*/private Object parameter;/*** 请求返回的结果*/private Object result;//省略了getter,setter方法
}

添加切面类WebLogAspect

定义了一个日志切面,在环绕通知中获取日志需要的信息,并应用到controller层中所有的public方法中去。

/*** 统一日志处理切面*/
@Aspect
@Component
@Order(1)
public class WebLogAspect {private static final Logger LOGGER = LoggerFactory.getLogger(WebLogAspect.class);@Pointcut("execution(public * com.sheep.controller.*.*(..))")public void webLog() {}@Before("webLog()")public void doBefore(JoinPoint joinPoint) throws Throwable {}@AfterReturning(value = "webLog()", returning = "ret")public void doAfterReturning(Object ret) throws Throwable {}@Around("webLog()")public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {long startTime = System.currentTimeMillis();//获取当前请求对象ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletRequest request = attributes.getRequest();//记录请求信息WebLog webLog = new WebLog();Object result = joinPoint.proceed();Signature signature = joinPoint.getSignature();MethodSignature methodSignature = (MethodSignature) signature;Method method = methodSignature.getMethod();if (method.isAnnotationPresent(ApiOperation.class)) {ApiOperation apiOperation = method.getAnnotation(ApiOperation.class);webLog.setDescription(apiOperation.value());}long endTime = System.currentTimeMillis();String urlStr = request.getRequestURL().toString();webLog.setBasePath(StrUtil.removeSuffix(urlStr, URLUtil.url(urlStr).getPath()));webLog.setIp(request.getRemoteUser());webLog.setMethod(request.getMethod());webLog.setParameter(getParameter(method, joinPoint.getArgs()));webLog.setResult(result);webLog.setSpendTime((int) (endTime - startTime));webLog.setStartTime(startTime);webLog.setUri(request.getRequestURI());webLog.setUrl(request.getRequestURL().toString());LOGGER.info("{}", JSONUtil.parse(webLog));return result;}/*** 根据方法和传入的参数获取请求参数*/private Object getParameter(Method method, Object[] args) {List<Object> argList = new ArrayList<>();Parameter[] parameters = method.getParameters();for (int i = 0; i < parameters.length; i++) {//将RequestBody注解修饰的参数作为请求参数RequestBody requestBody = parameters[i].getAnnotation(RequestBody.class);if (requestBody != null) {argList.add(args[i]);}//将RequestParam注解修饰的参数作为请求参数RequestParam requestParam = parameters[i].getAnnotation(RequestParam.class);if (requestParam != null) {Map<String, Object> map = new HashMap<>();String key = parameters[i].getName();if (!StringUtils.isEmpty(requestParam.value())) {key = requestParam.value();}map.put(key, args[i]);argList.add(map);}if (requestParam == null && requestBody == null && args != null) {return args;}}if (argList.size() == 0) {return null;} else if (argList.size() == 1) {return argList.get(0);} else {return argList;}}
}

进行接口测试

运行项目并访问:http://localhost:8080/swagger-ui.html

访问下查询接口看看效果
在这里插入图片描述
在这里插入图片描述

源码地址

https://gitee.com/yang1112/learn-project.git

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/190547.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux--初识和基本的指令(3)

目录 1.前言 1.指令 1.1 cat指令 1.2 echo指令 1.3 more 指令 1.4 less指令 1.5 什么时候使用less和more 1.6 head指令 1.7 tail指令 1.8 wc指令 1.9 与时间相关的指令 1.9.1 date指令 1.9.2 cal指令 1.10 16.find指令&#xff1a;&#xff08;灰常重要&#x…

千梦网创:熟悉抖音内容创作的切入方式

因为身边抖音网红的资源比较近&#xff0c;所以虽然一直没有露脸去做短视频运营&#xff0c;但是最近也是跟随朋友一起开始了短视频的学习之路。 在参观过一些“超级直播间”之后&#xff0c;我们敲定了未来的两个盈利方向&#xff0c;这两个方向可以将我们身边的资源极致利用…

MyBatis-逆向工程

1.简单生成 1.添加依赖和插件 <dependencies><!-- MyBatis核心依赖包 --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.9</version></dependency><!-- MySQL驱动…

金蝶Apusic应用服务器deployApp接口任意文件上传漏洞复现 [附POC]

文章目录 金蝶Apusic应用服务器deployApp接口任意文件上传漏洞复现 [附POC]0x01 前言0x02 漏洞描述0x03 影响版本0x04 漏洞环境0x05 漏洞复现1.访问漏洞环境2.构造POC3.复现 0x06 修复建议 金蝶Apusic应用服务器deployApp接口任意文件上传漏洞复现 [附POC] 0x01 前言 免责声明…

【前端】-【electron】

文章目录 介绍electron工作流程环境搭建 electron生命周期&#xff08;app的生命周期&#xff09;窗口尺寸窗口标题自定义窗口的实现阻止窗口关闭父子及模态窗口自定义菜单 介绍 electron技术架构&#xff1a;chromium、node.js、native.apis electron工作流程 桌面应用就是…

常见的攻击防护

只做模拟机器使用&#xff0c;不使用真实机器 目录 一、 DHCP饿死和防护应对措施.................................. 1 1&#xff0c; 实验拓扑&#xff1a;...................................................... 2 2&#xff0c; 实验配置............................…

Web自动化测试怎么做?Web自动化测试的详细流程和步骤

1.什么是web自动化测试 自动化&#xff08;Automation&#xff09;是指机器设备、系统或过程&#xff08;生产、管理过程&#xff09;在没有人或较少人的直接参与下&#xff0c;按照人的要求&#xff0c;经过自动检测、信息处理、分析判断、操纵控制&#xff0c;实现预期的目标…

opencv阈值处理

阈值处理 二值化 自适应阈值 OTSU二值化

latex表格中内容过多如何换行【已解决】

最近在写论文的时候放了一个表格&#xff0c;但是表格看起来特别大&#xff0c;因为想让某些内容多的单元格完成换行操作 首先在main.tex引入makecell包 \usepackage{makecell} 然后回到表格找到你想换行的单元格&#xff0c;把\makecell{}加进去&#xff0c;然后在需要换行的…

基于物联网技术的基站能耗监控解决方案-安科瑞 蒋静

摘 要&#xff1a;随着社会的不断发展和进步&#xff0c;人们对通信基站的需求增加。随着通信基站大规模的建设和使用&#xff0c;基站内部的电源情况、供电安全保障或节能减排等问题&#xff0c;仍然是基站建设的着重问题。不管是建设者还是使用者&#xff0c;都应当注重用电安…

[socket 弹 shell] msg_box3

前言 题目比较简单&#xff0c;没开 Canary 和 NX. Arch: amd64-64-littleRELRO: Full RELROStack: Canary foundNX: NX disabledPIE: PIE enabledRWX: Has RWX segments 漏洞利用与分析&#xff1a; 白给的函数调用&#xff0c;其中 ptr 10 是用…

Long-Context下LLM模型架构全面介绍

深度学习自然语言处理 原创作者&#xff1a;cola 随着ChatGPT的快速发展&#xff0c;基于Transformer的大型语言模型(LLM)为人工通用智能(AGI)铺平了一条革命性的道路&#xff0c;并已应用于知识库、人机界面和动态代理等不同领域。然而&#xff0c;存在一个普遍的限制:当前许多…

模拟业务流程+构造各种测试数据,一文带你测试效率提升80%

我们做软件测试的时候&#xff0c;经常需要页面有点数据&#xff0c;特别是涉及到一些数据统计的测试用例的时候&#xff0c;更是需要源源不断的测试数据让前端页面生成对应的报表测试统计的数据正确性。 如果我们通过手工的方式操作业务流程来实现数据的构造的话&#xff0c;少…

【Cisco Packet Tracer】子网划分的计算及实验

子网划分&#xff1a;Internet组织机构定义了五种IP地址&#xff0c;有A、B、C三类地址。A类网络有126个&#xff0c;每个A类网络可能有16777214台主机&#xff0c;它们处于同一广播域。而在同一广播域中有这么多节点是不可能的&#xff0c;网络会因为广播通信而饱和&#xff0…

在 ArcGIS 软件中添加左斜宋体(东体)的方法与步骤

河流水系在作图时一般设置为左斜宋体&#xff08;东体&#xff09;、蓝色&#xff0c;比如黄河、青海湖等&#xff0c;如下图所示&#xff1a; 标准地图水系注记 下面讲解如何在 ArcGIS 软件中添加左斜宋体&#xff08;东体&#xff09;&#xff0c;首先需要下载左斜宋体&#…

【开源】基于JAVA语言的校园疫情防控管理系统

项目编号&#xff1a; S 037 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S037&#xff0c;文末获取源码。} 项目编号&#xff1a;S037&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 学生2.2 老师2.3 学校管理部门 三、…

《管家婆》辉煌2005+(V4.0)简单教程

《管家婆》辉煌2005&#xff08;V4.0&#xff09;简单教程 呉師傅 运行环境&#xff1a;   操作系统推荐使用Win2000&#xff08;32位&#xff09;、WinXP&#xff08;32位&#xff09;、Win7&#xff08;位&#xff09; 兼容&#xff1a;Win7&#xff08;64位&#xff09…

阿里云MySQL从 2003->1251->1396

目的 由于需要在阿里云的实例中装MySQL数据库&#xff0c;安装前期&#xff08;本地访问&#xff09;还是挺顺利的&#xff0c;但是到了远程连接的时候&#xff0c;却出现了一系列的Bug&#xff0c;以为是没有 实名认证没有备案 的原因导致的&#xff0c;但是后来…

vue中中的动画组件使用及如何在vue中使用animate.css

“< Transition >” 是一个内置组件&#xff0c;这意味着它在任意别的组件中都可以被使用&#xff0c;无需注册。它可以将进入和离开动画应用到通过默认插槽传递给它的元素或组件上。进入或离开可以由以下的条件之一触发&#xff1a; 由 v-if 所触发的切换由 v-show 所触…

Kubernetes中PostgreSQL的推荐方法

1*HDp3_wvu78Vaa-4C9NFHaQ.gif 你是否曾听说过避免在Kubernetes中运行数据库的建议&#xff1f;有人认为Kubernetes不适合有状态的应用程序&#xff0c;但这些说法是否属实&#xff1f;让我们深入探讨并挑战这些说法。 Kubernetes&#xff1a;有关有状态工作负载的误解平台 在涉…