日常记录-springboot整合用户操作日志AOP

news/2025/2/12 5:00:08/

springboot整合日志AOP

  • 一、自定义操作日志注解类
  • 二、操作日志记录实现类
  • 三、操作日志注解放在你要切入的方法上

一、自定义操作日志注解类

import java.lang.annotation.*;@Target(ElementType.METHOD)//注解放置的目标位置即方法级别
@Retention(RetentionPolicy.RUNTIME)//注解在哪个阶段执行
@Documented
public @interface OperateLogAnnotation {String operateModel() default ""; // 操作模块,比如:用户模块 - 登录String operateType() default "";  // 操作类型 新增、删除等String remark() default "";  // 操作说明}

二、操作日志记录实现类

import com.xxx.OperateLogAnnotation;import lombok.extern.slf4j.Slf4j;import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.*;@Aspect
@Component
@Slf4j
public class OperationLogAspect {/*** @Pointcut 定义切点表达式* 设置操作日志切入点   在注解的位置切入代码*/@Pointcut("@annotation(com.xxx.OperateLogAnnotation)")public void operLogPoinCut() {//log.info("日志=========================切入点");}/*** @Before 前置通知* @param joinPoint 连接点:比如接口方法被调用的时候就是日志切面的连接点*/@Before(value = "operLogPoinCut()")public void before(JoinPoint joinPoint) {//log.info("日志--------在方法执行前(紧邻切入点)执行");}/*** @Around 环绕通知:通知包裹了目标方法,在目标方法调用之前和之后执行自定义的行为* @param joinPoint* @return* @throws Throwable*/@Around(value = "operLogPoinCut()")public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {//log.info("日志--------方法执行前后都有通知,通知在方法前还是后取决于其中的 ProceedingJoinPoint.proceed() 的位置;");long startTime = System.currentTimeMillis();//获取当前请求对象ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletRequest request = attributes.getRequest();//记录请求信息Object[] objs = joinPoint.getArgs();Object result = joinPoint.proceed();//返回的结果,这是一个进入方法和退出方法的一个分界Signature signature = joinPoint.getSignature();// 从切面织入点处通过反射机制获取织入点处的方法MethodSignature methodSignature = (MethodSignature) signature;//获取切入点所在的方法Method method = methodSignature.getMethod();long endTime = System.currentTimeMillis();long millisecond =  (endTime-startTime);try {//获取操作描述OperateLogAnnotation annotation = method.getAnnotation(OperateLogAnnotation.class);//业务逻辑,把操作日志插入数据库中去} catch (Exception e) {e.printStackTrace();}return result;}/*** @AfterReturning 返回通知:在目标方法成功执行之后调用通知功能* @param result 返回结果* @throws Throwable*/@AfterReturning(value = "operLogPoinCut()", returning = "result")public void doAfterReturning(JoinPoint joinPoint,Object result) throws Throwable {}/*** 异常通知:方法抛出异常之后通知* @param joinPoint* @param ex*/@AfterThrowing(pointcut = "operLogPoinCut()", throwing = "ex")public void doAfterThrowing(JoinPoint joinPoint, Exception ex){String className = joinPoint.getTarget().getClass().getSimpleName();String methodName = joinPoint.getSignature().getName();log.info("==========日志切面异常通知 {}.{} 异常 {} ==========", className, methodName, ex.getMessage());}/*** 根据方法和传入的参数获取请求参数*/private Object getParameter(Method method, Object[] args) {List<Object> argList = new ArrayList<>();Parameter[] parameters = method.getParameters();for (int i = 0; i < parameters.length; i++) {//将RequestBody注解修饰的参数作为请求参数RequestBody requestBody = parameters[i].getAnnotation(RequestBody.class);if (requestBody != null) {argList.add(args[i]);}//将RequestParam注解修饰的参数作为请求参数RequestParam requestParam = parameters[i].getAnnotation(RequestParam.class);if (requestParam != null) {Map<String, Object> map = new HashMap<>();String key = parameters[i].getName();if (!StringUtils.isEmpty(requestParam.value())) {key = requestParam.value();}map.put(key, args[i]);argList.add(map);} else {argList.add(args[i]);}}if (argList.size() == 0) {return null;} else if (argList.size() == 1) {return argList.get(0);} else {return argList;}}}

三、操作日志注解放在你要切入的方法上

@Slf4j
@RestController
@RequestMapping("/test")
public class TestController  {@PostMapping("/log")@OperateLogAnnotation(operateModel = "测试模块", operateType = "测试", remark = "测试日志")public ApiResult log() {return ApiResult.ok();}
}

http://www.ppmy.cn/news/1186212.html

相关文章

python中使用websocket进行链接与数据存储

笔者最近在测试星火大模型的时候&#xff0c;他们是使用websocket 来建立对话&#xff0c;而且星火大模型开放的测试代码&#xff0c;质量上不咋地&#xff08;20231030记录&#xff09;&#xff0c;还需要对websocket有一定的了解&#xff0c;才适合自己微调。 安装&#xff…

Git窗口打开vim后如何退出编辑(IDEA/Goland等编辑器)

最近在学习git高级操作过程中&#xff0c;遇到了一下问题&#xff1a; 我在学习Git合并多个commit为一个的时候&#xff0c;需要输入一个命令 git rebase -i HEAD~2 这说明已经是编辑模式了。当我写好后&#xff0c;我还按照原来在linux上的按下ESC键&#xff0c;但是只是光…

ModuleNotFoundError: No module named ‘paddle.fluid.incubate.fleet‘

在使用rocketqa的时候可能会遇到下面的问题&#xff1a; 问题&#xff1a; 解决方法&#xff1a; 这完全是paddlepaddle的问题。 在rocketqa/utils/optimization.py出现下面的语句&#xff0c;这个时候直接把出错的注释掉就可以&#xff0c;因为它完全没有用到。&#xff08;…

使用 node.js 简单搭建Web服务 使用node简单搭建后端服务 使用node搭建服务

使用 node.js 简单搭建Web服务 使用node简单搭建后端服务 使用node搭建服务 1、初始化项目2、安装 Express.js Web 服务框架3、创建 app.js 主入口文件, 并且实现 GET、POST请求4、启动服务5、请求测试 1、初始化项目 例如项目名为 node-server-demo mkdir node-server-demo进…

vue3获取页面路径

import { useRouter, useRoute } from vue-routerconst router useRouter()router.currentRoute.value.path // 页面路径

Shell 脚本学习 day01

release node v1 初始版本 #定义备份目录#当前时间#检查备份目录是否存在&#xff0c;不存在需要创建# 查找并备份 .xxx 文件# 提取文件名&#xff08;不包含路径部分&#xff09;# 构建备份文件名# 将查出来的.xxx文件拷贝到备份目录#!/bin/bash # context 备份根目录下所有.…

S32DS踩坑日记二、调试和SPI

J-Link调试需要注意以下配置&#xff1a; 一&#xff1a;从下图中Debug Configurations进入配置J-Link 二&#xff1a; 三&#xff1a; 关于初始化&#xff1a; 还有一个宏&#xff1a; FEATURE_HAS_HIGH_SPEED_RUN_MODE需要改成0&#xff0c;因为高温型号不支持1。 如果不…

Android WMS——Dialog和Toast窗口创建(五)

前面文章介绍了 Activity 窗口创建的流程,这里我们在看一下 Dialog 和 Toast 窗口创建的流程。 一、Dialog窗口创建 Dialog 中创建 Window 是在其构造方法中完成。 1、Dialog显示 源码位置:/frameworks/base/core/java/android/app/Dialog.java private final WindowMana…