当前位置: 首页 > news >正文

【Java】自定义注解和AOP切面的使用

前言

我们在开发的过程中,一般都需要对方法的入参进行打印,或者Debug调试的时候我们要查看方法入参的参数是否数量和数据正确性。

一般我们需要知道请求的参数接口路径请求ip

但是考虑以后项目上线BUG排查的问题,最好的方式就是使用切面的方式来记录每个方法执行时要保存的日志处理,那么下面我们来实现一个使用自定义注解的方式来对每个请求的方法上进行日志存储

AOP切面:对某个方法进行增强处理,例如在某个方法执行前或者执行后进行操作。

案例

首先我们看一个controller接口

import lombok.extern.slf4j.Slf4j;@Slf4j
@RestController
@RequestMapping("/user/")
public class TestController {@PostMapping("getUserById")public String getUserById(@RequestBody User user) {log.info("/user/getUserById params:{}", user.toString());//执行代码逻辑...return "请求成功";}
}

这种一般没什么问题,一般我们测试的时候都可以这样来写,但如果有很多的方法,那么每个方法都这样写,显然很是繁琐,那么我们通过下面的方式来实现当进入方法前打印请求的一些信息

实现

我们自定义一个注解,名为Itboy

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)//ElementType.METHOD表示为该注解在方法上添加
public @interface Itboy {
}

然后需要用到一些依赖,这些是使用AOP的依赖,我们提前引入一下

<dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.8.14</version>
</dependency>
<dependency><groupId>org.aspectj</groupId><artifactId>aspectjrt</artifactId><version>1.9.19</version>
</dependency>

然后我们定义一个切面类,名为ItboyAspect
注:这篇文章我使用的System打印方式,如果需要保存日志,换为对应的logger.info()即可。

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
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.text.SimpleDateFormat;
import java.util.Date;@Component
@Aspect
@Slf4j
public class ItboyAspect {//@Pointcut:为切入点,切入到Itboy这个注解上面@Pointcut("@annotation(com.mayikt.demo.Itboy)")public void itboyAspect() {}//@Before为在进入切点之前自动执行Before中的逻辑(进入之前的前提是方法上需要有我们设置的自定注解)@Before("itboyAspect()")public void beforeItboy(JoinPoint joinPoint) {//获取本次请求ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletRequest request = requestAttributes.getRequest();//获取到方法名String methodName = joinPoint.getSignature().getName();System.err.println("======================================方法:" + methodName + "() 开始======================================");//执行时间SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");Date date = new Date();String time = sdf.format(date);System.err.println("时间                 : " + time);//请求URLSystem.err.println("URL                 : " + request.getRequestURL());//请求方法System.err.println("HTTP Method         : " + methodName);//打印controller全路径和执行方法System.err.println("Class Method        : " + joinPoint.getSignature().getDeclaringTypeName() + "." + methodName);//请求IPSystem.err.println("IP                  : " + request.getRemoteHost());//请求入参System.err.println("Requert params      : " + JSON.toJSONString(joinPoint.getArgs()));}//后置通知@After("itboyAspect()")public void afterItboy(JoinPoint joinPoint) {//获取到方法名String methodName = joinPoint.getSignature().getName();System.err.println("======================================方法:" + methodName + "() 结束======================================");}
}

然后我们只需要在需要保存的方法上添加@Itboy注解即可

	@Itboy@PostMapping("selectUserList")public String getUserById(@RequestBody User user) {log.info("/user/selectUserList params:{}", user.toString());//执行代码逻辑...return "请求成功";}

最后我们来看一下效果

2023-04-02 14:21:29.033  INFO 5912 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 1 ms
======================================方法:getUserById() 开始======================================
时间                 : 2023-04-02 14:21:29
URL                 : http://127.0.0.1:8080/user/selectUserList
HTTP Method         : getUserById
Class Method        : com.mayikt.demo.TestController.getUserById
IP                  : 127.0.0.1
Requert params      : [{"address":"华东","age":18,"id":10010,"name":"贾强"}]
======================================方法:getUserById() 结束======================================
2023-04-02 14:21:29.171  INFO 5912 --- [nio-8080-exec-1] com.mayikt.demo.TestController           : /user/selectUserList params:User(id=10010, name=贾强, age=18, address=华东)

总结

使用上面这种方式,减轻了我们自己手动日志打印的繁琐,而且配置也相对于比较简单,如果有其他需求是比较频繁的操作的话,我们就可以使用AOP切面的方式来完成。

肥肠好用

相关文章:

【Java】自定义注解和AOP切面的使用

前言 我们在开发的过程中&#xff0c;一般都需要对方法的入参进行打印&#xff0c;或者Debug调试的时候我们要查看方法入参的参数是否数量和数据正确性。 一般我们需要知道请求的参数、接口路径、请求ip等 但是考虑以后项目上线BUG排查的问题&#xff0c;最好的方式就是使用…...

前后台协议联调拦截器

前后台协议联调&拦截器4&#xff0c;前后台协议联调4.1 环境准备4.2 列表功能4.3 添加功能4.4 添加功能状态处理4.5 修改功能4.6 删除功能5&#xff0c;拦截器5.1 拦截器概念5.2 拦截器入门案例5.2.1 环境准备5.2.2 拦截器开发步骤1:创建拦截器类步骤2:配置拦截器类步骤3:S…...

【还在传统绑骨骼动画?】让AI助力你实现2D游戏角色动画流程

思路&#xff08;让3D模型替代动作&#xff09; 一、利用MJ或者SD生成你需要的游戏角色&#xff08;获取原图像&#xff09; 需要的知识&#xff1a; 会调关键词chatGpt&#xff08;看小红书、抖音、B站、Youtube、Telegrame等等都行&#xff0c;别傻忽忽跑到知识星球被收割…...

动态规划+例题

适用场景 题目链接&#xff1a;数字三角形 /*正推DP&#xff0c;可能数据比较小&#xff0c;这个正推不太麻烦可以AC*/ #include<bits/stdc.h> using namespace std; int r; int a[1005][1005],f[1005][1005];int main(){cin>>r;for(int i1;i<r;i){for(int j1…...

快商通荣获多个政府科技、人才奖项

近日&#xff0c;快商通与快商通首席科学家李海洲教授荣获由厦门市科学技术局、厦门市委人才办等多部门发布的“2022年度厦门市科学技术奖”、“2022厦门十大成长性人才企业”、“2022厦门战略性新兴产业十大创新人才”等多个 政府科技、人才奖项 &#xff0c;并进行全网公示。…...

Linux的基本命令的使用

文章目录一、初识LinuxLinux目录结构二、如何拥有一个Linux环境&#xff1f;三、Linux命名Linux命令基础lscd pwd特殊路径符clearmkdirtouch cat morecp mv rmsuwhich findgrep wc 管道符ehco tail 重定向符psnetstatvi vim一、初识Linux 我们的计算机由硬件和软件两部分组成&…...

RecycleView小结

RecycleView四级缓存 一级缓存&#xff1a;用于存放当前屏幕可显示区域的ViewHolder&#xff0c;目的是为了方便更新数据&#xff0c;以及对View操作时更加快捷二级缓存&#xff1a;用于缓存最近滑动出屏幕的ViewHolder&#xff0c;目的是为了当用户将该View滑出屏幕外时又突然…...

【Python】如何实现Redis构造简易客户端(教程在这)

文章目录前言一、准备二、原理剖析三、编写简易Redis客户端总结前言 Redis 是我们在开发过程中经常会用到的内存数据库&#xff0c;尤其是在Python的第三方模块Redis-py的支持下&#xff0c;在Python中使用Redis及其方便。 但是在有些情况下&#xff0c;我们无法使用像Redis-…...

326. 3 的幂 ——【Leetcode每日一题】

326. 3 的幂 给定一个整数&#xff0c;写一个函数来判断它是否是 3 的幂次方。如果是&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 整数 n 是 3 的幂次方需满足&#xff1a;存在整数 x 使得 n3xn 3^xn3x。 示例 1&#xff1a; 输入&#xff1a;n 27 …...

UE4 Sequence学习

1.常用轨道 1.1 Camera轨道 Camera轨道可以理解为Camera Cuts轨道和Camera Actor轨道&#xff0c;一般点击Sequencer上的摄像机图标可以自动创建&#xff1a; Camera Cuts轨道&#xff0c;可以进行不同相机机位的切换&#xff0c;一般会随着Camera Actor轨道自动创建&#x…...

总结MySQL、Redis的优化措施与使用 mysql_upgrade升级数据结构

目录 一.MySQL数据库优化 二.Redis优化 三.MySQL创建测试账号报错 一.MySQL数据库优化 遵循MySQL层优化的五个原则: 减少数据访问&#xff0c;返回更少的数据&#xff0c;减少交互次数减少服务器CPU开销&#xff0c;利用更多资源。理解SQL优化原理并进行SQL优化&#xff0c…...

C++11线程库

C11线程库 本质是对不同平台的线程库进行封装。因为windows和linux下各有自己的接口&#xff0c;这使得代码的可移植性比较差。C11中最重要的特性就是对线程进行支持了&#xff0c;使得C在并行编程时不需要依赖第三方库&#xff0c;而且在原子操作中还引入了原子类的概念。要使…...

智能化生产,提高效率!使用关键词采集工具助力企业数字化转型

关键词采集工具在企业数字化转型中的优势和作用进行阐述。 随着信息技术的不断发展&#xff0c;企业数字化转型已经成为了企业发展的必然趋势。 对于各种规模的企业而言&#xff0c;数字化转型可以提升企业的生产效率、降低成本、提高产品质量等方面带来更多的发展机遇。 而关…...

浅谈自动化测试用例创建和文档

通过自动创建测试用例和文档&#xff0c;探索自然语言处理 (NLP) 在革新软件测试方面的变革力量。 技术的快速发展导致对高效和有效的软件测试方法的需求增加。该领域最有前途的进步之一是自然语言处理 (NLP) 技术的集成。NLP 是人工智能(AI)的一个子集&#xff0c;专注于通过…...

[Java Web]AJAX Axios | 一种结合HTML来取代传统JSP的技术

⭐作者介绍&#xff1a;大二本科网络工程专业在读&#xff0c;持续学习Java&#xff0c;努力输出优质文章 ⭐作者主页&#xff1a;逐梦苍穹 ⭐所属专栏&#xff1a;Java Web 目录1、AJAX1.1、简介1.2、作用1.3、同步和异步1.4、代码实现1.4.1、服务端1.4.2、客户端1.4.2.1、完善…...

【C++】多态问答题

前言 本篇仅整理一些比较偏的多态的问答题 文章目录前言一. 内联与虚函数二. 静态函数与虚函数三. 构造函数与虚函数四. 虚函数与普通函数结束语一. 内联与虚函数 内联函数可以是虚函数吗&#xff1f; 首先我们看一下语法有没有问题 我们看到&#xff0c;程序成功运行了&#…...

【设计模式】适配器模式

一&#xff0c;定义适配器模式&#xff1a;结构型模式之一&#xff0c;适配器提供客户类需要的接口&#xff0c;适配器的实现就是把客户类的请求转化为对适配者的相应接口的调用。也就是说:当客户类调用适配器的方法时&#xff0c;在适配器类的内部将调用适配者类的方法&#x…...

跨域之CorsFilter

跨域之CorsFilter CorsFilter 是 Spring 框架提供的一个用于处理跨域请求的过滤器。在开发中&#xff0c;我们常常需要处理前端发来的跨域请求&#xff0c;CorsFilter 就可以帮助我们实现这一功能。 CorsFilter 主要用于设置跨域请求的响应头&#xff0c;以允许跨域请求能够被…...

STM32基于HAL工程读取DS1302时间数据

STM32基于HAL工程读取DS1302时间数据✨申明&#xff1a;本文章仅发表在CSDN网站&#xff0c;任何其他网站&#xff0c;未注明来源&#xff0c;见此内容均为盗链和爬取&#xff0c;请多多尊重和支持原创!&#x1f341;对于文中所提供的相关资源链接将作不定期更换。&#x1f4cc…...

《Effective Objective-C 2.0 》 阅读笔记 item10

第10条&#xff1a;在既有类中使用关联对象存放自定义数据 1. 关联对象 可以给某对象关联许多其他对象&#xff0c;这些对象通过“键”来区分&#xff0c;这就是关联对象。存储对象值的时候&#xff0c;可以指明“存储策略”&#xff08;storage policy&#xff09;&#xff…...

Android Wi-Fi 连接失败日志分析

1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分&#xff1a; 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析&#xff1a; CTR…...

23-Oracle 23 ai 区块链表(Blockchain Table)

小伙伴有没有在金融强合规的领域中遇见&#xff0c;必须要保持数据不可变&#xff0c;管理员都无法修改和留痕的要求。比如医疗的电子病历中&#xff0c;影像检查检验结果不可篡改行的&#xff0c;药品追溯过程中数据只可插入无法删除的特性需求&#xff1b;登录日志、修改日志…...

MMaDA: Multimodal Large Diffusion Language Models

CODE &#xff1a; https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA&#xff0c;它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构&#xf…...

MVC 数据库

MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...

苍穹外卖--缓存菜品

1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得&#xff0c;如果用户端访问量比较大&#xff0c;数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据&#xff0c;减少数据库查询操作。 缓存逻辑分析&#xff1a; ①每个分类下的菜品保持一份缓存数据…...

代理篇12|深入理解 Vite中的Proxy接口代理配置

在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...

SQL慢可能是触发了ring buffer

简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...

mac:大模型系列测试

0 MAC 前几天经过学生优惠以及国补17K入手了mac studio,然后这两天亲自测试其模型行运用能力如何&#xff0c;是否支持微调、推理速度等能力。下面进入正文。 1 mac 与 unsloth 按照下面的进行安装以及测试&#xff0c;是可以跑通文章里面的代码。训练速度也是很快的。 注意…...

用鸿蒙HarmonyOS5实现中国象棋小游戏的过程

下面是一个基于鸿蒙OS (HarmonyOS) 的中国象棋小游戏的实现代码。这个实现使用Java语言和鸿蒙的Ability框架。 1. 项目结构 /src/main/java/com/example/chinesechess/├── MainAbilitySlice.java // 主界面逻辑├── ChessView.java // 游戏视图和逻辑├──…...

基于开源AI智能名片链动2 + 1模式S2B2C商城小程序的沉浸式体验营销研究

摘要&#xff1a;在消费市场竞争日益激烈的当下&#xff0c;传统体验营销方式存在诸多局限。本文聚焦开源AI智能名片链动2 1模式S2B2C商城小程序&#xff0c;探讨其在沉浸式体验营销中的应用。通过对比传统品鉴、工厂参观等初级体验方式&#xff0c;分析沉浸式体验的优势与价值…...