【Spring】自定义注解 + AOP 记录用户的使用日志

目录

​编辑

自定义注解 + AOP 记录用户的使用日志

使用背景

落地实践

一:自定义注解

二:切面配置

三:Api层使用

使用效果


自定义注解 + AOP 记录用户的使用日志

使用背景

(1)在学校项目中,安防平台实际的使用人员大多都是外聘人员,用户的一些关键操作最好记录清楚,像是青岛工程职业学院网络及监控系统项目中,有个功能是对全校学生权限的一键冻结和解冻。

(2)对接非常强势的第三方数据时,例如腾讯的腾讯微卡产品,虽然是他们将数据接入到海康平台,但仍然不接受定制,我们必须按照腾讯的接口协议,提供给他们接口。注意:此时没有办法走OpenApi,而请假数据是每天有推送的,为了一旦出现问题可回溯,需要记录完整的数据日志。

落地实践

一:自定义注解

配置自定义注解“LogPoint”,之后会用在关键的接口上,作为切入点来记录该接口的访问信息。


@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Documented
public @interface LogPoint {
    /***
    * @Description 日志描述
    * @return java.lang.String
    */
    String description() default "";
}

 

二:切面配置

1.在切面里,我们可以配置请求参数的详细信息逐条打印,和响应结果与它的耗时记录,这些打印信息足以应对现场的大多数问题。

2.不用担心info日志打印过多的问题,只需要把注解标注在关键的接口,与多占的那些硬盘空间相比,这些信息能帮助技术和研发节省更多的时间,更具性价比。

    
    /**
     * @ClassName AspectLogConfig
     * @Description 出入参日志配置类
     * @Version 1.0
     **/
    @Aspect
    @Component
    @Slf4j
    public class LogConfig {
        private final static Logger logger = LoggerFactory.getLogger(LogConfig.class);
    
        @Pointcut("@annotation(com.hikvision.pea.common.annotation.LogPoint)")
        public void logPoint() {
        }
    
        /***
         * @Description 切入点之前织入
         * @Param []
         * @return void
         */
        @Before("logPoint()")
        public void doBefore(JoinPoint joinPoint) throws Throwable {
            //开始打印请求日志
            ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = requestAttributes.getRequest();
    
            //打印请求相关参数
            logger.info("================== start ==================");
    
            //打印请求 url
            logger.info("URL              : {}", request.getRequestURL().toString());
            //打印描述信息
    
            //打印HTTP method
            logger.info("HTTP Method      : {}", request.getMethod());
            //打印调用 controller 的全路径以及执行方法
            logger.info("Class Method     : {}.{}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());
            //打印请求的ip
            logger.info("IP               : {}", request.getRemoteAddr());
            //打印请求入参
            logger.info("Request Args     : {}", joinPoint.getArgs());
        }
    
        @After("logPoint()")
        public void doAfter() throws Throwable {
    
        }
    
        /***
         * @Description 环绕
         * @Date 14:35 2022/6/23
         * @Param [proceedingJoinPoint]
         * @return java.lang.Object
         */
        @Around("logPoint()")
        public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
            long startTime = System.currentTimeMillis();
            //执行切点
            Object result = proceedingJoinPoint.proceed();
            logger.info("打印出参 : {}", result);
            logger.info("执行耗时 : {} ms", System.currentTimeMillis() - startTime);
            logger.info("================== end ===================" + System.lineSeparator());
            return result;
        }
    }

 

三:Api层使用

只需要将注解加在对应的接口上,无需其它编码。

/**
 * @ClassName ResourceController
 * @Description 门禁点控制器
 * @Version 1.0
 **/

@Api(tags = "门禁点控制器")
@RestController
@RequestMapping("/resource")
@Slf4j
public class ResourceController {
    @Autowired
    IResourceService iResourceService;

    @ApiOperation("获取门禁点资源")
    @PostMapping("/doorSources")
    @LogPoint(description = "获取门禁点资源")
    public ResponseData getDoorSources(@ApiParam("入参") @RequestBody ResourceReqVo resourceReqVo) {
        Page<Resource> resources = iResourceService.getResources(resourceReqVo);
        return ResponseData.success(resources);
    }
}

 

使用效果

将调用方的请求参数、IP、响应结果、耗时,都完整的打印出来,一旦出现外聘人员误操作或者三方数据不匹配,通过这些信息,定位起问题来都非常方便。

在这里插入图片描述

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

FastAdmin西陆房产系统(xiluHouse)全开源

应用介绍 一款基于FastAdminThinkPHPUniapp开发的西陆房产管理系统&#xff0c;支持小程序、H5、APP&#xff1b;包含房客、房东(高级授权)、经纪人(高级授权)三种身份。核心功能有&#xff1a;新盘销售、房屋租赁、地图找房、房源代理(高级授权)、在线签约(高级授权)、电子合同…

C#实现坐标系转换

已知坐标系的向量线段AB&#xff0c;旋转指定角度后平移到达坐标AB 获取旋转角度以及新的其他坐标转换。 新建窗体应用程序CoordinateTransDemo&#xff0c;将默认的Form1重命名为FormCoordinateTrans&#xff0c;窗体设计如图&#xff1a; 窗体设计代码如下&#xff1a; 部分…

Redis-缓存问题及解决方案

本文已收录于专栏 《中间件合集》 目录 概念说明缓存问题缓存击穿问题描述解决方案 缓存穿透问题描述解决方案 缓存雪崩问题描述解决方案提高缓存可用性过期时间配置熔断降级 总结提升 概念说明 Redis是一个开源的内存数据库&#xff0c;也可以用作缓存系统。它支持多种数据结构…

前端小案例——动态导航栏文字(HTML + CSS, 附源码)

一、前言 实现功能: 这案例是一个具有动态效果的导航栏。导航栏的样式设置了一个灰色的背景&#xff0c;并使用flex布局在水平方向上平均分配了四个选项。每个选项都是一个li元素&#xff0c;包含一个文本和一个横向的下划线。 当鼠标悬停在选项上时&#xff0c;选项的文本颜色…

华为自动驾驶干不过特斯拉?

文 | AUTO芯球 作者 | 李诞 什么&#xff1f; 华为的智能驾驶方案干不过蔚小理&#xff1f; 特斯拉的智能驾驶[FSD]要甩中国车企几条街&#xff1f; 这华为问界阿维塔刚刚推送“全国都能开”的城区“无图 NCA” 就有黑子来喷了 这是跪久了站不起来了吧 作为玩车14年&…

get通过发送Body传参-工具类

1、调用方式 String url "http://ip/xxx/zh/xxxxx/xxxx/userCode"; //进行url中的对应的参数 url2 url2.replace("ip",bancirili); url2 url2.replace("zh",zh); url2 url2.replace("userCode",userCode);String dateTime xxxx; //组…

04. 【Linux教程】安装 Linux 操作系统

通过前面的小节学习&#xff0c;我们已经对 Linux 操作系统有了简单的了解&#xff0c;同时也在 Windows 下安装了虚拟机软件 VMware &#xff0c;那么本节课我们就介绍下如何使用虚拟机软件安装 Linux 操作系统。 通过第一小节的学习我们知道 Linux 有很多的发行版本&#xf…

Vscode配置STM32开发环境(联合Keil MDK/IAR开发)

Vscode配置STM32开发环境&#xff08;替代Keil MDK/IAR&#xff09; 前言 使用了很长时间的Keil5 MDK&#xff0c;以及最近用了一段时间的IAR for ARM&#xff0c;总体来说体验都不是特别的好&#xff0c;Keil功能还行&#xff0c;也不卡顿&#xff0c;就是开发效率、界面样式…

1-2 动手学深度学习v2-基础优化方法-笔记

最常见的算法——梯度下降 当一个模型没有显示解的时候&#xff0c;该怎么办呢&#xff1f; 首先挑选一个参数的随机初始值&#xff0c;可以随便在什么地方都没关系&#xff0c;然后记为 w 0 \pmb{w_{0}} w0​在接下来的时刻里面&#xff0c;我们不断的去更新 w 0 \pmb{w_{0}…

asp.net core 依赖注入 实例化对象实例

在面向对象编程中&#xff0c;推荐使用面向接口编程&#xff0c;这样我们的代码就依赖于服务接口&#xff0c;而不是依赖于实现类&#xff0c;可以实现代码解耦。 名称解释&#xff1a; 我们把负责提供对象的注册和 获取功能的框架叫作“容器”&#xff0c; 注册到容器中的对象…

Android BitmapShader setLocalMatrix缩放Bitmap高度重新onMeasure,Kotlin

Android BitmapShader setLocalMatrix缩放Bitmap高度重新onMeasure&#xff0c;Kotlin <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:tools"http://sc…

macbook死机了按什么键重启?CleanMyMac怎么清理MacBook

当您的macbook出现死机情况&#xff0c;您可以尝试以下几种方法来重启&#xff1a; 强制重启&#xff1a; 如果只是某个应用程序卡住&#xff0c;可以使用Command Option Esc组合键强制退出该应用。对于持续性的卡顿或死机&#xff0c;可以通过点击菜单栏上的苹果图标&#…

2024清洁能源、环境与智慧城市国际研讨会(ISCEESC2024)

2024清洁能源、环境与智慧城市国际研讨会(ISCEESC2024) 会议简介 2024年清洁能源、环境与智慧城市国际研讨会&#xff08;ISCEESC2024&#xff09;将在中国丽江举行。本次会议主要围绕清洁能源、环境和智慧城市等研究领域&#xff0c;旨在为该研究领域的专家学者提供一个国际…

【SpringBoot】RBAC权限控制

&#x1f4dd;个页人主&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;SpringBoot⛺️稳重求进&#xff0c;晒太阳 权限系统与RBAC模型 权限 为了解决用户和资源的操作关系&#xff0c; 让指定的用户&#xff0c;只能操作指定的资源。 权限功能 菜单权限&a…

蓝桥杯Web应用开发-CSS 基础语法3(文本属性)

CSS 基础语法-文本属性 专栏持续更新中 文本属性 文本属性用于定义文本的样式&#xff0c;通过文本属性&#xff0c;可以改变文本的颜色、字间距、对齐方式、文本修饰和文本缩进等。常用文本属性如下表所示&#xff1a; 属 性可取值描述line-heightnormal、number、length、…

数字孪生网络攻防模拟与城市安全演练

在数字化浪潮的推动下&#xff0c;网络攻防模拟和城市安全演练成为维护社会稳定的不可或缺的环节。基于数字孪生技术我们能够在虚拟环境中进行高度真实的网络攻防模拟&#xff0c;为安全专业人员提供实战经验&#xff0c;从而提升应对网络威胁的能力。同时&#xff0c;在城市安…

Python基础学习-08 列表

Python 编程语言中有四种集合数据类型&#xff1a; 列表&#xff08;List&#xff09;是一种有序和可更改的集合。允许重复的成员。 选择集合类型时&#xff0c;了解该类型的属性很有用。 为特定数据集选择正确的类型可能意味着保留含义&#xff0c;并且可能意味着提高效率或…

ES6-对象的解构赋值

一、区别一下数组的解构赋值 - 对象的解构与数组有一个重要的不同。数组的元素是按次序排列的&#xff0c;变量的取值由它的位置决定&#xff1b;而对象的属性没有次序&#xff0c;变量必须与属性同名&#xff0c;才能取到正确的值二、说明 - 对象的解构赋值的内部机制&#…

STM32学习笔记三——深度讲解GPIO及其应用

目录 STM32GPIO端口位基本结构图&#xff1a; 结构图I/O引脚&#xff1a; GPIO输入输出总结 1.GPIO引脚的四种输入方式及其特点&#xff1a; 1)上拉输入(GPIO_Mode_IPU) 2)下拉输入(GPIO_Mode_IPD) 3)模拟输入(GPIO_Mode_AIN) 4)浮空输入(GPIO_Mode_IN_FLOATING…

信创ARM架构QT应用开发环境搭建

信创ARM架构QT应用开发环境搭建 前言交叉工具链Ubuntu上安装 32 位 ARM 交叉工具链Ubuntu上安装 64 位 ARM 交叉工具链 交叉编译 QT 库下载 QT 源码交叉编译 QT 源码 Qt Creator交叉编译配置配置 Qt Creator Kits创建一个测试项目 前言 有没有碰到过这种情况&#xff1f;开发出…