AOP-注解实现-记录日志到数据库

概念解释

AOPAspect Oriented Programming

  • Aspect:方面
  • Oriented:面向…的
  • Programming编程

之前我对模块化编程的认识,主要是局限在布局结构、目录结构上。比如Vuetemplate模板。
对方法的模块化编程,我之前的认识局限在封装共用的工具方法上。
但没想到函数方法也可以用类似于模板的方式模块化构建。
利用的就是AOP面向切面编程。对应软件设计模式中的“代理模式”,创建对象的代理对象,代理对象的原始操作。
可以在连接点处插入切面逻辑。

  • 连接点:JoinPoint,可以被AOP控制的方法(暗含方法执行时的相关信息)
  • 通知:Advice,指哪些重复的逻辑,也就是共性功能(最终体现为一个方法)
  • 切入点:PointCut,匹配连接点的条件,通知仅会在切入点方法执行时被应用
  • 切面:Aspect,描述通知与切入点的对应关系(通知+切入点)
  • 目标对象:Target,通知所应用的对象

image.png

AOP配置

导入依赖

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

image.png
本文实现的是,通过注解,记录日志到数据库。
注解的作用是标注哪些方法需要插入切面逻辑。

  • 创建文件夹annotation存放注解接口,用于标注切入点
  • 创建文件夹aop存放的切面类,用于设计切面
  • mapper文件夹下创建OperateLogMapper接口,用于操作数据库
  • pojo文件夹下创建OperateLog实体类,用于映射user_log

自定义Log注解

Log注解的作用仅用于标识。
添加@Retention(RetentionPolicy.RUNTIME)指定注解运行时生效。
添加@Target(ElementType.METHOD)指定注解作用在方法上。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface UserLog {
}

注解的类型是@interface,就是在interface之前加了个@

切入点表达式

可以使用与或非来组合切入点表达式

  • execution(……):根据方法的返回值、包名、类名、方法名、方法参数等信息来匹配
    • execution(访问修饰符? 返回值 包名.类名.?方法名(方法参数) throws 异常?)
  • @annotation(……):根据注解匹配

image.png
本文中是通过注解匹配,也就是添加该注解的方法在执行完毕后会自动添加到日志。

    @Autowired
    private HttpServletRequest request;
    @Autowired
    private OperateLogMapper operateLogMapper;

    @Around("@annotation(top.wushf.server.annotation.UserLog)")
    public Object recordLog(ProceedingJoinPoint joinPoint) throws Throwable {
        String jwt = request.getHeader("token");
        Claims claims;
        Integer operateUser = null;
        try {
            claims = JwtUtils.parseJwt(jwt);
            operateUser = (Integer) claims.get("id");
        } catch (Exception e) {

        }
        LocalDateTime operateTime = LocalDateTime.now();
        String className = joinPoint.getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        String methodParams = Arrays.toString(args);
        long begin = System.currentTimeMillis();
        Object result = joinPoint.proceed();
        String returnValue = JSONObject.toJSONString(result);
        long end = System.currentTimeMillis();
        long costTime = end - begin;
        OperateLog operateLog = new OperateLog(null, operateUser, operateTime, className, methodName, methodParams, returnValue, costTime);
        operateLogMapper.insertUserLog(operateLog);
        return result;
    }
}

切入点的方法、类名、参数、返回值都可以通过joinPoint获取。
但操作用户携带在requestheader中。获取request对象,解析jwt令牌。
当前切入点的request对象通过@Autowired注解自动注入。
parseJwt可以会抛出异常,需要放到try{}catch(){}中。

mapper持久层

插入日志需要调用持久层中的insert方法,将日志记录插入到数据库中。

@Mapper
public interface OperateLogMapper {
    @Insert("insert into user_log (operate_user,operate_time,class_name,method_name,method_params,return_value,cost_time)" + "values (#{operateUser}, #{operateTime}, #{className}, #{methodName}, #{methodParams}, #{returnValue}, #{costTime});")
    public void insertUserLog(OperateLog log);
}

之后可能会扩展多个模块,多个业务有各自的日志。所以实现的是insertUserLog。插入到用户操作日志的数据库中。

pojo实体类

好处很多,便于维护、传参等等,不多赘述。

@Data
@NoArgsConstructor
@AllArgsConstructor
public class OperateLog {
    private Integer id;
    private Integer operateUser;
    private LocalDateTime operateTime;
    private String className;
    private String methodName;
    private String methodParams;
    private String returnValue;
    private Long costTime;
}

Jwt生成与解析

黑马PPT用的是0.9的老版本,新版本很多方法已经弃用。目前是0.12.5版本。

//私钥
private final static String SECRET = "";
//过期时间,单位:秒
public final static int ACCESS_EXPIRE = 60 * 60 * 24 * 7;
//加密算法
private final static SecureDigestAlgorithm<SecretKey, SecretKey> ALGORITHM = Jwts.SIG.HS256;
//密钥实例
public static final SecretKey KEY = Keys.hmacShaKeyFor(SECRET.getBytes());

public static String generateJwt(Map<String, Object> claims) {
    Date exprireDate = Date.from(Instant.now().plusSeconds(ACCESS_EXPIRE));
    return Jwts.builder().claims(claims).expiration(exprireDate).issuedAt(new Date()).signWith(KEY, ALGORITHM).compact();
}

public static Claims parseJwt(String jwt) {
return Jwts.parser().verifyWith(KEY).build().parseSignedClaims(jwt).getPayload();
}

较之前的版本,现在的版本应该是更统一化了。
创建和解析的过程,都是先创建builder,利用builder创建或解析jwt令牌。

参考

  • https://blog.csdn.net/qq_50969362/article/details/134100542
  • day13-SpringBoot AOP.pptx

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于springboot+layui仓库管理系统设计和实现

基于 java springbootlayui仓库管理系统设计和实现 博主介绍&#xff1a;多年java开发经验&#xff0c;专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 央顺技术团队 Java毕设项目精品实战案例《1000套》 欢迎点赞 收藏 ⭐留言 文末获取…

硬件工程师面试题梳理-百度硬件面试题

硬件工程师基本职责 在公司里面&#xff0c;硬件工程师的主要职责包括设计、开发和测试硬件系统&#xff0c;以满足产品需求和性能要求。他们负责确保硬件系统的可靠性、稳定性和可维护性&#xff0c;并与软件工程师和其他团队成员合作&#xff0c;以确保硬件和软件的协同工作…

arcgis辅助下的GIS滑坡泥石流易发性评估模型构建

我国是地质灾害多发国家&#xff0c;地质灾害的发生无论是对于地质环境还是人类生命财产的安全都会带来较大的威胁&#xff0c;因此需要开展地质灾害风险普查。利用遥感&#xff08;RS&#xff09;技术进行地质灾害调查工作具有宏观、快速、准确的特点&#xff0c;能反映出地质…

SpringCloud(21)之SpringCloud Alibaba Nacos实战应用

一、Nacos安装 1.1 Nacos概述 Nacos是Alibaba微服务生态组件中的重要组件之一&#xff0c;主要用它实现应用的动态服务发现、配置管理、 服务管理。Nacos discovery alibaba/spring-cloud-alibaba Wiki GitHub Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简…

MotionCtrl: A Unified and Flexible Motion Controller for Video Generation

MotionCtrl: A Unified and Flexible Motion Controller for Video Generation 这篇论文是基于VideoCrafter的&#xff0c;而VideoCrafter是基于LVDM的 关于LVDM可以看https://blog.csdn.net/Are_you_ready/article/details/136615853 2023年12月6日发表在arxiv 这篇论文讨论…

seo js转码工具

js转码工具作用 用于把js加密 如果不想让别人看到自己的js 代码就可以使用这个方法 js工具网址 https://tool.chinaz.com/js.aspx 效果

J.K.罗琳创作的《神奇动物》系列电影赏析

故事情节 《神奇动物在哪里》&#xff1a; 这部电影讲述了纽特斯卡曼德来到纽约的故事&#xff0c;他是一位收集和研究魔法动物的巫师。在纽约&#xff0c;他的一只神奇生物逃脱&#xff0c;并引发了一系列麻烦。与此同时&#xff0c;纽约巫师社会面临着黑暗力量的威胁&#x…

超大规模-近场

这里先了解基站到用户的&#xff0c;无RIS的近场模型 超大规模智能反射面辅助的近场移动通信研究 &#xff08;论文题目&#xff09; &#xff08;期刊&#xff09;无线电通信技术 系统&#xff1a;BS-RIS-UE&#xff0c;两个阶段都是近场 模型&#xff1a;球面波传播模型&…

在dpvs上实现ICMP的源进源出

目录 1. 缘起2. 源码分析3. 让ICMP也走源进源出1. 缘起 在网络通信中,当一个请求报文从源主机到达目标主机,并经过中间路由器或交换机进行转发时,请求报文进入主机A的路径和响应报文离开主机A的路径可能不同。这种情况下,就会出现所谓的三角路径问题。如下图: 具体来说,…

USB协议学习(三)大容量存储设备SCSI协议分析

笔者来简单介绍一下SCSI得协议命令 1、SCSI协议认识 SCSI&#xff1a;Small Computer System Interface&#xff0c;用于计算机外部设备得接口标准&#xff0c;定义了与外部设备得一套协议。SCSI标准协议族支持很多钟SCSI设备&#xff0c;像盘&#xff0c;打印机&#xff0c;扫…

论企业安全漏洞扫描的重要性

前言 随着信息技术的迅猛发展和互联网的广泛普及&#xff0c;网络安全问题日益凸显。在这个数字化的世界里&#xff0c;无论是企业还是个人&#xff0c;都面临着前所未有的安全威胁。安全漏洞&#xff0c;作为这些威胁的源头&#xff0c;常常被忽视或无法及时发现。 而安全漏洞…

提示并输入一个字符串,统计该字符中大写、小写字母个数、数字个数、空格个数以及其他字符个数要求使用C++风格字符串完成

#include <iostream> #include <array> using namespace std;int main() {cout<<"请输入一个字符串"<<endl;//array<string,100> str;string str;getline(cin,str);int daxie0,xiaoxie0,num0,space0,other0;int lenstr.size();;for(in…

植物病害识别:YOLO水稻病害识别数据集(11000多张,yolo标注)

YOLO水稻病害识别数据集&#xff0c;包含叶斑病&#xff0c;褐斑病&#xff0c;细菌性枯萎病&#xff0c;东格鲁病毒病4个常见病害类别&#xff0c;共11000多张图像&#xff0c;yolo标注完整&#xff0c;可直接训练。 适用于CV项目&#xff0c;毕设&#xff0c;科研&#xff0c…

Flink 性能优化总结(反压优化篇)

反压的理解 Flink 中每个节点间的数据都以阻塞队列的方式传输&#xff0c;下游来不及消费导致队列被占满后&#xff0c;上游的生产也会被阻塞&#xff0c;最终导致数据源的摄入被阻塞。简单来说就是系统接收数据的速率远高于它处理数据的速率。 反压如果不能得到正确的处理&am…

软件测试面试需要准备什么?面试有什么技巧?看完面试轻松解决

前言 无论是在校招还是社会企业招聘中&#xff0c;应聘者总是要经过层层的考核才能被聘用。然而&#xff0c;在招聘时&#xff0c;设置的编程以及非技术面试问题&#xff0c;真的有必要吗&#xff1f;如此就能考核出一位开发者的真实水平&#xff1f; 说到底就是考验你的技术以…

分享10个ai人工智能ppt生成软件,一键轻松搞定PPT制作!

ai 人工智能发展至今&#xff0c;已经诞生了各式各样的 AI 软件&#xff0c;最常见的如 AI 写作软件、AI 绘画软件、AI 人工智能 ppt 生成器、AI 人工智能抠图软件等等。对每天要面对各类文档、演示文稿&#xff08;PPT&#xff09;的职场人来说&#xff0c;最被需要的 AI 软件…

javascript:void(0);用法及常见问题解析

在Web开发中&#xff0c;javascript:void(0);是一个经常被用到的代码片段&#xff0c;特别是在一些老式的网页中。这个代码片段的作用是执行一个空操作&#xff08;null operation&#xff09;&#xff0c;即不执行任何操作。它的主要用途是在JavaScript代码中创建一个空链接&a…

AHU 汇编 实验二

一、实验名称&#xff1a;实验二 不同寻址方式的灵活运用 二、实验内容&#xff1a;定义数组a[6]&#xff0c;用多种寻址方式访问对应元素&#xff0c;实现&#xff08;a[0]a[1]&#xff09;*(a[2]-a[3])/a[4],将结果保存在内存a[5]中&#xff0c;用debug查询结果。 实验过程&a…

代码随想录算法训练营第四十六天| 139.单词拆分、背包总结

文章目录 1.单词拆分[2.背包总结] 1.单词拆分 给你一个字符串 s 和一个字符串列表 wordDict 作为字典。如果可以利用字典中出现的一个或多个单词拼接出 s 则返回 true。 注意&#xff1a;不要求字典中出现的单词全部都使用&#xff0c;并且字典中的单词可以重复使用。 示例 1…

c++ 开发环境 LNK1104: 无法打开文件“carve.lib” 已解决

别人分享&#xff0c; 和自己最近遇到问题一摸一样。以为没什么用的静态资源&#xff0c;结果 无法编译。 昨天安装配置了&#xff0c;结果今天早上打开电脑&#xff0c;所以dll的工程全部报错&#xff1a; 1>------ 已启动全部重新生成: 项目: Dll_test, 配置: Debug x64…