AOP应用之系统操作日志
本文演示下如何使用AOP,去实现系统操作日志功能。
实现步骤
- 引入AOP包
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId><version>2.6.6</version></dependency>
- 定义数据模型
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;
}
- 定义系统日志注解SyslogAnno
package com.angel.ocean.annotation;import java.lang.annotation.*;/*** 定义系统日志注解*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SyslogAnno {String value() default "";}
- 定义切面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;}
}
- 定义日志数据处理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();}
}
- 打包成系统操作日志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,去实现系统操作日志功能。 实现步骤 引入AOP包 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId><version>2.6.6</version></de…...

海外云手机自动化管理,高效省力解决方案
不论是企业还是个人,对于海外社媒的营销都是需要自动化管理的,因为自动化管理不仅省时省力,而且还节约成本; 海外云手机的自动化管理意味着什么?那就是企业无需再投入大量的人力和时间去逐一操作和监控每一台设备。 通…...
后仿真中的 《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磁盘管理 合并磁盘分区的前提是你的两个磁盘区域是相邻的,比如如下: 如果需要吧这个磁盘进行分解,你可以选择压缩一部分磁盘或者是直接删除卷 我这里的话,因为压缩出来的卷和C盘好像是不相邻的(我之前做过&…...
【昇思初学入门】第四天打卡
数据变换Transforms 心得体会 MindSpore提供了丰富的数据变换工具,针对图像数据可以使用如Rescale、Normalize和HWC2CHW等,且使用Compose类允许我们定义一个变换序列,并将它们作为一个整体应用到数据上。 composed transforms.Compose([v…...

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

移动端+PC端应用模式的智慧城管综合执法办案平台源码,案件在线办理、当事人信用管理、文书电子送达、沿街店铺分析
城市管理综合执法管理平台实现执法办案、业务全流程在线办理,依托移动端PC端的“两端”应用模式,保障能够通过信息化手段进行日常的执法办案工作,强化执法监督功能。提供了案件在线办理、当事人信用管理、文书电子送达、沿街店铺分析等功能&a…...
AI音乐大模型时代:版权归属与创意产业的新生长点
AI在创造还是毁掉音乐? 简介:最近一个月,轮番上线的音乐大模型,一举将素人生产音乐的门槛降到了最低,并掀起了音乐圈会不会被AI彻底颠覆的讨论。短暂的兴奋后,AI产品的版权归属于谁,创意产业要…...
C++函数作为参数
C++函数作为参数 在C++中,函数作为另一个函数的参数是非常常见的做法,特别是在处理回调函数和泛型编程时。我们展示了如何在C++中将函数作为参数传递给另一个函数,包括普通函数、std::function 和 std::bind、lambda表达式以及类成员函数。每种方法都有其独特的优势,可以根…...

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

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 交互式式网格中,有一数值类型为 NUMBER,保留小数点后两位的项,在 展示时小数点前的 0 不显示。 效果如下: 转换前: m.WEIGHT_COEFFICIENT 解决方案: 将 NUMBER(20,2…...

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

1980python个性化电影推荐管理系统mysql数据库Django结构layUI布局elasticsearch存储计算机软件工程网页
一、源码特点 python Django个性化电影推荐管理系统是一套完善的web设计系统mysql数据库 利用elasticsearch存储浏览数据 ,对理解python编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。 开发环境pycharm…...

基于IDEA的Maven(依赖介绍和引用)
如何通过一个坐标信息(依赖)去引用 ,某个"jar 包" 会在这篇博客进行学习。 目录 一、学习开始 (0)项目的结构组成和 "pom.xml" 文件内容。 (1)首先需要一个标签…...

pytest测试框架pytest-sugar插件生成进度条
Pytest提供了丰富的插件来扩展其功能,介绍下插件pytest-sugar,可以帮助我们在控制台中显示彩色的测试结果和进度条,提供失败的堆栈回溯信息。 为了使用 pytest-sugar,需要满足以下条件: 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:App间的跳转及通信 App间跳转场景 登陆系统: 跨平台,跨App 标记用户,个性化的推送 使用第三方登录(减少注册成本 / 无须维护敏感信息) 微信 / 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...
基于算法竞赛的c++编程(28)结构体的进阶应用
结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...

iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版分享
平时用 iPhone 的时候,难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵,或者买了二手 iPhone 却被原来的 iCloud 账号锁住,这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...

Ascend NPU上适配Step-Audio模型
1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统,支持多语言对话(如 中文,英文,日语),语音情感(如 开心,悲伤)&#x…...

Map相关知识
数据结构 二叉树 二叉树,顾名思义,每个节点最多有两个“叉”,也就是两个子节点,分别是左子 节点和右子节点。不过,二叉树并不要求每个节点都有两个子节点,有的节点只 有左子节点,有的节点只有…...

有限自动机到正规文法转换器v1.0
1 项目简介 这是一个功能强大的有限自动机(Finite Automaton, FA)到正规文法(Regular Grammar)转换器,它配备了一个直观且完整的图形用户界面,使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...

HDFS分布式存储 zookeeper
hadoop介绍 狭义上hadoop是指apache的一款开源软件 用java语言实现开源框架,允许使用简单的变成模型跨计算机对大型集群进行分布式处理(1.海量的数据存储 2.海量数据的计算)Hadoop核心组件 hdfs(分布式文件存储系统)&a…...
在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案
这个问题我看其他博主也写了,要么要会员、要么写的乱七八糟。这里我整理一下,把问题说清楚并且给出代码,拿去用就行,照着葫芦画瓢。 问题 在继承QWebEngineView后,重写mousePressEvent或event函数无法捕获鼠标按下事…...
Caliper 配置文件解析:fisco-bcos.json
config.yaml 文件 config.yaml 是 Caliper 的主配置文件,通常包含以下内容: test:name: fisco-bcos-test # 测试名称description: Performance test of FISCO-BCOS # 测试描述workers:type: local # 工作进程类型number: 5 # 工作进程数量monitor:type: - docker- pro…...
FOPLP vs CoWoS
以下是 FOPLP(Fan-out panel-level packaging 扇出型面板级封装)与 CoWoS(Chip on Wafer on Substrate)两种先进封装技术的详细对比分析,涵盖技术原理、性能、成本、应用场景及市场趋势等维度: 一、技术原…...

基于stm32F10x 系列微控制器的智能电子琴(附完整项目源码、详细接线及讲解视频)
注:文章末尾网盘链接中自取成品使用演示视频、项目源码、项目文档 所用硬件:STM32F103C8T6、无源蜂鸣器、44矩阵键盘、flash存储模块、OLED显示屏、RGB三色灯、面包板、杜邦线、usb转ttl串口 stm32f103c8t6 面包板 …...