SpringBoot项目使用AOP及自定义注解保存操作日志

news/2024/12/25 2:38:52/文章来源:https://www.cnblogs.com/bigcat26/p/18529065

@

目录
  • 概述:
  • 特色
  • 使用方式
  • 注意点
  • 代码
    • 第一步:pom引入AOP
    • 第二步:创建自定义注解、Bean实体、枚举、常量类
    • 第三步:Controller层方法使用自定义注解标识
    • 第四步:新建一个日志操作类LogAopAction,专门用来处理操作保存日志
    • 第五步:postman模拟调用接口,输出AOP中ProceedingJoinPoint获取目标方法,参数,注解

概述:

该SpringBoot项目使用AOP的环绕@Around注解及自定义注解保存操作日志到数据库,自定义注解中会配置日志模板类型logModelType字段,通过该字段去匹配是创建、删除、修改...等等功能,本案例就是为了模拟现实项目中通过AOP及自定义注解如何保存操作详情日志功能。

特色

form表单除了input输入框,也会有一些按钮【Disable/Enable】,这些按钮就需要转换数字值然后动态拼接详情日志参数,日志操作类LogAopAction中拼接参数不只是简单的一堆get、set、if else去拼接,而是根据类型logModelType字段 =》 去找枚举LogDetailEnums =》通过枚举值找常量类LogDetailConstants,常量类中定义了各种类型操作的占位符,动态拼接参数使用MessageFormat.format(),这样使用更加简单、看起来更加优雅、实现可扩展性不用写一堆代码。

使用方式

  1. 第一步:pom引入AOP
  2. 第二步:创建自定义注解、Bean实体、枚举、常量类
  3. 第三步:Controller层方法使用自定义注解标识
  4. 第四步:新建一个日志操作类LogAopAction,专门用来处理操作保存日志
  5. 第五步:postman模拟调用接口,输出AOP中ProceedingJoinPoint获取目标方法,参数,注解

注意点

  • 注意点1:日志操作类LogAopAction必须加两个注解@Aspect和@Component,其中@Aspect注解代表该类为切面,而@Component为了使该类能让spring容器扫描到
  • 注意点2:@Around注解中配置@annotation注解用来指定生效的自定义注解名字
  • 注意点3:该案例描述AOP中ProceedingJoinPoint获取目标方法,参数,注解
  • 注意点4:接收实体Bean要重新toString方法,不然无法转成json,因为未重写toString方法中用的是等号 "=" 而不是冒号 ":"
  • 注意点5:格式化常量类定义好的占位符请使用MessageFormat.format(),拼接起来更加方便

代码

第一步:pom引入AOP

<!--aop相关的依赖引入-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.78</version>
</dependency>

第二步:创建自定义注解、Bean实体、枚举、常量类

自定义注解LogAnnotation

package com.example.demo.config;import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface LogAnnotation {//日志模板类型String logModelType();
}

实体类

package com.example.demo.bean;import lombok.Data;/*** @Author 211145187* @Date 2022/2/23 09:32**/
@Data
public class OperateTeacherReq {//idprivate Integer id;//姓名private String name;//开关【0:Disable、1:Enable】private Integer pstnFlag;@Overridepublic String toString() {return "{" +"id:" + id +", name:'" + name + '\'' +", pstnFlag:" + pstnFlag +'}';}
}

枚举类LogDetailEnums

package com.example.demo.enums;public enum LogDetailEnums {/*** 开户*/CREATE_ACCOUNT("CREATE_ACCOUNT", LogDetailConstants.CREATE_ACCOUNT),/*** PSTN Flag值转换*/PSTN_ENABLE_FLAG("pstnFlag_1","Enable"),PSTN_DISABLE_FLAG("pstnFlag_0","Disable");private String code;private String message;LogDetailEnums(String code, String message) {this.code = code;this.message = message;}public String getCode() {return code;}public void setCode(String code) {this.code = code;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}public static String getDetailByCode(String messageCode){try {for (LogDetailEnums value : LogDetailEnums.values()) {if (value.code.equals(messageCode)){return value.message;}}} catch (Exception e) {e.printStackTrace();}return "";}public static LogDetailEnums getLogDetailEnum(String code){if (code==null){return null;}for (LogDetailEnums value : LogDetailEnums.values()) {if (code.equals(value.code)){return value;}}return null;}
}

常量类LogDetailConstants

package com.example.demo.enums;public class LogDetailConstants {public static final String CREATE_ACCOUNT = "【Add Account】id:[{0}], User Name:[{1}],pstnFlag:[{2}]";
}

第三步:Controller层方法使用自定义注解标识

package com.example.demo.controller;import com.example.demo.bean.TeacherReq;
import com.example.demo.config.LogAnnotation;
import com.example.demo.mapper.TeacherMapper;
import com.example.demo.response.Response;
import org.apache.commons.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;import java.io.File;
import java.io.IOException;/*** @Author 211145187* @Date 2022/5/7 11:34**/
@RestController
public class Controller {
@RequestMapping(value = "/operateLog", method = RequestMethod.POST)@LogAnnotation(logModelType = "CREATE_ACCOUNT")public Response operateLog(@RequestBody OperateTeacherReq req) {return Response.success(req);}
}

第四步:新建一个日志操作类LogAopAction,专门用来处理操作保存日志

package com.example.demo.config;import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.example.demo.bean.OperateTeacherReq;
import com.example.demo.enums.LogDetailEnums;
import com.example.demo.response.Response;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;import java.lang.reflect.Method;
import java.text.MessageFormat;@Aspect
@Component
public class LogAopAction {/*** AOP切面保存操作日志* @Author 211145187* @Around 注解描述的方法为一个环绕通知方法,在此方法中可以添加扩展业务逻辑,可以调用下一个切面对象或目标方法* @param point 连接点(此连接点只应用@Around描述的方法)* @Date 2022/5/16 14:38* @param point* @Return Response**/@Around("@annotation(com.example.demo.config.LogAnnotation) && execution(* com.example.demo.controller.*.*(..))")public Response logOperate(ProceedingJoinPoint point) throws NoSuchMethodException {//获取类的字节码对象,通过字节码对象获取方法信息Class<?> targetCls=point.getTarget().getClass();//获取方法签名(通过此签名获取目标方法信息)MethodSignature signature = (MethodSignature) point.getSignature();Method method = signature.getMethod();//获取目标方法上的注解指定的操作名称Method targetMethod=targetCls.getDeclaredMethod(signature.getName(),signature.getParameterTypes());System.out.println("获取目标方法上的注解指定的操作名称:"+targetMethod);LogAnnotation logAnnotation = method.getAnnotation(LogAnnotation.class);String logModelType=logAnnotation.logModelType();System.out.println("获取自定义注解参数值logModelType:" + logModelType);//获取目标方法名(目标类型+方法名)String targetClsName=targetCls.getName();String targetObjectMethodName=targetClsName+"."+method.getName();System.out.println("获取目标方法名:" + targetObjectMethodName);//获取请求参数Object[] args = point.getArgs();//TODO 操作日志保存到数据库中String logDetailInfo = LogDetailEnums.getDetailByCode(logModelType);switch (LogDetailEnums.getLogDetailEnum(logModelType)) {case CREATE_ACCOUNT:OperateTeacherReq req = JSONObject.parseObject(JSON.toJSONString(args[0]), OperateTeacherReq.class);System.out.println("获取请求参数:" + req);JSONObject jsonObject = JSONObject.parseObject(req.toString());logDetailInfo = MessageFormat.format(logDetailInfo, req.getId(), req.getName(), LogDetailEnums.getDetailByCode("pstnFlag_" + jsonObject.getString("pstnFlag")));break;default:System.out.println("无该类型!");break;}return Response.success(logDetailInfo);}
}

第五步:postman模拟调用接口,输出AOP中ProceedingJoinPoint获取目标方法,参数,注解

常量类详情日志占位符:
public static final String CREATE_ACCOUNT = "【Add Account】id:[{0}], User Name:[{1}],pstnFlag:[{2}]";

postman调用接口

postman结果打印

控制台打印:

获取目标方法上的注解指定的操作名称:public com.example.demo.response.Response com.example.demo.controller.Controller.operateLog(com.example.demo.bean.OperateTeacherReq)
获取自定义注解参数值logModelType:CREATE_ACCOUNT
获取目标方法名:com.example.demo.controller.Controller.operateLog
获取请求参数:{id:1, name:'教师1', pstnFlag:1}

项目代码路径图片

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于Java+SpringBoot心理测评心理测试系统功能实现二

三、部分系统功能试卷信息实体类Entity、试卷答题信息实体类Entity、留言信息实体类Entity、公告信息实体类Entity、心理测试信息实体类Entity一、前言介绍: 1.1 项目摘要 心理测评和心理测试系统在当代社会中扮演着越来越重要的角色。随着心理健康问题日益受到重视,心理测评…

关于 IntelliJ IDEA 2024 安装激活教程(亲测有效~)

第一步速度慢的点击这里进行下载 第二步点击xx 关掉程序! 第三步 点击获取补丁文件 打开标注的文件注意: 以后这个文件夹不要动 点击 进入 /scripts点击【确定】按钮后,过程大概 5- 30 秒,如看到弹框提示 Done 时,表示成功完成,之后打开idea 输入 6G5NXCPJZB-eyJsaWNlbnN…

基于Java+SpringBoot心理测评心理测试系统功能实现一

三、部分系统功能关于我们信息实体类Entity、前台用户信息实体类Entity、封面图信息实体类Entity、咨询师信息实体类Entity、咨询师预约记录信息实体类Entity一、前言介绍: 1.1 项目摘要 心理测评和心理测试系统在当代社会中扮演着越来越重要的角色。随着心理健康问题日益受到…

高级语言程序设计课程第六次作业

这个作业属于哪个课程:https://edu.cnblogs.com/campus/fzu/2024C 这个作业要求在哪里:https://edu.cnblogs.com/campus/fzu/2024C/home 姓名:刘嘉奕 学号:102400204逻辑性强,难以理解,在使用指针时容易用错,&,的使用混杂关系难以找准,刚开始编写时无法打印最后一个…

灰色关联分析(系统分析)

笔记大纲 参阅:https://www.mubu.com/doc/2hVFyCub_lV 思维导图

别名与用户管理体系

别名与用户管理体系 1. 概述别名,给命令进行设置一般用于给命令设置一个昵称/爱称.ll ls -l color=auto应用场景:给常用命令设置个快捷方式,使用简单方便给危险命令加上的防护措施.1.1 如何创建别名--给rm设置别名只要运行rm就提示 rm is dangerous,pls use mv. 需求只有运行…

20222408 2024-2025-1 《网络与系统攻防技术》实验四实验报告

1.实验内容 1.1实验要求 (1)对恶意代码样本进行识别文件类型、脱壳、字符串提取操作。 (2)使用IDA Pro静态或动态分析所给的exe文件,找到输出成功信息的方法。 (3)分析恶意代码样本并撰写报告,回答问题。 (4)对于Snort收集的蜜罐主机5天的网络数据源进行分析,回答问…

SPSS 26 下载与安装教程

SPSS(Statistical Product and Service Solutions),即“统计产品与服务解决方案”,是社会科学研究领域内的翘楚。本教程提供了丰富的数据管理、描述统计、推断统计以及回归分析等功能介绍,界面友好,易学易用; 1、安装包 SPSS 26: 链接:https://pan.quark.cn/s/87f4464…

20222414 2024-2025-1 《网络与系统攻防技术》实验四实验报告

一、实验内容 1.恶意代码文件类型标识、脱壳与字符串提取 对提供的rada恶意代码样本,进行文件类型识别,脱壳与字符串提取,以获得rada恶意代码的编写作者,具体操作如下: (1)使用文件格式和类型识别工具,给出rada恶意代码样本的文件格式、运行平台和加壳工具; (2)使用…

[极客大挑战 2019]EasySQL 1 -Xxiaoma解题

0X01:先上解题过程 1:遇到这种题,第一个想到的就是sql注入,直接万能密码就得到flag了。 账户名为:1 or 1=1 # 密码随便输入 即可得到flag0X02:sql注入万能密码原理 SQL注入是一种安全漏洞,攻击者通过在应用程序的输入中插入或者操作SQL命令来改变原有SQL语句的结构,从而…

RISK ANALYSIS

人类健康和安全风险,微生物风险工程,数学建模,风险表征,风险沟通,风险管理和决策,风险感知,可接受性和伦理法律和监管政策,生态风险。@目录一、征稿简介二、重要信息三、服务简述四、投稿须知 一、征稿简介二、重要信息期刊官网:https://ais.cn/u/3eEJNv三、服务简述 …