spring boot 实现mybatis拦截器

项目是个报表系统,服务端是简单的Java web架构,直接在请求参数里面加了个query id参数,就是mybatis mapper的query id,刚好对接接口的请求参数,没有使用接口模式。

基于这种特性,分页使用了PageHelper插件,但是只使用获取指定范围记录这部分,查询的总条数是自己实现的(插件的总条数,需要创建查询对象实现),直接在查询后多发送一次数据库请求,使用自定义的拦截器,拦截查询的请求(默认注入一个参数,等于指定值),在正常的SQL前后 拼接上 "select count(1) coun from (" +sql+")",直接在数据库中,查询结果集的条数。如下:

if ( mapParam.get("count") != null && mapParam.get("count").toString().equalsIgnoreCase("sum")) {
// 从StatementHandler中取出查询的SQL
String sql = (String) metaStatementHandler.getValue("delegate.boundSql.sql"); sql = "select count(1) coun from ( " + sql + " )";
// 将修改的SQL放回StatementHandler中
metaStatementHandler.setValue("delegate.boundSql.sql", sql);
}

mybatis的 拦截器配置如下:

<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<!-- 支持通过Mapper接口参数来传递分页参数 -->
<property name="supportMethodsArguments" value="true"/>
<property name="rowBoundsWithCount" value="true"/>
<property name="reasonable" value="true"/>
</plugin>
<!-- mybatis写出sql记录控件(拦截器) -->
<!-- 自己写的那个拦截器 -->
<plugin interceptor="com.xx.SqlInterceptorCount">
<!-- 方言 -->
<property name="dialect" value="oracle"/>
</plugin> </plugins>

Java使用如下:

// 从数据库查询
result = QueryMapper.getObjFromDB(paras.get("qdi"),paras);
// 查询当前sql 的总条数
total = QueryMapper.getQdiSum(paras.get("qdi"),paras);

查 total 的时候,给paras,默认注入一个count参数。

paras.put("count", "sum");
hashMap = (HashMap)session.selectList(qdi, paras).get(0);

用起来还是很酸爽的。

--------------朴素的分割线------------------

进入主题

为迎合时代的发展,领导的召唤,项目架构改版,迁入springboot,方便统一管理(监控)

程序员就开干了啊。。。

。。。

。。。

。。。

。。。

。。。

// 程序员挥汗如雨中

几天后,springboot的项目开发完了,但是遇到个问题,mybatis的拦截器不生效,配置如下:

mybatis:
mapper-locations: classpath:mapper/*.xml

事实上,并没有配置,不过可以加个mybatis的配置文件,像这样,如下:

mybatis:
mapper-locations: classpath:mapper/*.xml
configuration:
interceptions: cn.utstarcom.statplatform7.interceptor.SqlInterceptorCount
config-location: classpath:mybatis-config.xml

mbatis-config.xml 内容如下:

<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<!-- 支持通过Mapper接口参数来传递分页参数 -->
<property name="supportMethodsArguments" value="true"/>
<property name="rowBoundsWithCount" value="true"/>
<property name="reasonable" value="true"/>
</plugin>
<!-- mybatis写出sql记录控件(拦截器) -->
<!-- 自己写的那个拦截器 -->
<plugin interceptor="com..SqlInterceptorCount">
<!-- 方言 -->
<property name="dialect" value="oracle"/>
</plugin> </plugins>

拦截器内容如下:

@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
public class SqlInterceptorCount implements Interceptor { private Logger logger = LoggerFactory.getLogger(SqlInterceptorCount.class);
private static final ObjectFactory DEFAULT_OBJECT_FACTORY = new DefaultObjectFactory();
private static final ObjectWrapperFactory DEFAULT_OBJECT_WRAPPER_FACTORY = new DefaultObjectWrapperFactory();
private static final ReflectorFactory DEFAULT_REFLECTOR_FACTORY = new DefaultReflectorFactory(); @Override
public Object intercept(Invocation invocation) throws Throwable { try {
StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
MetaObject metaStatementHandler = MetaObject.forObject(statementHandler, DEFAULT_OBJECT_FACTORY,
DEFAULT_OBJECT_WRAPPER_FACTORY, DEFAULT_REFLECTOR_FACTORY); // HashMap mapParam = (HashMap) metaStatementHandler.getValue("delegate.boundSql.parameterObject");
Object paramObject = metaStatementHandler.getValue("delegate.boundSql.parameterObject");
if (paramObject instanceof Map) {
HashMap paramMap = (HashMap)paramObject;
if (paramMap.get("count") != null && paramMap.get("count").toString().equalsIgnoreCase("sum")) {
// get sql from StatementHandler
String sql = (String) metaStatementHandler.getValue("delegate.boundSql.sql");
sql = "select count(1) coun from ( " + sql + " )";
// set moidfy sql to StatementHandler
metaStatementHandler.setValue("delegate.boundSql.sql", sql);
}
}
} catch (Exception e) {
logger.error("throw exception and will not handle the mybatis sql");
}
// process the next query process
return invocation.proceed();
} /**
*
* @param o
* @return
*/
@Override
public Object plugin(Object o) { return null
;
}
@Override
public void setProperties(Properties properties) { }
}

事实上,mybatis的配置文件和配置的 interceptions,不能使用(我当然知道是),启动没有问题,数据库也可以操作,但是拦截器没有生效

1、在又是一大圈的乱找,发现个说法,在拦截器上加个  @Component 注解就可以了。

然后,还是不行,这个更惨,只要查询数据库,都会返回个null ,又没有报错信息,只是个null

2、又是网上一通乱找,看到个说法:说拦截器只有 plugin方法执行了,intercept方法没有执行

debug 一下,发现问题了,加上@Component 注解,plugin方法执行了,返回个null,知道为什么吗,看下plugin的代码:

@Override
public Object plugin(Object o) { return null;
}

我去

不返回null,返回什么

不返回null,返回什么

不返回null,返回什么

之后接简单了,plugin 方法是实现 Interceptor 接口的时候,IDEA生成的方法,有个默认实现,返回null

改改:

 @Override
public Object plugin(Object o) { // logger.info("Interceptor : SqlInterceptorCount is running, but this is plugin method not intercept method");
/*
use Intercepts annotation,intercept StatementHandler method prepare
*/
if (o instanceof StatementHandler) {
return Plugin.wrap(o, this);
}
return o;
}

在传入对象是 STATEMENTHandler的对象的时候,把方法转发到intercept 方法,拦截器可以正常执行了。

结论就是:

  springboot下的mybatis拦截器,和单独用mybatis的拦截器一样,但是不需要配置,直接在拦截器前面加个@Component 注解,在plugin 方法中将请求转发到intercept方法拦截即可,不需要其他配置。

完整代码如下:

@Component
@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
public class SqlInterceptorCount implements Interceptor { private Logger logger = LoggerFactory.getLogger(SqlInterceptorCount.class);
private static final ObjectFactory DEFAULT_OBJECT_FACTORY = new DefaultObjectFactory();
private static final ObjectWrapperFactory DEFAULT_OBJECT_WRAPPER_FACTORY = new DefaultObjectWrapperFactory();
private static final ReflectorFactory DEFAULT_REFLECTOR_FACTORY = new DefaultReflectorFactory(); @Override
public Object intercept(Invocation invocation) throws Throwable { try {
StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
MetaObject metaStatementHandler = MetaObject.forObject(statementHandler, DEFAULT_OBJECT_FACTORY,
DEFAULT_OBJECT_WRAPPER_FACTORY, DEFAULT_REFLECTOR_FACTORY); // HashMap mapParam = (HashMap) metaStatementHandler.getValue("delegate.boundSql.parameterObject");
Object paramObject = metaStatementHandler.getValue("delegate.boundSql.parameterObject");
if (paramObject instanceof Map) {
HashMap paramMap = (HashMap)paramObject;
if (paramMap.get("count") != null && paramMap.get("count").toString().equalsIgnoreCase("sum")) {
// get sql from StatementHandler
String sql = (String) metaStatementHandler.getValue("delegate.boundSql.sql");
sql = "select count(1) coun from ( " + sql + " )";
// set moidfy sql to StatementHandler
metaStatementHandler.setValue("delegate.boundSql.sql", sql);
}
}
} catch (Exception e) {
logger.error("throw exception and will not handle the mybatis sql");
}
// process the next query process
return invocation.proceed();
} /**
*
* @param o
* @return
*/
@Override
public Object plugin(Object o) { // logger.info("Interceptor : SqlInterceptorCount is running, but this is plugin method not intercept method");
/*
use Intercepts annotation,intercept StatementHandler method prepare
*/
if (o instanceof StatementHandler) {
return Plugin.wrap(o, this);
}
return o;
} @Override
public void setProperties(Properties properties) { }
}

最新文章

  1. 设置UITableView的separatorInset值为UIEdgeInsetsZero,分隔线不最左端显示的问题
  2. Quartz2D 画大白
  3. 阿里云SLB后Nginx、Tomcat获取真实IP
  4. 当我们安装使用时,会出现eclipse启动不了,出现“Java was started but returned exit code=13......”的问题
  5. Android 优秀的开源框架整理
  6. hdu 1181 变形课
  7. stage划分
  8. Machine Learning 学习笔记 (4) —— 广义线性模型
  9. python+selenium浏览器调用(chrome、ie、firefox)
  10. IOS学习之路十二(UITableView下拉刷新页面)
  11. JDBC 学习笔记(二)—— 大数据+存储过程+批处理+事务管理
  12. TortoiseGit disconnected: no supported authentication methods available(server sent:publickey)
  13. [Bootstrap] 1. container &amp; container-fluid
  14. CBO学习笔记(转)
  15. Android EditText 取消复制粘贴功能,取消横向全屏编辑功能(一)
  16. 【转】svn cleanup failed–previous operation has not finished; run cleanup if it was interrupted
  17. PPLB条码打印
  18. php实现监控在线服务应用程序小栗子
  19. 关于C语言文件操作
  20. spark升级后 集成hbase-1.0.0-cdh5.4.5异常

热门文章

  1. e-olymp Problem9 N-digit numbers(打表)
  2. 数据存储 共享参数 SharedPreferences
  3. 从零开始写bootloader(2)
  4. 微信小程序开发——前端如何区分小程序运行环境
  5. 在别家网站上执行自己的js代码(谷歌浏览器)(谷歌扩展程序)
  6. 13-算法训练 P0505
  7. node.js中module模块的理解
  8. Aspose.Words三 创建表格
  9. 微软官方的.net开发人员代码示例
  10. 在Qt(C++)中与Python混合编程