自定义MyBatis拦截器

article/2025/10/1 8:15:27

文章目录

  • 自定义MyBatis拦截器
    • 作用
    • MyBatis中的四大核心对象
    • 在mybatis中可被拦截的类型有四种(按照拦截顺序)
    • 拦截器需要实现Mybatis提供的Interceptor接口
    • 利用反射获取运行中的实体字段的名字
    • 利用反射动态的为sql语句传递新参数
    • 使用mybatis自定义的拦截器为插入,更新语句自动赋值的时候的小bug
    • 使用自定义MyBatis拦截器在对数据库进行更新插入的时候动态添加修改人,创建人参数
      • 定义拦截器类
      • 在mybatis的配置文件中声明拦截器
      • 在mapper映射文件中获取拦截器中设置的参数
      • 验证结果
    • MyBatis会把动态代理中所有的接口生成一个map集合以及BeanUtils.setProperty()可以往这个map集合里面动态添加键值对
    • interceptor方法中的invocation对象

自定义MyBatis拦截器

作用

通过拦截器可以拦截四大核心对象中的其中一个,我下文中拦截的是Executor核心对象,然后对这个核心对象的update方法进行了拦截,再结合反射,在每次更新的时候都动态的给sql加上一个更新人操作,在每次插入的时候都动态的给sql加上一个创建人操作。下文中的拦截器主要是在更新或者插入的时候,给sql语句多传递一个参数。
我们还可以通过拦截StatementHandler核心对象修改sql语句,还可以通过拦截其它两个核心对象达到某些目的。但是目前只掌握拦截Executor核心对象给sql语句动态的增加参数就行了。

MyBatis中的四大核心对象

MyBatis中的四大核心对象:Executor,StatementHandler,ParamterHandler,ResultSetHandler

拦截器可以拦截四大核心对象中的其中一个对象,然后对这个对象进行增强,如下图:

在这里插入图片描述

2.各个参数的含义:
@Intercepts:标识该类是一个拦截器;
@Signature:指明自定义拦截器需要拦截哪一个类型,哪一个方法;2.1 type:对应四种类型中的一种;2.2 method:对应接口中的哪个方法;2.3 args:对应哪一个方法参数类型(因为可能存在重载方法);

上图中的MyInterceptor拦截器,拦截的就是StatementHandler对象。至于上图中的method的值是什么,那就具体要看你是什么需求了,如下图:

在这里插入图片描述

通过args来指定上图中的方法中的参数,如下图:

在这里插入图片描述

什么叫做增强呢,就比如现在有一个sql语句,那么它在经过拦截器的时候,拦截器会给这个sql语句在原有的基础上增加一些新的东西,这就叫做增强。

在mybatis中可被拦截的类型有四种(按照拦截顺序)

Executor:拦截执行器的方法。
ParameterHandler:拦截参数的处理。
StatementHandler:拦截Sql语法构建的处理。
ResultHandler:拦截结果集的处理。拦截器顺序
Executor -> ParameterHandler -> StatementHandler -> ResultSetHandler

拦截器需要实现Mybatis提供的Interceptor接口

拦截器通过实现Mybatis提供的Interceptor拦截接口,重写了三个方法:setProperties/plugin/ intercept,三者执行顺序是setProperties—》plugin—》Interceptor。

 setProperties方法:该方法通过设置属性,将核心配置文件configuration.xml文件中对拦截器的配置项下的属性获取过来,便于在拦截器中使用。plugin方法:该方法用来协商,达成协议,把代理权给普通的业务员this,传进wrap方法实现的源码去做代理,没有获取代理权的代理人在这个地方就会停下,不会向下走了,获取代理权的代理人可以去做拦截代理。intercept方法:则是获取拦截对象下的要拦截的东西,然后对其加以改编,添加自己的行为,按照条件进行改编拦截对象,然后通过源码下的反射invocation来调用被拦截的方法,让原本被拦截的方法继续执行(invocation.proceed())。

invocation.proceed()是拦截器是否放行,如果拦截器执行了此句代码,那么表示拦截器要放行,那么我们的动态代理接口可以成功执行,但是如果拦截器中的intercept方法中,没有执行此句代码,那么就表示拦截器没有放行,那么动态代理接口就不可以成功执行;

如果我们在intercept方法中想要放行,直接return invocation.proceed();就可以了。

利用反射获取运行中的实体字段的名字

利用反射获取实体类中的字段的时候,必须要把setAccessible方法的值设置成true,这样在进行访问安全检查的时候才不会抛出异常,要不然利用反射获取实体类中的字段的时候会抛IllegalAccessException异常。

在这里插入图片描述

利用反射动态的为sql语句传递新参数

我们如果没有用反射,那么传递给sql语句的参数就是动态代理接口中传递的哪些参数,是不能够更改的,但是如果用上了反射,也就是使用BeanUtils.setProperty(bean,name,value)方法,那么我们会在运行期间,增加新的参数传递给sql语句。我们这里的bean对象是一个Map集合,如下图:

在这里插入图片描述
注意上图中的叙述有错误,不是改变一个实体类中的属性,而是往map集合中加一个键值对,bean是一个map集合。

在这里插入图片描述

使用mybatis自定义的拦截器为插入,更新语句自动赋值的时候的小bug

mapper映射文件中,从拦截器中取值的参数,一定要和拦截器中自动设置的参数保持一致,要不然的话是取不到拦截器中的值的,如下图:

在这里插入图片描述

update修改的时候,我们传递的goodsDO并没有modifyMan字段的值,但是因为有拦截器自动添加了modifyMan字段,所以数据库中的值会被自动插入,如下图:

在这里插入图片描述

使用自定义MyBatis拦截器在对数据库进行更新插入的时候动态添加修改人,创建人参数

定义拦截器类

如下图:

在这里插入图片描述

/*** @Date 2022/1/29 17:42* @Author 望轩*/
@Intercepts({@Signature(type = Executor.class ,method = "update",args={MappedStatement.class,Object.class})
})
public class MyInterceptor implements Interceptor {@Overridepublic Object intercept(Invocation invocation) throws Throwable {//invocation.getArgs()得到的结果就是args中的参数,第一个元素肯定是MappedStatement,第二个元素是我们传递给sql语句的参数//如果没有传递则只能得到一个元素,也就是invocation.getArgs().length的长度是1//如果相关的动态代理接口没有传递参数,则我们不需要对传递给sql语句的参数进行处理,直接放行动态代理接口方法if(invocation.getArgs().length == 1){//只要执行了invocation.proceed()方法才会对动态代理接口进行放行,否则动态代理接口不会执行return invocation.proceed();}//获取动态代理接口传递给sql语句的参数实体Object parameter = invocation.getArgs()[1];System.out.println(parameter);//获取Sql语句的类型,也即是Sql语句是增删改查中的哪一个MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();//修改人或者是创建人String man = "";if(sqlCommandType.equals(SqlCommandType.INSERT)){man = "createMan";}if(sqlCommandType.equals(SqlCommandType.UPDATE)){man = "modifyMan";}//通过反射获取我们传递给sql语句也即是动态代理接口中的实体属性Field[] fields = GoodsDO.class.getDeclaredFields();for(Field field : fields){//安全性访问检查:设置为truefield.setAccessible(true);String fieldName = field.getName();if(fieldName.equals(man)){BeanUtils.setProperty(parameter,man,"wangxuan");System.out.println(parameter);}}return invocation.proceed();}@Overridepublic Object plugin(Object target) {//plugin方法主要是将拦截器中定义的增强功能(也就是拦截器)和原来的核心对象合并起来,成为最终的核心对象wrap,然后把这个对象返回Object wrap = Plugin.wrap(target, this);return wrap;}@Overridepublic void setProperties(Properties properties) {//这个方法里面可以取出来我们mybatis的配置文件中插件中配置的属性}}

在mybatis的配置文件中声明拦截器

在这里插入图片描述

在mapper映射文件中获取拦截器中设置的参数

在这里插入图片描述

验证结果

在这里插入图片描述

MyBatis会把动态代理中所有的接口生成一个map集合以及BeanUtils.setProperty()可以往这个map集合里面动态添加键值对

当MyBatis底层在处理动态代理接口中的参数的时候,会把动态代理接口中的参数处理成一个map集合。

如果动态代理接口中没有使用@Param注解。假设某个动态代理接口inter1(Object A,Object B,Object C),那么Mybatis最终会处理成Map{A:A(),B:B(),C:C(),param1:A(),param2:B(),param3:C()};我们在mapper的xml映射文件中,可以通过#{A}获取参数,也可以通过#{param1}获取参数。

**如果动态代理接口中使用了@Param注解。**假设某个动态代理接口inter2(@Param(“variable1”) Object A,@Param(“variable2”) Object B,@Param(“variable3”) Object C),那么MyBatis最终会处理成Map{“variable1”:A(),“variable2”:B(),“variable3”:C()}的形式。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

interceptor方法中的invocation对象

Invocation对象可以通过反射调度获取到拦截的某个核心对象的具体内容,比如说拦截的核心对象的名字,拦截的核心对象的方法,传递给核心对象的这个方法的参数,这些参数包括动态代理接口中传递给sql语句的参数。总之我们可以通过invocation这个对象通过反射调度,获取到sql语句的全部信息。

拦截器其实拦截的是四大核心对象中的某个方法,如果它拦截这个方法不放行,对应的动态代理接口,它就过不去,所以就不能执行sql语句;只要当拦截器放行了,动态代理接口才会执行。
invocation.proceed()是拦截器是否放行,如果拦截器执行了此句代码,那么表示拦截器要放行,那么我们的动态代理接口可以成功执行,但是如果拦截器中的intercept方法中,没有执行此句代码,那么就表示拦截器没有放行,那么动态代理接口就不可以成功执行;

如果我们在intercept方法中想要放行,直接return invocation.proceed();就可以了。


http://chatgpt.dhexx.cn/article/ge6R7Gfy.shtml

相关文章

Mybatis拦截器的使用及其源码详解

Mybatis拦截器的使用及其源码详解 Mybatis相关全览一、简介执行与添加顺序拦截器生效入口 二、使用例子 三、原理加载入口生成代理遍历拦截器匹配&生成代理 四、实践例子 本文用的是3.5.10版本 源码地址:https://github.com/mybatis/mybatis-3/releases 文档地址…

Mybatis拦截器Interceptor

前言 最近项目使用Mybatis拦截器对数据进行加解密,以下记录如何将拦截器集成到项目中以及在使用过程中踩过的一些小坑,与君共勉 1.Myabtis拦截器是什么? MyBatis允许使用者在映射语句执行过程中的某一些指定的节点进行拦截调用&#xff0c…

Springboot 自定义mybatis 拦截器,实现我们要的扩展

前言 相信大家对拦截器并不陌生,对mybatis也不陌生。 有用过pagehelper的,那么对mybatis拦截器也不陌生了,按照使用的规则触发sql拦截,帮我们自动添加分页参数 。 那么今天,我们的实践 自定义mybatis拦截器也是如此&a…

mybatis 拦截器

🚀 优质资源分享 🚀 学习路线指引(点击解锁)知识定位人群定位🧡 Python实战微信订餐小程序 🧡进阶级本课程是python flask微信小程序的完美结合,从项目搭建到腾讯云部署上线,打造一…

Mybatis——拦截器Interceptor

本篇介绍Mybatis拦截器/插件相关知识,包括相关的类及作用、拦截器有哪几种、拦截器可以在Mybatis的执行过程中的哪些节点起作用、拦截器如何使用、相关的API,最后附上代码示例。 1. Mybatis拦截器是什么?一般用途? MyBatis允许使…

vue后台管理框架(iview + vue)

iview官网:https://www.iviewui.com/docs/introduce vueiview后台管理文档:https://lison16.github.io/iview-admin-doc/#/ vueiview后台管理线上示例:https://admin.iviewui.com/login vueiview后台管理github:https://github.co…

基于ThinkPHP6+Layui的后台管理框架

项目介绍 一款 PHP 语言基于 ThinkPhp6.x、Layui、MySQL等框架精心打造的一款模块化、插件化、高性能的前后端分离架构敏捷开发框架,可用于快速搭建前后端分离后台管理系统,本着简化开发、提升开发效率的初衷,框架自研了一套个性化的组件&am…

Quickadmin:基于ThinkPhp6+Vue+ElementUI后台管理框架

Quickadmin:基于ThinkPhp6VueElementUI后台管理框架 简介 QuickAdmin 是一款基于ThinkPHP 6.x,ElementUI&&Vue 2.x前后端分离后台管理框架,通过框架自带的在线代码生成器,可以轻松的实现后台管理的curd(增删…

后台管理怎样用html实现,后台管理实现

京淘后台管理实现 1.1 商品列表展现 1.1.1 商品POJO对象 1.1.2 表格数据页面结构 1.1.3 请求URL地址 说明:如果采用UI框架并且添加了分页插件,则会自动的形成如下的URL请求地址 1.1.4 编辑ItemController 1.1.5 编辑ItemService 1.1.6 编辑ItemMapper 手…

【React项目架构 】+后台管理系统cms实操

React项目架构 一、 react脚手架 (一) 、yarn 安装 (二) 、react安装 npx create-react-app [-g] npm i react17.0.0 react-dom17.0.0 babel-standalone6.26.0 npm i react-router-dom npm i redux4.1.1 --save npm i redux-thunk2.4.1 npm i redux-persist npm install an…

Python实现的一个简洁轻快的后台管理框架.支持拥有多用户组的RBAC管理后台,不用配置各种运行环境

Mini Admin 完整代码下载地址:Python实现的一个简洁轻快的后台管理框架.支持拥有多用户组的RBAC管理后台 Mini Admin,一个简洁轻快的后台管理框架.支持拥有多用户组的RBAC管理后台 🚀 应用场景:2-5人的管理团队,需要管理的资源数…

vue——后台管理系统框架

效果图 代码: <template><el-container class="box-el-container"><el-aside class="box-el-aside" :style="{width:isCollapse?60px:200px}"><el-col :span="12" class="el-menu-aside"><!…

基于ThinkPHP6+Layui通用后台管理框架

项目介绍 一款 PHP 语言基于 ThinkPhp6.x、Layui、MySQL等框架精心打造的一款模块化、插件化、高性能的前后端分离架构敏捷开发框架&#xff0c;可用于快速搭建前后端分离后台管理系统&#xff0c;本着简化开发、提升开发效率的初衷&#xff0c;框架自研了一套个性化的组件&am…

Rust学习指南(一)安装RUST后台管理框架

Windows安装 Rust安装非常简单&#xff0c;只要将Visual Studio的 Visual Studio的构建工具或者Visual Stuido 2022的构件工具安装即可。当被问及要安装哪些内容时&#xff0c;请确保已选择 “C build tools”&#xff0c;并包括 Windows 10 SDK 和英文语言包。具体可以参考这个…

php是一种通用开源,caozha-admin(PHP网站后台管理框架)

caozha-admin 后台管理框架 1.7.2 caozha-admin是一个通用的PHP网站后台管理框架&#xff0c;基于开源的ThinkPHP开发&#xff0c;特点&#xff1a;易上手&#xff0c;零门槛&#xff0c;界面清爽极简&#xff0c;极便于二次开发。 基础功能 1、系统设置 2、管理员管理 3、权限…

移动端后台管理系统框架

创建此项目的初衷 目前移动端越来越重要&#xff0c;好多项目都从PC端转移到了移动端。 前一段给客户做了一个PC和M自适应的项目&#xff0c;用vue-element-admin框架&#xff0c;手机端也能用&#xff0c;但体验有点差&#xff0c;客户改了好多。本来是好意&#xff0c;客户只…

(若依)RuoYi后台管理框架前端

若依后台管理 官方网址 后台管理二开推荐 官网的源码地址可供下载前后端代码 最近进到公司后跟着团队接了两家公司的App一套的开发&#xff0c;到公司的第一天就是先配置开发环境 安装软件之类的 第二天 带着熟悉RuoYi框架 很巧带我的大哥和我是一个学校毕业的 是大师兄 若依…

后台管理系统框架bootstrap中文版

简介&#xff1a; 后台管理系统框架bootstrap中文版 网盘下载地址&#xff1a; http://kekewl.cc/8TLdhidu7gi0 图片&#xff1a;

SpringBoot后台管理系统框架

SpringBoot后台管理系统框架 SpringBoot后台管理系统功能介绍 登录 注册 用户列表和添加功能 只是个框架 实现了shiro权限控制, 详细的shiro使用 一个模板项目系统 只有少量功能 使用技术 SpringBoot框架 Mysql数据库 redis shiro权限 thymeleaf(前端) 功能展示 shi…

thinkphp 后台管理框架swiftadmin的使用

SwiftAdmin 极速开发框架 这款框架是基于ThinkPHP Layui 完美契合&#xff0c;在开发上采用最精简最高效的做法去完成业务系统的需求&#xff0c;是一款优秀的中后台极速开发解决方案。 可以很卡快的上手开发&#xff0c;而且他的文档也很完善&#xff0c;代码量不是很多&…