mybatisPlus|mybatis 拦截器(实现简单多租户 + 整合 mybatis plus 不影响分页插件 )
admin
2023-08-15 23:35:28
0

一。 Mybatis拦截器并不是每个对象里面的方法都可以被拦截的。Mybatis拦截器只能拦截Executor、ParameterHandler、StatementHandler、ResultSetHandler四个类里面的方法。
mybatisPlus|mybatis 拦截器(实现简单多租户 + 整合 mybatis plus 不影响分页插件 )
文章图片

二 。可以拦截四个对象中某个对象中的具体某一个方法

@Intercepts({@Signature( type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})}) public class MyBatisInterceptor implements Interceptor {/** * 代理对象每次调用的方法,就是要进行拦截的时候要执行的方法。在这个方法里面做我们自定义的逻辑处理 */ @Override public Object intercept(Invocation invocation) throws Throwable { return null; }/** * plugin方法是拦截器用于封装目标对象的,通过该方法我们可以返回目标对象本身,也可以返回一个它的代理 * * 当返回的是代理的时候我们可以对其中的方法进行拦截来调用intercept方法 -- Plugin.wrap(target, this) * 当返回的是当前对象的时候 就不会调用intercept方法,相当于当前拦截器无效 */ @Override public Object plugin(Object target) { return null; }/** * 用于在Mybatis配置文件中指定一些属性的,注册当前拦截器的时候可以设置一些属性 */ @Override public void setProperties(Properties properties) {} }

Intercepts的声明可以是多个Signaturetype拦截的是那个类method是类中的那个方法args是该方法的参数

三。先看下源码
package org.apache.ibatis.executor; import java.sql.SQLException; import java.util.List; import org.apache.ibatis.cache.CacheKey; import org.apache.ibatis.cursor.Cursor; import org.apache.ibatis.mapping.BoundSql; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.reflection.MetaObject; import org.apache.ibatis.session.ResultHandler; import org.apache.ibatis.session.RowBounds; import org.apache.ibatis.transaction.Transaction; public interface Executor { ResultHandler NO_RESULT_HANDLER = null; int update(MappedStatement var1, Object var2) throws SQLException; List query(MappedStatement var1, Object var2, RowBounds var3, ResultHandler var4, CacheKey var5, BoundSql var6) throws SQLException; List query(MappedStatement var1, Object var2, RowBounds var3, ResultHandler var4) throws SQLException; Cursor queryCursor(MappedStatement var1, Object var2, RowBounds var3) throws SQLException; List flushStatements() throws SQLException; void commit(boolean var1) throws SQLException; void rollback(boolean var1) throws SQLException; CacheKey createCacheKey(MappedStatement var1, Object var2, RowBounds var3, BoundSql var4); boolean isCached(MappedStatement var1, CacheKey var2); void clearLocalCache(); void deferLoad(MappedStatement var1, MetaObject var2, String var3, CacheKey var4, Class var5); Transaction getTransaction(); void close(boolean var1); boolean isClosed(); void setExecutorWrapper(Executor var1); }


package org.apache.ibatis.executor.parameter; import java.sql.PreparedStatement; import java.sql.SQLException; public interface ParameterHandler { Object getParameterObject(); void setParameters(PreparedStatement var1) throws SQLException; }

package org.apache.ibatis.executor.statement; import java.sql.Connection; import java.sql.SQLException; import java.sql.Statement; import java.util.List; import org.apache.ibatis.cursor.Cursor; import org.apache.ibatis.executor.parameter.ParameterHandler; import org.apache.ibatis.mapping.BoundSql; import org.apache.ibatis.session.ResultHandler; public interface StatementHandler { Statement prepare(Connection var1, Integer var2) throws SQLException; void parameterize(Statement var1) throws SQLException; void batch(Statement var1) throws SQLException; int update(Statement var1) throws SQLException; List query(Statement var1, ResultHandler var2) throws SQLException; Cursor queryCursor(Statement var1) throws SQLException; BoundSql getBoundSql(); ParameterHandler getParameterHandler(); }

package org.apache.ibatis.executor.resultset; import java.sql.CallableStatement; import java.sql.SQLException; import java.sql.Statement; import java.util.List; import org.apache.ibatis.cursor.Cursor; public interface ResultSetHandler { List handleResultSets(Statement var1) throws SQLException; Cursor handleCursorResultSets(Statement var1) throws SQLException; void handleOutputParameters(CallableStatement var1) throws SQLException; }

各个接口中的实现功能大概就和table描述一致我们只要根据业务去针对性的进行拦截处理就可以


基于mybatis plus写的一个简单的租户分割
@Slf4j @Intercepts({@Signature( type = StatementHandler .class, method = "prepare", args = {Connection.class, Integer.class})}) public class MyBatisInterceptor extends AbstractSqlParserHandler implements Interceptor {public MyBatisInterceptor() { }/** * 代理对象每次调用的方法,就是要进行拦截的时候要执行的方法。在这个方法里面做我们自定义的逻辑处理 * * * 等于是重写这个方法了 把参数拿过来然后返回原方法的result * * */ @Override public Object intercept(Invocation invocation) throws Throwable { StatementHandler statementHandler = PluginUtils.realTarget(invocation.getTarget()); //映射工具 MetaObject metaObject = SystemMetaObject.forObject(statementHandler); //中间去判断多层 this.sqlParser(metaObject); MappedStatement mappedStatement = (MappedStatement)metaObject.getValue("delegate.mappedStatement"); //要是查询操作并且 要求 StatementType 非存储过程(属于jDBCStatement(非预编译) prepareStatement(预编译) CallableStatement 调用存储过程的statement) if(SqlCommandType.SELECT == mappedStatement.getSqlCommandType() && StatementType.CALLABLE != mappedStatement.getStatementType()){ //获取到执行的sql BoundSql boundSql = (BoundSql)metaObject.getValue("delegate.boundSql"); HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); String tentId = request.getHeader("tentId"); String originalSql = boundSql.getSql(); //可能出现sql 注入验证下参数 metaObject.setValue("delegate.boundSql.sql",originalSql +"and tent_id = " +tentId); } return invocation.proceed(); }/** * plugin方法是拦截器用于封装目标对象的,通过该方法我们可以返回目标对象本身,也可以返回一个它的代理 * * 当返回的是代理的时候我们可以对其中的方法进行拦截来调用intercept方法 -- Plugin.wrap(target, this) * 当返回的是当前对象的时候 就不会调用intercept方法,相当于当前拦截器无效 */ @Override public Object plugin(Object target) { return target instanceof StatementHandler ? Plugin.wrap(target, this) : target; }/** * 用于在Mybatis配置文件中指定一些属性的,注册当前拦截器的时候可以设置一些属性 */ @Override public void setProperties(Properties properties) {} }

声明时候bean的加载顺序决定 plugin的加载顺序,在springboot + mybatis plus中我的写法
/** * @author chenkang */ @Configuration @MapperScan(value = https://www.it610.com/article/{"com.chenkang.tenant.mapper"}) public class MybatisPlusConfig {@Bean @Order(1) public PaginationInterceptor paginationInterceptor() { return new PaginationInterceptor(); }@Bean @Order(2) public MyBatisInterceptor myBatisInterceptor() { return new MyBatisInterceptor(); }}





【mybatisPlus|mybatis 拦截器(实现简单多租户 + 整合 mybatis plus 不影响分页插件 )】

相关内容

热门资讯

a... 本文目录导航: abaqus振动照应剖析中处罚力的加载方法 abaqus反...
a... 本文目录导航: abaqus资料可以不设置参数吗 abaqus外面没有自带...
A... 本文目录导航: ANSYS Workbench中二维平面剖析的设置。 an...
h... 本文目录导航: hfss19.2允许win11吗 微带如何假负载 ...
a... 本文目录导航: ansys模流剖析用哪个模块 Ansys_workbenc...
v... 本文目录导航: 在ansys中,建好几何模型后,随意变动一下视图,旋转、加大、增加,Fit...
A... 本文目录导航: Ansys软件可以收费试用吗? ansys有哪些软件 ...
a... 本文目录导航: abaqus中如何同时关上两个cae文件? abaqus找...
a... 本文目录导航: ansys流体剖析迭代次数可以中止嘛 Ansys Flot...
这... 本文目录导航: 哪位大佬有 Fluent14.5流场剖析从入门到知晓,这种百度网盘资源的链...
经... 双击D2进入System Coupling的设置,在Solution上右击选用Clear Gener...
a... 本文目录导航: ansys软件引见 ansys有哪些软件 ...
a... 本文目录导航: abaqus系列技巧18:聊聊abaqus云图外面的魔术加大镜--缩放倍数...
a... 本文目录导航: abaqus中网格不可绘制 abaqus结果可视化某个部件...
a... 本文目录导航: abaqus结果可视化某个部件云图只显示网格接壤处的? a...
驳... 本文目录导航: ABAQUS中假设选择施加的载荷类型为pressure,对应的载荷单位应该...
a... 本文目录导航: abaqus2020旋转不了物体 怎样判别abaqus转的...
在... 本文目录导航: 在abaqus中如何删除一个单元 ABAQUS怎样删除网格...
它... 本文目录导航: abaqus为什么叫abaqus,它是那些词的简称么?全称是什么呢? ...
披着“现货订购”外衣的非法期货...   近期,甘肃西北商品交易市场有限公司旗下的“铂银掘金APP”引发大量投资者集中维权。该平台打着“低...