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

相关内容

热门资讯

大浪淘金APP黑幕揭秘:内盘操...   大浪淘金APP平台最隐蔽的黑幕,在于其完全封闭的内盘交易系统。这个看似与国际市场接轨的交易平台,...
告别固定工资实现财富自由?一品...   普通投资者被广告宣传诱导,注册就送现金,充值返现金券等等这些宣传方式,都是在引流到平台开户,不怕...
哈易购APP打着现货交易幌子搞...   网络上各类白银、铂金等贵金属投资广告铺天盖地,不少平台以"现货交易"为名,暗中却从事着非法期货交...
5元起投!高额收益?中国白银、...   上海华通白银国际交易中心有限公司(以下简称“华通白银国际”)打着“白银、铂金现货订购”的旗号,实...
"九州订购APP、起...   近年来,贵金属投资热度持续攀升,但乱象也随之而来。一些不法分子趁机搭建虚假交易平台,打着"低门槛...
坚锅淘金APP投资者频繁爆仓亏...   坚锅淘金APP对外宣称是贵金属现货交易平台,日常出入金看似畅通无阻,给人一种合规运营的假象。但事...
斗金订购APP“5元订购现货”...   斗金订购APP“5元订购现货”骗局揭秘:充值易、回本难,越陷越深!  许多投资人在未核实平台合规...
贵金属APP乱象曝光:&quo...   当前市场上部分贵金属类APP未取得正规交易资质,涉嫌误导消费者参与白银、铂金等商品的非合规交易!...
华通白银、银宝街APP被指虚假...   警惕现货白银投资陷阱:上海华通白银背后的平台涉嫌非法期货交易  近年来,各类现货白银交易平台以“...
充值送300,月入过万?别被量...   如今,网络上充斥着大量未经批准的贵金属及其他产品订购交易平台。这些平台普遍缺乏合法经营资质,却将...
鑫汇智投APP贵金属非法期货、...   鑫汇智投APP贵金属非法期货、人为控盘,大量投资者遭恶意收割  鑫汇智投APP长期以“低门槛、高...
矅光智策APP非法贵金属交易骗...   不少投资人在矅光智策APP上进行贵金属交易后出现了严重亏损。许多人在下载该平台时,根本不清楚其是...
飞鸽订购APP非法期货交易骗局...   飞鸽订购APP非法期货交易骗局,很多投资者根本没搞懂规则就盲目充值,买涨买跌跟买cai票一样!平...
天龙白银APP被操控的非法期货...   中小投资者在网络平台参与商品现货订购交易,表面看似合规合法,实则暗藏诸多难以察觉的风险。商品现货...
下载送试玩金?千万别碰!带你揭...   当前,许多贵金属APP交易平台正采用欺诈性营销手段。它们通过抖音等短视频平台,以“5元起投”“充...
泡泡淘金APP骗局:打着&qu...   泡泡淘金APP骗局:打着"商品订购"幌子,实则非法期货收割投资者!投资需谨慎,切勿轻信“高额回报...
南商云购APP虚假电子盘背后的...   南商云购是虚假电子盘吗?它是否具备合规的交易资质?这个曾经的"现货电子盘"如今摇身一变,披上了"...
警惕"祥龙订购&qu...   祥龙订购APP、掌上银牛APP等平台背后的运营方——四川禄宏商品现货市场有限公司,仅具备现货交易...
中国白银、华银:虚假宣传、后台...   中国白银APP宣称是上市公司“中国白银集团”与“上海华通白银国际交易中心”旗下的现货交易平台,提...
起底“优品订购”APP非法期货...   “优品订购”APP根本不具备任何合法的交易资质。其背后的运营方仅凭随便注册一家公司、开发一款交易...