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...
滚球游戏笔记
1、准备工作 (1) 创建地面:3D Object-Plane,命名为Ground (2) 创建小球:3D Object-sphere,命名为Player,PositionY 0.5。添加Rigidbody组件 (3) 创建文件夹:Create-Foder,分别命名为Material…...
Mysql8死锁排查
Mysql8死锁排查 Mysql8 查询死锁的表 -- 查询死锁表select * from performance_schema.data_locks;-- 查询死锁等待时间select * from performance_schema.data_lock_waits;Mysql8之前的版本 查询死锁的表 -- 查询死锁表SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS;-- 查询…...
程序猿成长之路之数据挖掘篇——决策树分类算法(1)——信息熵和信息增益
决策树不仅在人工智能领域发挥着他的作用,而且在数据挖掘中也在分类领域中独占鳌头。了解决策树的思想是学习数据挖掘中的分类算法的关键,也是学习分类算法的基础。 什么是决策树 用术语来说,决策树(Decision Tree)是…...
数据通信与网络(五)
交换机功能: 地址学习(端口/MAC地址映射表) 通信过滤(基于端口/MAC地址映射表) 生成树协议(断开环路) 隔离冲突域 生成树协议 隔离冲突域 交换机配置模式(用不同级别的命令对交换机进行配置) 普…...
数据中心容灾考题
abc cd abc c为啥...
win10远程桌面连接端口,远Win10远程桌面连接端口修改及无法连接解决方案
一、Win10远程桌面连接端口概述 Win10远程桌面连接功能允许用户从远程位置访问和控制另一台计算机。远程桌面连接默认使用TCP 3389端口,但出于安全或其他需求,用户可能希望修改此端口。 二、Win10远程桌面连接端口修改方法 要修改Win10远程桌面连接的…...
基于AT89C52单片机的温度报警系统
点击链接获取Keil源码与Project Backups仿真图: https://download.csdn.net/download/qq_64505944/89456321?spm=1001.2014.3001.5503 仿真构造:AT89C52+DS18B20温度模块+三按键+蜂鸣器+四位数码管显示+电源模块。 压缩包构造:源码+仿真图+设计文档+原理图+开题文档+元件…...
[保姆级教程]uniapp配置vueX
文章目录 注意新建文件简单的使用 注意 uniapp是支持vueX的只需配置一下就好 新建文件 在src文件中,新建一个store(如果有的话跳过) 在store中新建一个js文件,修改js文件名称和选择模板为default 在 uni-app 项目根目录下&…...
第二次IAG
IAG in NanJing City 我与南京奥体的初次相遇,也可能是最后一次! 对我来说,IAG 演唱会圆满结束啦! 做了两场充满爱[em]e400624[/em]的美梦 3.30号合肥站,6.21号南京站[em]e400947[/em] 其实,没想到昨天回去看呀!(lack of money […...
智慧校园综合管理系统的优点有哪些
在当今这个信息化飞速发展的时代,智慧校园综合管理系统正逐步成为教育领域的一股革新力量,它悄然改变着我们对传统校园管理的认知。这套系统如同一个无形的桥梁,将先进的信息技术与学校的日常运作紧密相连,展现出多维度的优势。 …...
引擎网站推广法怎么做/网站推广和优化的原因网络营销
使用Git Gui的查看中文代码的时候,会出现乱码,如下: 解决方法: 1、在乱码的区域点击鼠标右键,选择Encoding,然后选择Unicode(UTF-8) 2、最终乱码问题解决,如下图&#x…...
长沙网站设计我选刻/seo推广软件
区块链作为一个正在发展的崭新技术,对于大多数而言都是一个陌生的词汇,那么就会产生大多数人都不够信任这一现象的结果。对此,区块链领域的专家徐明星表示:区块链实现的是“基于代码的信任”。 区块链究竟是什么,似乎没…...
高端品牌网站建设专人一对一服务/google关键词指数
标签(空格分隔): QCon 10.17-10.19在上海度过了Qcon的三天。今年的Qcon主题非常的散,这也是近两年无论ArchSummit还是QCon的一个特点,基本涵盖了以互联网技术为主的所有领域。 我个人主要关注还是云计算、机器学习和大…...
可以做婚礼视频的网站有哪些/stp营销战略
是的,有很多关于 Kalman 滤波、插值法和折线算法的例子和开源库。 Kalman 滤波: 一个简单的例子: https://github.com/rlabbe/Kalman-and-Bayesian-Filters-in-Python scikit-learn 库中的 Kalman 滤波实现: https://github.com/scikit-lear…...
建设一个企业网站/津seo快速排名
如果高性能布局的? 通过多次避免多次测量布局子级可实现高性能,如果需要多次进行测量,即固有特性测量 package com.anguomob.jecpack.activity.composeComposable fun PhotographerCard(modifier: Modifier Modifier) {Row(modifier modif…...