mybatis、mybatis-plus插件开发,实现数据脱敏功能

首先说一下mybatis中四大组件的作用,下面开发的插件拦截器会使用
四大组件Executor、StatementHandler、ParameterHandler、ResultSetHandler


Executor:

Executor 是 MyBatis 中的执行器,负责 SQL 语句的执行工作。它通过调度 StatementHandler、ParameterHandler 和 ResultSetHandler 来完成 SQL 的增删改查操作。Executor 管理事务和缓存,可以是 SimpleExecutor、ReuseExecutor、BatchExecutor 或在开启二级缓存时的 CachingExecutor。

ParameterHandler:

ParameterHandler 用于处理 SQL 语句的参数设置。它将 Mapper 接口方法的参数封装,并负责将这些参数值传递给 PreparedStatement,以便进行预编译和执行。ParameterHandler 通过 TypeHandler 接口完成 Java 类型到 JDBC 类型的转换。

ResultSetHandler:

ResultSetHandler 负责处理 SQL 执行后的返回结果集(ResultSet)。它将结果集转换并映射到 Java 对象,完成从数据库字段到 Java 实体属性的映射工作。ResultSetHandler 能够处理多种结果集的复杂映射关系。

StatementHandler:

StatementHandler 是 MyBatis 中的语句处理器,它是四大对象的核心,起到承上启下的作用。StatementHandler 负责使用 JDBC 的 Statement(包括 PreparedStatement 和 CallableStatement)执行实际的数据库操作。它通过调用 ParameterHandler 来设置 SQL 参数,并通过调用 ResultSetHandler 来处理查询结果。



实现思路:


1 首先我们需要对数据的结果集进行拦截,也就是说需要拦截这个接口的方法

2 得到数据返回的结果集后,对结果集转换成 List 进行遍历脱敏

3 脱敏的时候我们还需要判断一下哪些字段需要进行脱敏,这里我们定义注解来标识需要脱敏的字段(在这个注解里面可以定义一些脱敏策略,比如对手机号的脱敏规则、身份证的脱敏规则等等)

4 遍历的时候通过反射,获取所有属性

5 我这里的脱敏有三个条件

        a、必须带有 脱敏标识注解
        b、必须是 String 类型
        c、不得为空,这里直接使用工具类来判断 StringUtils.isEmpty()


6 脱敏条件达成后,就获取该注解上的 脱敏策略,根据脱敏策略 对属性进行脱敏

7 将脱敏后的结果重新设置到属性上


具体实现步骤


定义注解和不同的脱敏策略

import java.util.function.Function;

//这里的Function是jdk8新特性,自己了解一哈子
//提示:传入一个函数执行
public interface Desensitizer extends Function<String,String> {

}
//这里定义脱敏策略
public enum TuoMinStrategy {
    
    /*手机号*/
    PHONE(s->s.replaceAll("^(\\\\d{3})\\\\d{4}(\\\\d{4})$","$1****$2")),
    /*用户名 匹配中文全部替换*/
    USERNAME(s->s.replaceAll("[\\u4e00-\\u9fa5]","*"));

    private final Desensitizer desensitizer;

    TuoMinStrategy(Desensitizer d) {
        desensitizer = d;
    }

    public Desensitizer getDesensitizer() {
        return desensitizer;
    }
}
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

//作用于属性上
@Target(ElementType.FIELD)
//运行时生效
@Retention(RetentionPolicy.RUNTIME)
public @interface TuoMin {

    /**
     * 脱敏策略
     * @return
     */
    TuoMinStrategy strategy();

}

脱敏插件核心类
注意:注解中的属性,method和args不是硬背的,有技巧,如这个,
ResultSetHandler类,点进去,要拦截哪个方法,方法名直接复制,方法里的参数,直接copy 引用

import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.lang.reflect.Field;
import java.sql.Statement;
import java.util.List;
import java.util.stream.Stream;

@Component //需要放入到 ioc 容器中拦截器才会生效哦
//指定要拦截的目标方法的注解
//<h1>1、这个就是指定需要拦截的方法,这里我们指定拦截返回结果集的方法</h1>
@Intercepts(@Signature(type = ResultSetHandler.class,method = "handleResultSets",args= Statement.class))
public class TongMinPlugin implements Interceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
       	//<h1>2、得到数据返回的结果集,对结果集转换成 List<Object> 进行遍历脱敏</h1>
        List<Object> records = (List<Object>) invocation.proceed();
        System.out.println("records = " + records);
        // 遍历数据 调用 tuoMin 这个方法
        records.forEach(this::tuoMin);
        return records;
    }

    private void tuoMin(Object source) {
        Class<?> sourceClass = source.getClass();
        System.out.println("sourceClass = " + sourceClass);
        MetaObject metaObject = SystemMetaObject.forObject(source);//这个东东是 mybatis 提供的,通过这个玩意我们可以得到属性的值
        System.out.println("metaObject = " + metaObject);
        // 使用 stream 流
        /**
         * 1、得到所有属性
         * 2、筛选出带有 TuoMin.class 注解的属性
         * 3、调用doTuoMin方法将这些属性脱敏
         */
        Stream.of(sourceClass.getDeclaredFields())
                .filter(field -> field.isAnnotationPresent(TuoMin.class))
                .forEach(field->doTuoMin(metaObject,field));
    }

    private void doTuoMin(MetaObject metaObject, Field field) {
        System.out.println("metaObject = " + metaObject);
        System.out.println("field = " + field);

        String name = field.getName();
        System.out.println("name = " + name);
        Object value = metaObject.getValue(name);//根据属性名得到属性值
        System.out.println("value = " + value);
        // 脱敏条件:必须为String类型,值不等于空
        if (String.class == metaObject.getGetterType(name) && StringUtils.hasText(value.toString())) {
            //获取脱敏策略
            TuoMin tuoMin = field.getAnnotation(TuoMin.class);
            System.out.println("tuoMin = " + tuoMin);
            TuoMinStrategy type = tuoMin.strategy();
            System.out.println("type = " + type);
            // 调用策略正则表达式脱敏,得到结果
            Object apply = type.getDesensitizer().apply((String) value);
            System.out.println("apply = " + apply);
            // 将脱敏后的结果重新设置到属性上
            metaObject.setValue(name,apply);
        }
    }

}

3 在需要脱敏的pojo的字段上加上注解,如

@TableField(value = "title")
@TuoMin(strategy = TuoMinStrategy.USERNAME) //加上注解并指定脱敏策略
private String title;

测试,举例

脱敏前:
张三达美

脱敏后:
张 * * 美


部分文字和代码引用博文
【MyBatis】脱敏插件_前端脱敏插件是什么-CSDN博客

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

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

相关文章

在SpringBoot 3.0环境下创建一个SpringBoot 项目

一、环境配置 1.专业版的IDEA 版本号&#xff1a;尽量选择不要太老&#xff0c;不要太早 这里以2023.3.1为例。 官网&#xff1a;Download IntelliJ IDEA – The Leading Java and Kotlin IDE (jetbrains.com) 破解版&#xff1a;网上找资料哦&#xff01;&#xff01;&#…

【Python】基于动态规划和K聚类的彩色图片压缩算法

引言 当想要压缩一张彩色图像时&#xff0c;彩色图像通常由数百万个颜色值组成&#xff0c;每个颜色值都由红、绿、蓝三个分量组成。因此&#xff0c;如果我们直接对图像的每个像素进行编码&#xff0c;会导致非常大的数据量。为了减少数据量&#xff0c;我们可以尝试减少颜色…

7.7、指针和函数

代码 #include <iostream> using namespace std;//实现两个数字进行交换 void swap01(int a, int b) {int temp a;a b;b temp;cout << "swap01a " << a << endl;cout << "swap01b " << b << endl; }void sw…

AUTOSAR NvM模块(七)

NvM工具配置demo 一切block的配置根据自己的需求&#xff01; NvMBlockDescriptor NvM Common MemIf General FeeBlockConfiguration FeeGeneral

Go语言学习:每日一练3

Go语言学习&#xff1a;每日一练3 目录 Go语言学习&#xff1a;每日一练3方法接口继承类型断言 方法 方法是一类有接收者参数的函数。 接收者的类型定义和方法的声明必须在一个包里 type MyInt intfunc (m MyInt) Add(add int) int {return int(m) add } //OR func (m *MyInt)…

苹果Mac电脑能玩什么游戏 Mac怎么运行Windows游戏

相对于Windows平台来说&#xff0c;Mac电脑可玩的游戏较少。虽然苹果设备的性能足以支持各种大型游戏&#xff0c;但由于系统以及苹果配套服务的限制&#xff0c;很多游戏无法在Mac系统中运行。不过&#xff0c;借助虚拟机软件&#xff0c;Mac电脑可以突破系统限制玩更多的游戏…

66.Python-web框架-Django-免费模板django-datta-able的分页的一种方式

目录 1.方案介绍 1.1实现效果 1.2django.core.paginator Paginator 类: Page 类: EmptyPage 和 PageNotAnInteger 异常: 1.3 templatetags 2.方案步骤 2.1创建一个common app 2.2创建plugins/_pagination.html 2.3 其他app的views.py查询方法 2.4在AIRecords.html里…

Unity中模拟抛物线(非Unity物理)

Unity中模拟抛物线非Unity物理 介绍剖析问题以及所需公式重力加速度公式&#xff1a;h 1/2*g*t*t(h 1/2 * g * t ^ 2)速度公式&#xff1a;Vt V初 a * t 主要代码总结 介绍 用Unity物理系统去做的抛物线想要控制速度或者想要细微的控制一些情况是非常困难的。所以想要脱离U…

Flutter——最详细(Drawer)使用教程

背景 应用左侧或右侧导航面板&#xff1b; 属性作用elevation相当于阴影的大小 import package:flutter/material.dart;class CustomDrawer extends StatelessWidget {const CustomDrawer({Key? key}) : super(key: key);overrideWidget build(BuildContext context) {return…

【Python】已解决ModuleNotFoundError: No module named ‘tensorflow‘

文章目录 一、分析问题背景二、可能出错的原因三、错误代码示例四、正确代码示例五、注意事项 已解决ModuleNotFoundError: No module named ‘tensorflow‘ 一、分析问题背景 ModuleNotFoundError: No module named ‘tensorflow’ 是一个常见的错误&#xff0c;通常在Pytho…

MATLAB常用语句总结7

MATLAB总结7&#xff1a;常见错误归纳 文章目录 MATLAB总结7&#xff1a;常见错误归纳前言一、rand 的使用二、蒙塔卡罗求解方法1.函数的定义2.函数引用 三、函数引用与多变量四、矩阵引用五、非线性函数&#xff1a;fmincon的使用六、线性规划函数1.linprog2.fminbnd、fminsea…

Docker学习笔记(二)镜像、容器、仓库相关命令操作

一、docker镜像操作 列出镜像列表 我们可以使用 docker images 来列出本地主机上的镜像。 各个选项说明: REPOSITORY&#xff1a;表示镜像的仓库源 TAG&#xff1a;镜像的标签 IMAGE ID&#xff1a;镜像ID CREATED&#xff1a;镜像创建时间 SIZE&#xff1a;镜像大小 查…

pdf太大怎么压缩大小,pdf文件太大如何压缩变小

在数字化时代&#xff0c;pdf文件已成为我们工作、学习和生活中不可或缺的一部分。然而&#xff0c;随着文件内容的丰富&#xff0c;pdf文件的体积也日益增大&#xff0c;给存储和传输带来不便。本文将为你详细介绍四种实用的pdf文件压缩方法&#xff0c;帮助你轻松减小pdf容量…

【ROS2】初级:CLI工具 -配置环境

目标&#xff1a;本教程将指导您如何准备您的 ROS 2 环境。 教程级别&#xff1a;初学者 时间&#xff1a;5 分钟 目录 背景 先决条件 任务 源代码设置文件将源添加到您的 shell 启动脚本检查环境变量 摘要 下一步 背景 ROS 2 依赖于使用 shell 环境组合工作空间的概念。“Work…

C# Winform自制多轴力臂(简单易懂,方便扩展)

WinForms框架广泛应用于上位机开发领域&#xff0c;其中对力臂的精准控制是常见需求之一。本文深入探讨了如何创建自定义的多轴力臂图形控件&#xff0c;不仅涵盖了力臂图形控件的角度调节机制&#xff0c;还详细展示了如何实现力臂运动的生动动态效果&#xff0c;为开发者提供…

解决VSCode中导入PyTorch时报错的HTTP错误与Channel冲突

问题描述与解释 在Anaconda中成功安装PyTorch&#xff0c;并进行了验证&#xff1a; (base) C:\Users\Hui>conda activate pytorch(pytorch) C:\Users\\Hui>python Python 3.8.19 (default, Mar 20 2024, 19:55:45) [MSC v.1916 64 bit (AMD64)] :: Anaconda, Inc. on …

妙手ERP支持授权TikTok Shop全托管店铺,支持智能编辑、定时发布等操作!

全托管模式可以说是近两年跨境电商的热潮&#xff0c;在全托管模式下&#xff0c;卖家只需备货&#xff0c;平台进行运营、履约。因此&#xff0c;这种模式也迅速成为计划出海的跨境卖家重点关注方向。 一、TikTok Shop全托管 目前&#xff0c;几大主流跨境电商平台都已上线全…

springboot旅游管理系统-计算机毕业设计源码16021

摘 要 本文旨在设计和实现一个基于Spring Boot框架的旅游管理系统。该系统通过利用Spring Boot的快速开发特性和丰富的生态系统&#xff0c;提供了一个高效、可靠和灵活的解决方案。系统将实现旅游景点信息的管理、线路规划、跟团游玩、旅游攻略、酒店信息管理、订单管理和用户…

【操作与配置】VSCode配置C/C++及远程开发

MINGW环境配置 进入网站&#xff0c;如下图下载&#xff1a;MinGW Distro - nuwen.net 运行安装包&#xff0c;使其安装在你指定的位置 将MinGW的bin目录添加到系统的环境变量PATH中 使用 winx 选择进入“系统”点击“高级系统设置”在“系统属性&#xff1a;高级”窗口中&am…

Vue前端打包

关于NGINX 介绍:Nginx是一款轻量级的Web服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器。其特点是占有内存少&#xff0c;并发能力强&#xff0c;在各大型互联网公司都有非常广泛的使用。 NGiMx 官网:https://nginx.org/ conf 配置文件目录 html静态资源文件目录 lo…