mybatisplus自定义拦截器_springboot自定义拦截器

mybatisplus自定义拦截器_springboot自定义拦截器文章目录自定义MyBatis拦截器作用MyBatis中的四大核心对象在mybatis中可被拦截的类型有四种(按照拦截顺序)拦截器需要实现Mybatis提供的Interceptor接口利用反射获取运行中的实体字段的名字利用反射动态的为sql语句传递新参数使用mybatis自定义的拦截器为插入,更新语句自动赋值的时候的小bug使用自定义MyBatis拦截器在对数据库进行更新插入的时候动态添加修改人,创建人参数定义拦截器类在mybatis的配置文件中声明拦截器在mapper映射文件中获取拦截器中设置的参数验证结果

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

自定义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 { 

@Override
public 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){ 

//安全性访问检查:设置为true
field.setAccessible(true);
String fieldName = field.getName();
if(fieldName.equals(man)){ 

BeanUtils.setProperty(parameter,man,"wangxuan");
System.out.println(parameter);
}
}
return invocation.proceed();
}
@Override
public Object plugin(Object target) { 

//plugin方法主要是将拦截器中定义的增强功能(也就是拦截器)和原来的核心对象合并起来,成为最终的核心对象wrap,然后把这个对象返回
Object wrap = Plugin.wrap(target, this);
return wrap;
}
@Override
public 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();就可以了。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/195599.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 浅析AnyCast网络技术「建议收藏」

    浅析AnyCast网络技术「建议收藏」什么是BGPAnyCast?BGPanycast就是利用一个(多个)as号码在不同的地区广播相同的一个ip段。利用bgp的寻路原则,短的aspath会选成最优路径(bgp寻路原则之n),从而优化了访问速度。其实bgpanycast是不同服务器用了相同的ip地址。阿里的DNS就是使用了BGPAnyCast“其实bgpanycast是不同服务器用了相同的ip地址。”言简意赅啊!D…

  • 按位异或的深入理解[通俗易懂]

    按位异或的深入理解[通俗易懂]异或运算:首先异或表示当两个数的二进制表示,进行异或运算时,当前位的两个二进制表示不同则为1相同则为0.该方法被广泛推广用来统计一个数的1的位数!参与运算的两个值,如果两个相应bit位相同,则结果为0,否则为1。即:  0^0=0,   1^0=1,   0^1=1,   1^1=0按位异或的3个特点:(1)0^0=0,0^1=1 0

  • A卡福利 : AMD Fluid Motion Video补帧教程,让你的视频从24帧补到60帧(144)

    A卡福利 : AMD Fluid Motion Video补帧教程,让你的视频从24帧补到60帧(144)背景:AMDFluidMotionVideo是一项AMD研发,将帧率为24FPS【即帧每秒,FramesperSecond】或者其他帧率低于60FPS的视频补帧成60帧的技术。1.准备工具:完美解码(Potplayer),BuleskyFrc2.打开AMD的深红驱动设置,依次点击"视频"-"自定义"-"AMDFluidMotionVideo…

  • 一键分享到QQ空间、QQ好友、新浪微博、微信代码

    一键分享到QQ空间、QQ好友、新浪微博、微信代码

    2021年10月28日
  • phpstorm2021永久激活码[在线序列号][通俗易懂]

    phpstorm2021永久激活码[在线序列号],https://javaforall.cn/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

  • scala implicit class

    scala implicit classscala是一门scalable的语言,扩展性很强。 implicit 是scala的一个关键词,当它被用于class时,该类将被认为是implicitclass,它可以用来扩展现有类的行为和方法以下在scalaREPL中展示implicitclass的作用scala>”HAL”.increment:8:error:valueincrementi

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号