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 不影响分页插件 )】

相关内容

热门资讯

超... 本文目录导航: 超级云计算是什么 怎么做难看的PPT 1、...
谢... 本文目录导航: 请问云主机是什么 云主机有什么好处 具体的教程,谢谢! 云...
w... 本文目录导航: wps是什么意思 ppt的新配置designer和morp...
大... 本文目录导航: 大专学什么专业务工率高? 未来十年务工率最高的几大专业都是...
软... 本文目录导航: 软件技术专升本可以报什么专业 云计算专升本可以报医学吗 ...
云... 本文目录导航: 云计算务工前景 云计算务工方向及前景怎样样 ...
学... 本文目录导航: 学云计算进去无能嘛 云计算技术与运行是干什么的 ...
中... 本文目录导航: 如何了解云计算,中国的云计算产业开展现状如何 云计算未来几...
云... 本文目录导航: 云计算1+x证书含金量 云计算须要考什么证书 ...
云... 本文目录导航: 云计算股票龙头股票有哪些? 普通云计算概念龙头股有哪些?...
大... 本文目录导航: 大专云计算技术运行务工方向 大专毕业证上是物联网,实践学习...
大... 本文目录导航: 大数据云计算有必要升本吗 内蒙古大专云计算技术与运行专业升...
9... 本文目录导航: 99%学霸假期逆袭必看网站 99%学霸假期逆袭必看网站 ...
云... 本文目录导航: 云计算属于哪个专业 云计算属于什么专业 计...
计... 本文目录导航: 计算机二级MSOffice上机操作题及答案 想做一篇关于解...
A... 本文目录导航: AI能否会彻底扭转上流职业市场,如律师、会计师和医师? A...
人... 本文目录导航: 人工智能芯片产业链有哪些? 更多本行业钻研剖析详见前瞻产业...
人... 本文目录导航: 人工智能会带来哪些风险? 或许有一天,人工智能机器人将取代...
a... 本文目录导航: ai智能写作软件哪个好 ai智能写作软件有哪些?ai智能对...
自... 本文目录导航: 自考本科计算机专业难吗 自考计算机专业须要考哪些科目 ...