【工作记录】springboot集成aop实现日志@20230918

news2024/11/25 10:36:47

springboot集成aop实现日志

1. 添加依赖

<!-- aop 依赖 -->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

2. 定义注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ActionLog {

    String action() default "";

    String topic() default "";

}

3. 定义切面类

import com.cnhqd.authcenter.framework.common.utils.IpUtils;
import com.cnhqd.authcenter.framework.common.utils.JsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

@Slf4j
@Aspect
@Component
public class ActionLogAspect {

  @Pointcut("@annotation(com.cnhqd.authcenter.framework.common.log.ActionLog)")
  public void actionLog() {

  }

  /*** 在切点之前织入* @param joinPoint* @throws Throwable*/
  @Before("actionLog()")
  public void doBefore(JoinPoint joinPoint) throws Exception {
    // 开始打印请求日志
    ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
    HttpServletRequest request = attributes.getRequest();// 打印请求相关参数
    log.info("=================== Start ====================");
    // 打印请求url
    log.info("URL            : {}", request.getRequestURL().toString());
    // 打印Httpmethod
    log.info("HTTP Method    : {}", request.getMethod());
    // 打印调用 controller 的全路径以及执行方法
    log.info("Class Method   : {}.{}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());
    // 打印请求的IP
    log.info("IP             : {}", IpUtils.getIpAddr(request));
    // 打印请求入参
    log.info("Request Args   : {}", JsonUtils.toJsonString(joinPoint.getArgs()));
    ActionLog annotation = ((MethodSignature) joinPoint.getSignature()).getMethod().getAnnotation(ActionLog.class);
    log.info("topic          :{}", annotation.topic());
    log.info("action         :{}", annotation.action());
  }

  @AfterReturning("actionLog()")
  public void afterReturning(){
    log.info("result        :{}", 200);
    log.info("=================== End ====================");
  }

  @AfterThrowing(pointcut = "actionLog()", throwing = "ex")
  public void afterThrowing(Throwable ex) {
    log.info("result        :{}", ex.getMessage());
    log.info("=================== End ====================");
  }

}

各注解说明:

@Aspect:声明该类为一个注解类;  

@Pointcut:定义一个切点,后面跟随一个表达式,表达式可以定义为某个 package 下的方法,也可以是自定义注解等;  

@Before: 在切点之前,织入相关代码;  

@After: 在切点之后,织入相关代码;  

@AfterReturning: 在切点返回内容后,织入相关代码,一般用于对返回值做些加工处理的场景;  

@AfterThrowing: 用来处理当织入的代码抛出异常后的逻辑处理;  

@Around: 在切入点前后织入代码,并且可以自由的控制何时执行切点;

4. 简单测试

编写测试controller

import com.cnhqd.authcenter.framework.common.log.ActionLog;
import com.cnhqd.authcenter.system.vo.SysAccountLoginVO;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("testAops")
public class TestAopsController {

    @GetMapping("get")
    @ActionLog(action = "get", topic = "测试AOP")
    public String get(String id) {
        return id;
    }

    @PostMapping("post")
    @ActionLog(action = "post", topic = "测试AOP")
    public String post(@RequestBody SysAccountLoginVO vo) {
        System.out.println(JsonUtils.toJsonString(vo));
        return "success";
    }

    @GetMapping("getEx")
    @ActionLog(action = "getEx", topic = "测试AOP")
    public String getEx() {
        throw new RuntimeException("getEx-这里是异常输出测试");
    }

    @PostMapping("postEx")
    @ActionLog(action = "postEx", topic = "测试AOP")
    public String postEx() {
        throw new RuntimeException("postEx-这里是异常输出测试");
    }
}

使用postman发送对应请求,观察控制台输出
postman-get
console-get
postman-getEx
console-getEx
postman-post
console-post
postman-postEx
console-postEx
可以看到日志可以正常输出,如有必要保存相关数据到数据库即可。

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

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

相关文章

HarmonyOS之 应用程序页面UIAbility

一 UIAbility介绍&#xff1a; 1.1 UIAbility是一种包含用户界面的应用组件&#xff0c;用于和用户进行交互UIAbility是系统调度的单元、提1.2 供窗口用于界面绘制2. UIAbility的创建和对应页面的创建 1.3 UIAbility内页面间的跳转 1.4 UIAbility的创建、前后台切换、销毁的生…

要如何选择报修工单管理系统?需要注意哪些核心功能?

现如今&#xff0c;越来越多的企业已经离不开报修工单管理系统&#xff0c;但市面上的产品繁多&#xff0c;很难寻找到一款特别符合企业需求的系统。企业采购报修工单管理系统的主要目的在于利用其核心功能&#xff0c;如工单流转等&#xff0c;来解决工作事件的流程问题&#…

uniapp----微信小程序 日历组件(周日历 月日历)【Vue3+ts+uView】

uniapp----微信小程序 日历组件&#xff08;周日历&& 月日历&#xff09;【Vue3tsuView】 用Vue3tsuView来编写日历组件&#xff1b;存在周日历和月日历两种显示方式&#xff1b;高亮显示当天日期&#xff0c;红点渲染有数据的日期&#xff0c;点击显示数据 1. calenda…

滑动时间窗口统计 QPS

一、代码 1、先上实现代码&#xff0c;如下 package cn.jt.emqxspringbootdesignpattern.emqx.controller;import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExec…

如何提取视频中的音频转为mp3

如何提取视频中的音频转为mp3&#xff1f;在丰富多样的视频作品中&#xff0c;我们常常会遇到一些引人入胜的对话和有趣的音乐变奏。不少朋友可能曾经看过那种画面与其他作品声音巧妙搭配&#xff0c;给人带来无比愉悦和和谐感的趣味作品。然而&#xff0c;很多人虽然有着相似的…

小程序中如何查看会员卡的注册时间

会员系统是小程序中非常重要的一部分&#xff0c;可以帮助企业更好地管理客户&#xff0c;并提供更好的服务。在实际应用中&#xff0c;我们经常需要查看会员的注册时间&#xff0c;以便更好地了解客户的行为和需求。本文将介绍小程序如何查看会员的注册时间。 1. 找到指定的…

uniapp后台播放音频功能制作

在UniApp中&#xff0c;你可以使用uni.getRecorderManager()方法来创建一个录音管理器实例。但是&#xff0c;请注意&#xff0c;录音管理器并不直接用于后台音频播放功能&#xff0c;而是用于录制音频。如果想要在后台播放音频&#xff0c;你需要使用uni.getBackgroundAudioMa…

小程序壁纸demo,数据采集第三方的,没有服务端

概述 小程序demo&#xff0c;共有三个页面&#xff0c;首页&#xff0c;详情&#xff0c;搜索&#xff0c;数据来源于第三方。有兴趣的可以看看&#xff0c;比较简单 详细 小程序demo&#xff0c;共有三个页面&#xff0c;首页&#xff0c;详情&#xff0c;搜索&#xff0c;…

2种方法,jmeter用一个正则提取器提取多个值!

jmeter中&#xff0c;用json提取器&#xff0c;一次提取多个值&#xff0c;这个很多人都会。但是&#xff0c;用正则提取器一次提取多个&#xff0c;是否可以呢&#xff1f; 肯定&#xff0c;很多人都自信满满的说&#xff0c;可以&#xff01;形如&#xff1a;token":“…

STM32单片机入门学习(一)

一、购入硬件装备 心血来潮&#xff0c;想学STM32&#xff0c;话不多说&#xff0c;先把东西买了STM32F103C8T6开发板ST-LINK下载器&#xff0c;小元器件自备。 二、安装软件装备 1.Keil uVision5安装 其他都是下一步。 2.用注册机给 Keil 5 注册 打开keil 5&#xff0c;打…

【C++】unordered_map与unorder_set的封装(哈希桶)

文章目录 前言一、模板参数的改造二、模板的特例化操作三、仿函数的妙用四、unordered迭代器基本操作1.const迭代器注意&#xff1a;2.HashTable与HTIterator的冲突 五、迭代器的构造问题六、完整代码1.hash_bucket.h2.unordered_set.h3.unordered_map.h 前言 我们开辟一个指针…

340. 至多包含 K 个不同字符的最长子串

340. 至多包含 K 个不同字符的最长子串 vip

Michael.W基于Foundry精读Openzeppelin第36期——Ownable2Step.sol

Michael.W基于Foundry精读Openzeppelin第36期——Ownable2Step.sol 0. 版本0.1 Ownable2Step.sol 1. 目标合约2. 代码精读2.1 pendingOwner() && transferOwnership(address newOwner) && _transferOwnership(address newOwner)2.2 acceptOwnership() 0. 版本 …

YOLOv8快速复现 训练 SCB-Dataset3-S 官网版本 ultralytics

目录 0 相关资料SCB-Dataset3-S 数据训练yaml文件 YOLOv8 训练SCB-Dataset3-S相关参数 0 相关资料 YOLOV8环境安装教程.&#xff1a;https://www.bilibili.com/video/BV1dG4y1c7dH/ YOLOV8保姆级教学视频:https://www.bilibili.com/video/BV1qd4y1L7aX/ b站视频&#xff1a;…

第一百五十回 自定义组件综合示例:游戏摇杆

文章目录 概念介绍实现方法示例代码我们在上一章回中介绍了自定义组件相关的内容,本章回中将综合使用这些内容 自定义游戏摇杆组件.闲话休提,让我们一起Talk Flutter吧。 概念介绍 我们介绍的游戏摇杆就是一个内层的小圆嵌套一个外层的大圆,大圆的位置不变,小圆只能在大圆…

【AD9361】设置带宽

接收链路滤波器 RX TIA LPF&#xff1a;RX TIA LPF 是一款单极点低通滤波器&#xff0c;具有可编程 3dB 转角频率。转折频率可在 1 MHz 至 70 MHz 范围内进行编程。RX TIA LPF 通常校准为基带通道带宽的 2.5 倍。 RX BB LPF&#xff1a;RX BB LPF 是具有可编程 3dB 转角频率的…

2、Window上的 虚拟机端口 暴露到 宿主机局域网教程

今天在公司的服务器主机上捣鼓虚拟机&#xff0c;要在虚拟机上安装一个oracle&#xff0c;虚拟机和主机能互相ping通的前提下&#xff0c;要将虚拟机上的端口号暴露在主机上&#xff0c;让项目组内的所有员工的电脑都能访问到该oracle数据库。 也就是电脑A 访问主机&#xff0…

Linux -- 使用多张gpu卡进行深度学习任务(以tensorflow为例)

在linux系统上进行多gpu卡的深度学习任务 确保已安装最新的 TensorFlow GPU 版本。 import tensorflow as tf print("Num GPUs Available: ", len(tf.config.list_physical_devices(GPU)))1、确保你已经正确安装了tensorflow和相关的GPU驱动&#xff0c;这里可以通…

Scala 高阶:Scala中的模式匹配

一、概述 Scala中的模式匹配&#xff08;case&#xff09;类似于Java中的switch...case&#xff0c;但是Scala的模式匹配功能更为强大。通过模式匹配&#xff0c;可以匹配更复杂的条件和数据结构&#xff0c;包括常量、类型、集合、元组等。而 Java 的 switch 语句只能用于匹配…

字符串函数----篇章(1)

目录 补上章缺失的两道题 七.笔试题&#xff08;7&#xff09; 八.笔试题&#xff08;8&#xff09; 一.字符串函数 ( 1 )----strlen函数 二.字符串函数 ( 2 )----strcpy函数 2-1模拟实现strcpy 三.字符串函数 ( 3 )----strcmp函数 ​编辑 3-1模拟实现strcmp 四.字符串函…