MyBatis组件的DAO层拦截器

最近老大想对储存到数据库的数据进行加密,不让某表的某几列以明文的形式储存,巧的是这些数据是公司框架写好的,不能直接上代码改。
而业务层对于这张表的数据,应用的地方非常多,从业务侧进行拦截不现实。
所以,决定指使本“怨种”编写 DAO 层的拦截器,对特定输入、输出的几个数据进行加解密。
…经过两天的 coding 拦截器完成度 80% 。
此时,提了一句“加密后的参数无法使用“模糊查询”,而且拦截的方法特别多”。老大大意回了句,先这样吧,弄别的先,看看别的有没有解决方案…
我…就知道~呵,DAO 层拦截器不被普遍使用是有原因的,一旦使用这项技术大概率是某个乌龙事件发生了~

查询拦截器

  1. 获取 id
  2. 比对 DAO 的全量方法名 com.xxx.xx.methedName 判断,是否是需要处理的方法
  3. 获取参数,判断、强转 参数为 bean
  4. 处理参数,参数替换(原对象的参数是不可变的需要赋值替换)
  5. 执行“业务逻辑”
  6. 处理响应
  7. 结束
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
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.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;import java.util.List;/*** 用户查询拦截器**/
@Component
@Intercepts({@Signature(type = Executor.class, method = "query",args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),@Signature(type = Executor.class, method = "query",args = {MappedStatement.class, Object.class, RowBounds.class,ResultHandler.class, CacheKey.class, BoundSql.class})
})
@Slf4j
public class UserQueryInterceptor implements Interceptor {/*** 需要拦截的 DAO 层查询方法* 相同 set 代表相同响应 DTO*/private static final Set<String> USER_SET = new HashSet<>();private static final Set<String> USER_LIST_SET = new HashSet<>();static {final String basePkg = "com.xxx.xx.manage.user.core.dao.UserDao.";// userfinal String getDetail = basePkg + "getDetail";final String get = basePkg + "get";USER_SET.add(getDetail);USER_SET.add(get);// userListfinal String getByUserName = basePkg + "getByUserName";final String listUserByResourceId = basePkg + "listUserByResourceId";USER_LIST_SET.add(getByUserName);USER_LIST_SET.add(listUserByResourceId);}@Overridepublic Object intercept(Invocation invocation) throws Throwable {log.info("UserQueryInterceptor in");Object result = invocation.proceed();MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];// 获取执行idString id = mappedStatement.getId();log.info("id : {}", id);// 处理查询参数processQueryParams(invocation, id);// 处理响应processResult(id, result);log.info("UserQueryInterceptor end");return result;}/*** 处理查询参数** @param invocation invocation* @param id         id*/private void processQueryParams(Invocation invocation, String id) {//todo:加密后的参数无法使用模糊查询}/*** 处理响应** @param id* @param result*/private void processResult(String id, Object result) {if (ObjectUtils.isNull(result)) {return;}if (USER_SET.contains(id)) {User user = (User) result;decode(user);}if (USER_LIST_SET.contains(id)) {List<User> list = (List<User>) result;for (User user : list) {decode(user);}}}/*** 解密** @param user user*/private void decode(User user) {if (null == user) {return;}// todo 解密user.setName(decode(user.getName());}/*** 解密** @param data 密文* @return 原文*/private String decode(String data) {// todo 解密return null;}}

更新拦截器

  1. 获取 id
  2. 比对 DAO 的全量方法名 com.xxx.xx.methedName 判断,是否是需要处理的方法
  3. 获取参数,判断、强转 参数
  4. 处理参数,参数替换(原对象的参数是不可变的需要赋值替换)
  5. 执行“业务逻辑”
  6. 结束
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
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.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;import java.util.List;/*** 用户插入、更新查询拦截器**/
@Component
@Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})
})
@Slf4j
public class UserUpdateInterceptor implements Interceptor {@Overridepublic Object intercept(Invocation invocation) throws Throwable {log.info("UserUpdateInterceptor in");MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];// 获取执行idString id = mappedStatement.getId();log.info("id : {}", id);// 获取参数Object params;if (invocation.getArgs().length > 1) {params = invocation.getArgs()[1];} else {return invocation.proceed();}log.info("params {}", params);// 处理目标参数processTargetParams(invocation, id, params);log.info("UserUpdateInterceptor end");return invocation.proceed();}/*** 处理目标参数** @param invocation invocation* @param id         id id参见UserDao* @param params     参数* @see UserDao*/private void processTargetParams(Invocation invocation, String id, Object params) {final String insert = "com.xxx.xx.manage.user.core.dao.UserDao.insert";final String update = "com.xxx.xx.manage.user.core.dao.UserDao.update";final String insertBatch = "com.xxx.xx.manage.user.core.dao.UserDao.insertBatch";switch (id) {// 插入case insert -> {User insertUser = (User) params;if (null != insertUser) {encodeUserInfo(insertUser);invocation.getArgs()[1] = insertUser;}log.info("insertUser encode : {}", insertUser);}// 更新case update -> {User updateUser = (User) params;if (null != updateUser) {encodeUserInfo(updateUser);invocation.getArgs()[1] = updateUser;}log.info("updateUser encode : {}", updateUser);}// 批量插入case insertBatch -> {List<User> userList = (List<User>) params;log.info("insertBatch encode : {}", userList);if (!CollectionUtils.isEmpty(userList)) {for (User user : userList) {encodeUserInfo(user);}invocation.getArgs()[1] = userList;}log.info("updateUser encode : {}", userList);}default -> {}}}/*** 用户信息加密** @param user 用户信息*/private void encodeUserInfo(User user) {if (StringUtils.isNotEmpty(user.getName())) {user.setName(encode(user.getName()));}}/*** 加密* 注意长度不能超过数据库允许的长度** @param data 数据* @return 加密后的数据*/private String encode(String data) {// todo 加密 return null;}}

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

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

相关文章

Java版-剑指offer数据结构与算法 视频教程 下载

Java版-剑指offer数据结构与算法 视频教程 下载 01-数据结构与算法入门基础 clip.mp4 02-clip1.mp4 03-clip2.mp4 04-基础数据结构&#xff1a;数组&链表&#xff08;一&#xff09;.mp4 05基础数据结构&#xff1a;数组&链表&#xff08;二&#xff09;.mp4 06-基…

成都爱尔周进院长提醒毕业生摘镜,术式如何挑

高考完迎来一个悠长假期&#xff0c;考后放松的同时&#xff0c;也有不少同学开始“准备”。 为奔赴梦想&#xff0c;为了理想的专业和学校&#xff0c;不少人决定摘镜。 不少专业有视力要求&#xff0c;且不同专业方向的要求各有不同。我们先来看看有视力要求的专业有哪些&am…

数据集制作——语义分割前png、jpg格式标签图转yolo格式.txt文件(附代码)

&#x1f4aa; 专业从事且热爱图像处理&#xff0c;图像处理专栏更新如下&#x1f447;&#xff1a; &#x1f4dd;《图像去噪》 &#x1f4dd;《超分辨率重建》 &#x1f4dd;《语义分割》 &#x1f4dd;《风格迁移》 &#x1f4dd;《目标检测》 &#x1f4dd;《暗光增强》 &a…

从0开始C++(二):类、对象、封装

目录 类&对象的概念 类的内容 对象的创建 ● 栈内存对象 ● 堆内存对象 封装 类&对象的概念 类和对象是一个比较抽象的概念&#xff0c;这里直接用一个实例方便理解。 类&#xff1a;类是一个抽象的概念&#xff0c;用来描述同一类对象的特点&#xff08;比如&am…

第九届信也科技杯全球AI算法大赛——语音深度鉴伪识别参赛A榜 0.968961分

遗憾没有进复赛&#xff0c;只是第41名。先贴个A榜的成绩。A榜的前三十名晋级&#xff0c;个个都是99分的大佬&#xff0c;但是B榜的成绩就有点低了&#xff0c;应该是数据不同源的问题&#xff0c;第一名0.78分。官网链接&#xff1a;语音深度鉴伪识别 官方baselin:https://g…

Springboot 权限认证框架 -- SA-Token 简介(一)

引言 现今的软件开发中&#xff0c;权限认证与访问控制是每一个应用都必不可少的功能。SA-Token是一个简单、安全、易用的权限认证框架&#xff0c;它主要解决登录认证、权限认证、Session会话、单点登录等功能。SA-Token以其轻量级、零学习成本的特点&#xff0c;迅速赢得了开…

Java 网关进程在向驱动程序发送其端口号之前退出

java gateway process exited before sending the driver its port number #248TOC Spark项目 这个是远程调试的一个Spark项目&#xff0c;首先要保证 Spark正确安装&#xff0c;配置好环境变量&#xff0c;这是前提。 可能的问题 Java 网关进程是 Apache Spark 的一个关键…

数组的常用方法

1.Array.map() 此方法是将数组中的每个元素调用一个提供的函数&#xff0c;结果作为一个新的数组返回&#xff0c;并没有改变原来的数组 let arr [1, 2, 3, 4, 5]; let newArr arr.map(x > x * 2); //arr [1, 2, 3, 4, 5] 原数组保持不变 //newArr [2, 4, 6, 8, 10] …

Linux mongodb安装及简单使用

说明&#xff1a;本文章主要是对mongodb的单击安装 1.创建文件夹&#xff0c;准备安装包 cd /user/local mkdir tools 2.解压mongodb包 mkdir mongodb tar -xvf mongodb-linux-x86_64-rhel70-5.0.11.tgz -C mongodb 3.进入解压目录 cd mongodb cd mongodb-linux-x86_64-…

emm, ComfyUI的作者从Stability.AI离职了

&#x1f356;背景 今天在更新ComfyUI的过程中&#xff0c;看到Manager中有这样一段描述&#xff1a; 嗯&#xff1f;做了新的官方网站&#xff1f;然后开始新篇章&#xff1f; 难道说ComfyUI的作者从Stability.AI离职了&#xff1f; 赶紧点开链接看了下&#xff0c;emm&…

24.bytebuf创建

1.byteBuf创建方法 2.自动动态扩容的 package com.xkj.bound;import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import lombok.extern.slf4j.Slf4j;@Slf4j public class TestByteBuf {public static void main(String[] args) {//bytebuf可以不指定…

Java集合框架源码分析:LinkedList

文章目录 一、LinkedList特性二、LinkedList底层数据结构三、LinkedList继承关系参考&#xff1a; 一、LinkedList特性 特性描述是否允许为空允许是否允许重复数据允许是否有序有序是否线程安全非线程安全 二、LinkedList底层数据结构 LinkedList同时实现了List接口和Deque接…

基于PLC的全自动洗衣机控制系统课设

一、设计题目 1.1课题内容 根据设计参数和控制要求&#xff0c;设计一全自动洗衣机&#xff0c;画出其运行框图及梯形图控制程序的编制&#xff0c;并画出硬件接线图。 1.2设计参数 1.3控制要求 &#xff08;1&#xff09;按下启动按扭及水位选择开关&#xff0c;开始进水直…

object类教程

Python object 类教程 在 Python 中&#xff0c;object 是所有类的基类。所有 Python 类都隐式或显式地继承自 object。理解 object 类是理解 Python 面向对象编程&#xff08;OOP&#xff09;的关键。它为所有类提供了一些基本的方法和属性&#xff0c;并定义了类的行为和实例…

「51媒体-年中大促」天津有哪些媒体资源-媒体宣传服务公司

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 天津的媒体资源相当丰富&#xff0c;涵盖了报纸、电视、广播、新闻门户网站、央媒驻天津机构、视频媒体以及全国媒体资源等多个方面。以下是详细的媒体资源分类和具体信息&#xff1a; 一…

嵌入式web 服务器boa的编译和移植

编译环境&#xff1a;虚拟机 ubuntu 18.04 目标开发板&#xff1a;飞凌OKA40i-C开发板&#xff0c; Linux3.10 操作系统 开发板本身已经移植了boa服务器&#xff0c;但是在使用过程中发现POST方法传输大文件时对数据量有限制&#xff0c;超过1M字节就无法传输&#xff0c;这是…

嵌入式linux获取RGB图片不清晰问题

1.RGB摄像头都是同一个厂家的usb接口的摄像头&#xff0c;接入我们设备上面&#xff0c;应用层通过v4l2框架获取到的JPEG图片不清晰&#xff0c;应用层没有对图片做任何转换&#xff0c;也尝试过获取YUV图片&#xff0c;依然不清晰。 2.相同的USB摄像头&#xff0c;接入windows…

Java 面试题篇 Sleep()方法与Wait() 方法的区别

在 Java 中&#xff0c;sleep() 和 wait() 方法都可以用来控制线程的执行顺序或等待特定条件的发生&#xff0c;但它们有着不同的使用场景和行为&#xff1a; 1. sleep() - sleep() 方法来自于 Thread 类&#xff0c;用于让当前线程暂停执行一段时间&#xff0c;以毫秒为单位。…

Nginx-Rewrite

1、Rewrite的定义 rewrite功能就是使用nginx提供的全局变量或自己设置的变量&#xff0c;结合正则表达式和标志位实现url重写以及重定向。rewrite只能放在 server { }, location { }, if { }中&#xff0c;并且只能对域名后边的除去传递的参数外的字符串起作用。 例如location…

进阶必看,3种灵活操作PyTorch张量的高级方法

大家好&#xff0c;在PyTorch中进行高级张量操作时&#xff0c;开发者经常面临这样的问题&#xff0c;如何根据一个索引张量从另一个张量中选取元素。 例如有一个包含数千个特征的大规模数据集&#xff0c;需要根据特定的索引模式快速提取信息。本文将介绍三种索引选择方法来解…