摘要:提供了一個(gè)入口,可以讓你在語(yǔ)句執(zhí)行過(guò)程中的某一點(diǎn)進(jìn)行攔截調(diào)用。
? ? ? ? mybatis提供了一個(gè)入口,可以讓你在語(yǔ)句執(zhí)行過(guò)程中的某一點(diǎn)進(jìn)行攔截調(diào)用。官方稱之為插件plugin,但是在使用的時(shí)候需要實(shí)現(xiàn)Interceptor接口,默認(rèn)情況下,MyBatis 允許使用插件來(lái)攔截的方法調(diào)用包括以下四個(gè)對(duì)象的方法:
以上內(nèi)容在官網(wǎng)包括網(wǎng)上一搜一大把,但是用的時(shí)候,應(yīng)該怎么選擇,什么時(shí)候用哪種,怎么入手呢?
? ? ? ? 我一開(kāi)始想用的時(shí)候,也不知道什么時(shí)候攔截哪種對(duì)象,后來(lái)我就寫(xiě)了一個(gè)簡(jiǎn)單的demo,大家在用mybatis的時(shí)候,無(wú)非就是crud操作,那么我就提供四個(gè)plugin,分別來(lái)攔截Executor、ParameterHandler、ResultSetHandler、StatementHandler ;然后提供了一個(gè)controller暴露了五個(gè)接口分別是getUserInfo、listUserInfo、addUser、updateUser、deleteUser,來(lái)看下都走了那幾個(gè)plugin(demo我會(huì)上傳到碼云上,項(xiàng)目架構(gòu)是springboot+mybatis+mybatis-plus,數(shù)據(jù)庫(kù)我用的是postgresql-14),我認(rèn)為這五個(gè)接口涵蓋了我們?cè)陂_(kāi)發(fā)中90%的場(chǎng)景,根據(jù)打印的日志得到的結(jié)論是:
所以根據(jù)上面的結(jié)論,我們就可以來(lái)確定我們?cè)陂_(kāi)發(fā)中用哪種plugin,參考場(chǎng)景如下:
下面結(jié)合代碼舉兩個(gè)場(chǎng)景的例子:
場(chǎng)景一:對(duì)查詢結(jié)果數(shù)據(jù)脫敏處理,首先定義了一個(gè)XfactorResultSetHandlerInterceptor,代碼如下:
package com.lhclab.xfactor.dal.wrapper;import java.lang.reflect.Field;import java.sql.Statement;import java.util.List;import org.apache.commons.codec.binary.StringUtils;import org.apache.ibatis.executor.resultset.ResultSetHandler;import org.apache.ibatis.plugin.Interceptor;import org.apache.ibatis.plugin.Intercepts;import org.apache.ibatis.plugin.Invocation;import org.apache.ibatis.plugin.Signature;import org.apache.ibatis.reflection.MetaObject;import org.apache.ibatis.reflection.SystemMetaObject;import lombok.extern.slf4j.Slf4j;@Slf4j@Intercepts({ @Signature(type= ResultSetHandler.class,method = "handleResultSets",args = {Statement.class}) })public class XfactorResultSetHandlerInterceptor implements Interceptor { @Override public Object intercept(Invocation invocation) throws Throwable { log.info("===ResultSetHandler==="); Object resultSet = invocation.proceed(); List resultList = (List)resultSet; for(Object item : resultList) { Class> sourceClass = item.getClass(); MetaObject metaObject = SystemMetaObject.forObject(item); Field[] fields = sourceClass.getDeclaredFields(); for(Field field : fields) { if(StringUtils.equals(field.getName(), "password")) { metaObject.setValue(field.getName(), "******"); } } } return resultSet; }}
plugin定義好以后,要想讓插件起作用,需要把插件加入到MybatisSqlSessionFactoryBean中,代碼如下(見(jiàn)標(biāo)黃的部分)
package com.lhclab.xfactor.dal.config;import javax.sql.DataSource;import org.apache.ibatis.session.SqlSessionFactory;import org.mybatis.spring.annotation.MapperScan;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;import org.springframework.boot.jdbc.DataSourceBuilder;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.core.io.support.PathMatchingResourcePatternResolver;import com.baomidou.mybatisplus.annotation.DbType;import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;import com.lhclab.xfactor.common.exception.XfactorRuntimeException;import com.lhclab.xfactor.dal.wrapper.XfactorExecutorInterceptor;import com.lhclab.xfactor.dal.wrapper.XfactorParameterHandlerInterceptor;import com.lhclab.xfactor.dal.wrapper.XfactorResultSetHandlerInterceptor;import com.lhclab.xfactor.dal.wrapper.XfactorStatementHandlerInterceptor;import com.zaxxer.hikari.HikariDataSource;import lombok.extern.slf4j.Slf4j;@Slf4j@Configuration@MapperScan("com.lhclab.xfactor.dal.dao")public class DataSourceConfig { @Autowired private DataSourceProperties properties; @Bean public DataSource dataSource() { log.info("數(shù)據(jù)庫(kù)連接池創(chuàng)建中......"); HikariDataSource dataSource = null; try { dataSource = DataSourceBuilder.create(properties.getClassLoader()) .type(HikariDataSource.class) .driverClassName(properties.determineDriverClassName()) .url(properties.determineUrl()) .username(properties.determineUsername()).password(properties.getPassword()) .build(); } catch (Exception e) { throw new XfactorRuntimeException("get password failed!", e); } return dataSource; } @Bean public SqlSessionFactory xfactorSqlSessionFactory() throws Exception { MybatisSqlSessionFactoryBean sqlSessionFactoryBean = new MybatisSqlSessionFactoryBean(); sqlSessionFactoryBean.setDataSource(dataSource());// sqlSessionFactoryBean.setPlugins(mybatisPlusInterceptor(), new AnalyseMybatisPluginsInterceptor()); sqlSessionFactoryBean.setPlugins(new XfactorResultSetHandlerInterceptor(), new XfactorParameterHandlerInterceptor(), new XfactorStatementHandlerInterceptor(), new XfactorExecutorInterceptor()); PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath*:mapper/*xml")); sqlSessionFactoryBean.setTypeAliasesPackage("com.lhclab.xfactor.dal.dao.entity"); return sqlSessionFactoryBean.getObject(); } @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.POSTGRE_SQL)); return interceptor; }}
場(chǎng)景二:更改查詢庫(kù)表的schema(場(chǎng)景類似于修改sql語(yǔ)句),首先定義了一個(gè)XfactorStatementHandlerInterceptor,代碼如下:
package com.lhclab.xfactor.dal.wrapper;import java.sql.Connection;import org.apache.ibatis.executor.statement.RoutingStatementHandler;import org.apache.ibatis.executor.statement.StatementHandler;import org.apache.ibatis.plugin.Interceptor;import org.apache.ibatis.plugin.Intercepts;import org.apache.ibatis.plugin.Invocation;import org.apache.ibatis.plugin.Signature;import org.apache.ibatis.reflection.MetaObject;import org.apache.ibatis.reflection.SystemMetaObject;import com.zaxxer.hikari.pool.HikariProxyConnection;import lombok.extern.slf4j.Slf4j;@Slf4j@Intercepts({ @Signature(type= StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class}),})public class XfactorStatementHandlerInterceptor implements Interceptor { @Override public Object intercept(Invocation invocation) throws Throwable { log.info("===StatementHandler==="); ((HikariProxyConnection)invocation.getArgs()[0]).setSchema("notes");//這里改schema //這里改sql,但是如果是對(duì)select的sql語(yǔ)句進(jìn)行修改,建議實(shí)現(xiàn)Executor.class的plugin中進(jìn)行,當(dāng)前方式改select語(yǔ)句insert/update/delete都會(huì)走這個(gè)判斷 MetaObject metaObject = SystemMetaObject.forObject(((RoutingStatementHandler)invocation.getTarget()).getBoundSql()); String execSql = (String) metaObject.getValue("sql"); if(execSql.startsWith("select ") || execSql.startsWith("SELECT ")) { metaObject.setValue("sql", execSql.concat(" order by id desc")); } return invocation.proceed(); }}
結(jié)合以上兩個(gè)場(chǎng)景可知,有些目的可以通過(guò)多個(gè)類型的plugin都能實(shí)現(xiàn),但是肯定有一個(gè)是最佳方案的(plugin定義好以后,要想讓插件起作用,需要把插件加入到MybatisSqlSessionFactoryBean中,代碼見(jiàn)加粗的部分)。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/123645.html
摘要:插件插件接口在中使用插件,我們必須實(shí)現(xiàn)接口。它將直接覆蓋你所攔截對(duì)象原有的方法,因此它是插件的核心方法。插件在對(duì)象中的保存插件的代理和反射設(shè)計(jì)插件用的是責(zé)任鏈模式,的責(zé)任鏈?zhǔn)怯扇ザx的。 插件 1、插件接口 在MyBatis中使用插件,我們必須實(shí)現(xiàn)接口Interceptor。 public interface Interceptor { // 它將直接覆蓋你所攔截對(duì)象原有的方法,因...
摘要:攔截器的使用場(chǎng)景主要是更新數(shù)據(jù)庫(kù)的通用字段,分庫(kù)分表,加解密等的處理。攔截器均需要實(shí)現(xiàn)該接口。攔截器攔截器的使用需要查看每一個(gè)所提供的方法參數(shù)。對(duì)應(yīng)構(gòu)造器,為,為,為??蓞⒖紨r截器原理探究。 攔截器(Interceptor)在 Mybatis 中被當(dāng)做插件(plugin)對(duì)待,官方文檔提供了 Executor(攔截執(zhí)行器的方法),ParameterHandler(攔截參數(shù)的處理),Re...
摘要:剛學(xué)習(xí)攔截器方面,在網(wǎng)上找了很多關(guān)于攔截器方面的文章,自己也嘗試過(guò)寫(xiě)過(guò)幾個(gè),但是關(guān)于結(jié)果集的攔截始終沒(méi)有找到合適的不要噴我,畢竟是新手。 剛學(xué)習(xí)Mybatis攔截器方面,在網(wǎng)上找了很多關(guān)于Mybatis攔截器方面的文章,自己也嘗試過(guò)寫(xiě)過(guò)幾個(gè),但是關(guān)于結(jié)果集的攔截始終沒(méi)有找到合適的(PS: 不要噴我,畢竟是新手)。也在segmentfault 上提問(wèn)過(guò),依然沒(méi)有找到一個(gè)易于理解的,后來(lái)自...
摘要:使用這個(gè)類庫(kù)中的類將會(huì)加載必要的工廠類和類。最終它并不會(huì)依賴于或來(lái)構(gòu)建應(yīng)用程序代碼。下面對(duì)各部分作用總結(jié)下。和無(wú)縫整合的機(jī)制和的認(rèn)識(shí)在講如何無(wú)縫整合進(jìn)之前,我們先認(rèn)識(shí)下和這兩個(gè)接口的作用。附上上篇博文地址原理概括。 前言 本篇是繼上篇MyBatis原理概括延伸的,所以如果有小伙伴還沒(méi)看上篇博文的話,可以先去看下,也不會(huì)浪費(fèi)大家太多的時(shí)間,因?yàn)楸酒獣?huì)結(jié)合到上篇敘述的相關(guān)內(nèi)容。 好,切入正...
閱讀 1595·2023-04-25 19:00
閱讀 4336·2021-11-17 17:00
閱讀 1949·2021-11-11 16:55
閱讀 1708·2021-10-14 09:43
閱讀 3303·2021-09-30 09:58
閱讀 1007·2021-09-02 15:11
閱讀 2256·2019-08-30 12:56
閱讀 1543·2019-08-30 11:12