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

AOP应用之系统操作日志

本文演示下如何使用AOP,去实现系统操作日志功能。

实现步骤

  1. 引入AOP包
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId><version>2.6.6</version></dependency>
  1. 定义数据模型
package com.angel.ocean.domain.entity;import lombok.Data;
import java.util.Date;@Data
public class Syslog {/*** 主键**/private Long id;/*** ip 地址**/private String ip;/*** 类名**/private String className;/*** 方法名称**/private String methodName;/*** 传参**/private String params;/*** 执行结果, true-成功,false-失败**/private boolean status;/*** 响应信息**/private String response;/*** 业务类型**/private String remark;/*** 触发时间**/private Date createTime;/*** 操作用户**/private String createBy;
}
  1. 定义系统日志注解SyslogAnno
package com.angel.ocean.annotation;import java.lang.annotation.*;/*** 定义系统日志注解*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SyslogAnno {String value() default "";}
  1. 定义切面SyslogAspect
package com.angel.ocean.aspect;import com.alibaba.fastjson2.JSON;
import com.angel.ocean.annotation.SyslogAnno;
import com.angel.ocean.domain.entity.Syslog;
import com.angel.ocean.runner.SyslogHandlerTask;
import com.angel.ocean.util.LogDataUtil;
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 java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;/**1. 日志切面*/
@Slf4j
@Aspect
@Component
public class SyslogAspect {@Pointcut("@annotation(com.angel.ocean.annotation.SyslogAnno)")public void logPointCut() {}@AfterReturning(value = "logPointCut()", returning = "result")public void normalLog(JoinPoint point, Object result) {try {Syslog syslog = getSysLog(point);syslog.setStatus(true);syslog.setResponse(JSON.toJSONString(result));SyslogHandlerTask.LOG_QUEUE.offer(syslog);} catch (Exception e) {log.error("SyslogAspect.normalLog() error. ", e);}}@AfterThrowing(value = "logPointCut()", throwing = "throwable")public void exceptionLog(JoinPoint point, Throwable throwable) {try {Syslog syslog = getSysLog(point);syslog.setStatus(false);syslog.setResponse(throwable.getMessage());SyslogHandlerTask.LOG_QUEUE.offer(syslog);} catch (Exception e) {log.error("SyslogAspect.exceptionLog() error. ", e);}}private Syslog getSysLog(JoinPoint joinPoint) {Syslog sysLog = new Syslog();MethodSignature signature = (MethodSignature) joinPoint.getSignature();Method method = signature.getMethod();SyslogAnno sysLogAnno = method.getAnnotation(SyslogAnno.class);if (sysLogAnno != null) {sysLog.setRemark(sysLogAnno.value());}// 请求的 类名、方法名String className = joinPoint.getTarget().getClass().getName();String methodName = signature.getName();sysLog.setClassName(className);sysLog.setMethodName(methodName);// 请求的参数Object[] args = joinPoint.getArgs();try {List<String> list = new ArrayList<>();for (Object o : args) {list.add(JSON.toJSONString(o));}sysLog.setParams(list.toString());} catch (Exception e) {log.error("SyslogAspect.saveLog() error.", e);}sysLog.setIp(LogDataUtil.getIP());sysLog.setCreateBy(LogDataUtil.getUserId());sysLog.setCreateTime(new Date());return sysLog;}
}

工具类

package com.angel.ocean.util;import lombok.extern.slf4j.Slf4j;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;@Slf4j
public class LogDataUtil {private LogDataUtil() {}/***  获取用户IP地址*/public static String getIP() {String ip = "";try {HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();ip = request.getRemoteAddr();} catch (Exception e) {log.error("GetIPException", e);}return ip;}/*** 获取用户ID*/public static String getUserId() {String userId = "";try {HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();userId = request.getHeader("userId");} catch (Exception e) {log.error("GetUserIdException", e);}return userId;}
}
  1. 定义日志数据处理SyslogHandlerTask
package com.angel.ocean.runner;import cn.hutool.core.collection.CollUtil;
import com.angel.ocean.domain.entity.Syslog;
import com.angel.ocean.service.SyslogService;
import com.google.common.collect.Queues;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;@Slf4j
@Component
public class SyslogHandlerTask implements CommandLineRunner {@Resourceprivate SyslogService syslogService;/*** 操作日志队列*/public static final BlockingQueue<Syslog> LOG_QUEUE = new LinkedBlockingQueue<>();@Overridepublic void run(String... strings) throws Exception {new Thread(() -> {List<Syslog> SyslogList = new ArrayList<>();while (true) {try {Queues.drain(LOG_QUEUE, SyslogList, 100, 500, TimeUnit.MILLISECONDS);if (CollUtil.isNotEmpty(SyslogList)) {syslogService.batchInsert(SyslogList);SyslogList.clear();} else {Thread.sleep(500);}} catch (Exception e) {log.error("SyslogHandlerTask error={}", e.getMessage(), e);}}}, "Syslog_Props_Mysql").start();}
}
  1. 打包成系统操作日志SDK (ocean-log)

如何使用

继承系统操作日志SDK

<dependency><groupId>com.angel.ocean</groupId><artifactId>ocean-log</artifactId><version>1.0.0</version>
</dependency>

在Api的添加/修改/删除等方法上,添加SyslogAnno注解

@ApiModelProperty(value = "保存角色信息表")
@PostMapping("save")
@SyslogAnno("添加角色")
public ApiResult<?> save(@RequestBody SysRoleDTO dto) {service.save(dto);return ApiResult.success();
}

实例验证

接口调用
在这里插入图片描述系统操作日志数据
在这里插入图片描述

相关文章:

AOP应用之系统操作日志

本文演示下如何使用AOP&#xff0c;去实现系统操作日志功能。 实现步骤 引入AOP包 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId><version>2.6.6</version></de…...

海外云手机自动化管理,高效省力解决方案

不论是企业还是个人&#xff0c;对于海外社媒的营销都是需要自动化管理的&#xff0c;因为自动化管理不仅省时省力&#xff0c;而且还节约成本&#xff1b; 海外云手机的自动化管理意味着什么&#xff1f;那就是企业无需再投入大量的人力和时间去逐一操作和监控每一台设备。 通…...

后仿真中的 《specify/endspecify block》之(5)使用specify进行时序仿真

前面我们学习了specify...endspecify 具体是什么东西。今天,我们使用specify block 中定义的延时,来进行一次仿真。看看到底是背后如何运转的呢。 一 基本例子 一个用 specify 指定延迟的与门逻辑描述如下: module and_gate(output Z,input A, B);assign Z = A & …...

win10/11磁盘管理

win10/11磁盘管理 合并磁盘分区的前提是你的两个磁盘区域是相邻的&#xff0c;比如如下&#xff1a; 如果需要吧这个磁盘进行分解&#xff0c;你可以选择压缩一部分磁盘或者是直接删除卷 我这里的话&#xff0c;因为压缩出来的卷和C盘好像是不相邻的&#xff08;我之前做过&…...

【昇思初学入门】第四天打卡

数据变换Transforms 心得体会 MindSpore提供了丰富的数据变换工具&#xff0c;针对图像数据可以使用如Rescale、Normalize和HWC2CHW等&#xff0c;且使用Compose类允许我们定义一个变换序列&#xff0c;并将它们作为一个整体应用到数据上。 composed transforms.Compose([v…...

禁用/屏蔽 Chrome 默认快捷键

Chrome 有一些内置的快捷键&#xff0c;但是它并没有像其他软件一样提供管理快捷键的界面。在某些时候&#xff0c;当我们因为个人需求希望禁用 Chrome 某些快捷键时&#xff0c;又无从下手。 好在有开发者开发了 Chrome 插件&#xff0c;可以禁用 Chrome 快捷键的插件&#x…...

移动端+PC端应用模式的智慧城管综合执法办案平台源码,案件在线办理、当事人信用管理、文书电子送达、沿街店铺分析

城市管理综合执法管理平台实现执法办案、业务全流程在线办理&#xff0c;依托移动端PC端的“两端”应用模式&#xff0c;保障能够通过信息化手段进行日常的执法办案工作&#xff0c;强化执法监督功能。提供了案件在线办理、当事人信用管理、文书电子送达、沿街店铺分析等功能&a…...

AI音乐大模型时代:版权归属与创意产业的新生长点

AI在创造还是毁掉音乐&#xff1f; 简介&#xff1a;最近一个月&#xff0c;轮番上线的音乐大模型&#xff0c;一举将素人生产音乐的门槛降到了最低&#xff0c;并掀起了音乐圈会不会被AI彻底颠覆的讨论。短暂的兴奋后&#xff0c;AI产品的版权归属于谁&#xff0c;创意产业要…...

C++函数作为参数

C++函数作为参数 在C++中,函数作为另一个函数的参数是非常常见的做法,特别是在处理回调函数和泛型编程时。我们展示了如何在C++中将函数作为参数传递给另一个函数,包括普通函数、std::function 和 std::bind、lambda表达式以及类成员函数。每种方法都有其独特的优势,可以根…...

考前刷题练手感(北航期末往年数据结构编程题)

本次因为是考前一天极速刷题&#xff0c;所以没有讲解&#xff0c;若有问题可私信。 目录 一、 查找同时空人员二、 老鼠回家-无回路三、函数调⽤关系四、东二食堂模拟五、栈帧 一、 查找同时空人员 【问题描述】 假设一共有6个手机基站&#xff0c;都具有记录手机连接基站状…...

Android记录9--实现转盘效果

自定义View /2013.10.16_TurnPlate_Demo/src/com/wwj/turnplate/TurnPlateView.java package com.wwj.turnplate; import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; im…...

【Oracle APEX开发小技巧1】转换类型实现显示小数点前的 0 以 及常见类型转换

在 apex 交互式式网格中&#xff0c;有一数值类型为 NUMBER&#xff0c;保留小数点后两位的项&#xff0c;在 展示时小数点前的 0 不显示。 效果如下&#xff1a; 转换前&#xff1a; m.WEIGHT_COEFFICIENT 解决方案&#xff1a; 将 NUMBER&#xff08;20&#xff0c;2&#xf…...

GRIT论文阅读笔记

一篇试图统一生成任务和编码任务的工作&#xff0c;就是把只能完成生成任务的GPT改成既能生成又能encode。思路其实很简单&#xff0c;就是在输入的时候添加instruction tokens来指引模型做representation还是generation&#xff0c;然后各自算损失。representation任务用的是d…...

1980python个性化电影推荐管理系统mysql数据库Django结构layUI布局elasticsearch存储计算机软件工程网页

一、源码特点 python Django个性化电影推荐管理系统是一套完善的web设计系统mysql数据库 利用elasticsearch存储浏览数据 &#xff0c;对理解python编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。 开发环境pycharm…...

基于IDEA的Maven(依赖介绍和引用)

如何通过一个坐标信息&#xff08;依赖&#xff09;去引用 &#xff0c;某个"jar 包" 会在这篇博客进行学习。 目录 一、学习开始 &#xff08;0&#xff09;项目的结构组成和 "pom.xml" 文件内容。 &#xff08;1&#xff09;首先需要一个标签&#xf…...

pytest测试框架pytest-sugar插件生成进度条

Pytest提供了丰富的插件来扩展其功能&#xff0c;介绍下插件pytest-sugar&#xff0c;可以帮助我们在控制台中显示彩色的测试结果和进度条&#xff0c;提供失败的堆栈回溯信息。 为了使用 pytest-sugar&#xff0c;需要满足以下条件&#xff1a; Python 3.8 或更高版本pytest…...

若依框架集成微信支付

1. 添加微信支付相关依赖 <!-- 微信支付 --> <dependency><groupId>com.github.wxpay</groupId><artifactId>wxpay-sdk</artifactId><version>0.0.3</version> </dependency> <dependency><groupId>com.gi…...

IOS开发学习日记(十七)

简单的第三方登录和分享功能 第三方登录系统 URL Scheme&#xff1a;App间的跳转及通信 App间跳转场景 登陆系统&#xff1a; 跨平台&#xff0c;跨App 标记用户&#xff0c;个性化的推送 使用第三方登录&#xff08;减少注册成本 / 无须维护敏感信息&#xff09; 微信 / Q…...

【ARMv8/ARMv9 硬件加速系列 2 -- ARM NEON 加速运算介绍】

文章目录 ARM NEONNEON 向量寄存器NEON 寄存器使用方式NEON 寄存器的视图NEON 寄存器别名NEON 寄存器的用途ARM NEON 在ARMv8架构中,引入了一组新的寄存器,称为向量寄存器(Vector Registers),用于支持高效的向量和浮点计算。这些寄存器是SIMD(Single Instruction, Multi…...

LayoutSystem布局系统

简介: LayoutSystem,是UGUI中由CanvasUpdateSystem发起(m_LayoutRebuildQueue中大部分都是LayoutRebuilder)的关于布局排列的处理系统。 类图: 布局过程 核心代码讲解: LayoutRebuilder...

在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:

在 HarmonyOS 应用开发中&#xff0c;手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力&#xff0c;既支持点击、长按、拖拽等基础单一手势的精细控制&#xff0c;也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档&#xff0c…...

linux arm系统烧录

1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 &#xff08;忘了有没有这步了 估计有&#xff09; 刷机程序 和 镜像 就不提供了。要刷的时…...

Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器

第一章 引言&#xff1a;语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域&#xff0c;文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量&#xff0c;支撑着搜索引擎、推荐系统、…...

spring:实例工厂方法获取bean

spring处理使用静态工厂方法获取bean实例&#xff0c;也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下&#xff1a; 定义实例工厂类&#xff08;Java代码&#xff09;&#xff0c;定义实例工厂&#xff08;xml&#xff09;&#xff0c;定义调用实例工厂&#xff…...

Nginx server_name 配置说明

Nginx 是一个高性能的反向代理和负载均衡服务器&#xff0c;其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机&#xff08;Virtual Host&#xff09;。 1. 简介 Nginx 使用 server_name 指令来确定…...

Robots.txt 文件

什么是robots.txt&#xff1f; robots.txt 是一个位于网站根目录下的文本文件&#xff08;如&#xff1a;https://example.com/robots.txt&#xff09;&#xff0c;它用于指导网络爬虫&#xff08;如搜索引擎的蜘蛛程序&#xff09;如何抓取该网站的内容。这个文件遵循 Robots…...

css的定位(position)详解:相对定位 绝对定位 固定定位

在 CSS 中&#xff0c;元素的定位通过 position 属性控制&#xff0c;共有 5 种定位模式&#xff1a;static&#xff08;静态定位&#xff09;、relative&#xff08;相对定位&#xff09;、absolute&#xff08;绝对定位&#xff09;、fixed&#xff08;固定定位&#xff09;和…...

Linux-07 ubuntu 的 chrome 启动不了

文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了&#xff0c;报错如下四、启动不了&#xff0c;解决如下 总结 问题原因 在应用中可以看到chrome&#xff0c;但是打不开(说明&#xff1a;原来的ubuntu系统出问题了&#xff0c;这个是备用的硬盘&a…...

k8s业务程序联调工具-KtConnect

概述 原理 工具作用是建立了一个从本地到集群的单向VPN&#xff0c;根据VPN原理&#xff0c;打通两个内网必然需要借助一个公共中继节点&#xff0c;ktconnect工具巧妙的利用k8s原生的portforward能力&#xff0c;简化了建立连接的过程&#xff0c;apiserver间接起到了中继节…...

根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:

根据万维钢精英日课6的内容&#xff0c;使用AI&#xff08;2025&#xff09;可以参考以下方法&#xff1a; 四个洞见 模型已经比人聪明&#xff1a;以ChatGPT o3为代表的AI非常强大&#xff0c;能运用高级理论解释道理、引用最新学术论文&#xff0c;生成对顶尖科学家都有用的…...