mybatis拦截器的使用(输出日志或sql语句)

原创 2016年08月28日 14:52:48

拦截器的一个作用就是我们可以拦截某些方法的调用,我们可以选择在这些被拦截的方法执行前后加上某些逻辑,也可以在执行这些被拦截的方法时执行自己的逻辑而不再执行被拦截的方法。Mybatis拦截器设计的一个初衷就是为了供用户在某些时候可以实现自己的逻辑而不必去动Mybatis固有的逻辑。mybatis拦截器一般用于分页插件、输出日志、sql等。使用的方法如下:

首先要实现mybatis的Interceptor接口,

实现它的三个方法:

Object intercept(Invocation invocation) throws Throwable;

Object plugin(Object target);

void setProperties(Properties properties);
plugin方法是拦截器用于封装目标对象的,通过该方法我们可以返回目标对象本身,也可以返回一个它的代理。当返回的是代理的时候我们可以对其中的方法进行拦截来调用intercept方法,当然也可以调用其他方法,这点将在后文讲解。

setProperties方法是用于在Mybatis配置文件中指定一些属性的。

plugin方法中我们可以决定是否要进行拦截进而决定要返回一个什么样的目标对象。而intercept方法就是要进行拦截的时候要执行的方法。

下面例子本来相用于记录日志到数据库,但是由于mybatis底层无法注入spring的对象,所以,只能用于输出日志。

@Intercepts({@Signature(method = "update", type = Executor.class, args = {MappedStatement.class, Object.class})})
public class LogInterceptor implements Interceptor {
    /**
     * 注解拦截接口的方法
     * Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
     * ParameterHandler (getParameterObject, setParameters)
     * ResultSetHandler (handleResultSets, handleOutputParameters)
     * StatementHandler (prepare, parameterize, batch, update, query)
     */

    private static final Logger LOGGER = LoggerFactory.getLogger(LogInterceptor.class);

    private Properties properties;

    public Object intercept(Invocation invocation) throws Throwable {
        Object[] args = invocation.getArgs();
        // 获取执行的方法
        if (args.length > 1) {
            // 传入的对象
            Object obj = args[1];
            if (obj instanceof Log) {
                // 若是日志对象 则直接跳过
                return invocation.proceed();
            }
            saveLog(args[0], obj);
        }
        return invocation.proceed();
    }

    private void saveLog(Object arg, Object obj) {
        Log log = new Log();
        log.setCreateTime(DateUtils.now());
        log.setModifyTime(DateUtils.now());
        MappedStatement mappedStatement = (MappedStatement) arg;
        // 执行的方法名
        String name = mappedStatement.getSqlCommandType().name();
        String change = JsonMapper.toJson(obj);
        if (name.startsWith("INSERT")) {
            log.setType("新增" + obj.getClass().getSimpleName());
            log.setNewContent(change);
        } else if (name.startsWith("UPDATE")) {
            log.setType("修改" + obj.getClass().getSimpleName());
            log.setNewContent(change);
        } else if (name.startsWith("DELETE")) {
            log.setType("删除" + obj.getClass().getSimpleName());
            log.setOldContent(change);
        }

        LOGGER.info("----------------------------------------------");
        LOGGER.info(JsonMapper.toJson(log));
        LOGGER.info("----------------------------------------------");
    }

    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    public void setProperties(Properties properties) {
        this.properties = properties;
    }

}
类上面必须添加@Intercepts注解,@Signature,代表拦截点,

@Intercepts({@Signature(method = "update", type = Executor.class, args = {MappedStatement.class, Object.class})})
method表示需要拦截的方法,mybatis有

update, query, flushStatements, commit, rollback, getTransaction, close, isClosed
方法,其中,update包括新增、修改、删除等方法,query用于查询,其它的基本用不到。

type表示拦截的接口类型,有Executor、StatementHandler、ParameterHandler和ResultSetHandler。

args表示拦截的参数类型,有MappedStatement、Object、RowBounds和ResultHandler等等.


        编写完拦截器,需要在配置文件中注册拦截器,在sqlMapConfig配置文件中加上

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
  <settings>
      <setting name="cacheEnabled" value="true"/>
      <setting name="lazyLoadingEnabled" value="true"/>
      <setting name="multipleResultSetsEnabled" value="true"/>
      <setting name="useColumnLabel" value="true"/>
      <setting name="useGeneratedKeys" value="false"/>
    </settings>
    
    <plugins>
        <plugin interceptor="com.tc.itfarm.commons.interceptor.LogInterceptor"></plugin>
    </plugins>
</configuration>
启动项目测试即可,输出的日志如下:

2016-08-28 14:48:02  [ http-apr-8888-exec-8:70630 ] - [ INFO ]  ----------------------------------------------
2016-08-28 14:48:02  [ http-apr-8888-exec-8:70634 ] - [ INFO ]  {"recordId":null,"type":"修改User","oldContent":null,"newContent":"{\"recordId\":1,\"username\":\"wdd\",\"telephone\":\"18888888888\",\"sex\":2,\"password\":null,\"age\":22,\"status\":1,\"address\":\"安徽灵璧1\",\"photo\":null,\"email\":\"asdds\",\"qq\":\"812908087\",\"nickname\":\"爱吃猫的鱼1\",\"registerTime\":null,\"modifyTime\":1472366881824}","userId":null,"username":null,"createTime":1472366881824,"modifyTime":1472366881824}
2016-08-28 14:48:02  [ http-apr-8888-exec-8:70634 ] - [ INFO ]  ----------------------------------------------

若要插入到数据库,必须new一个dao对象操作


版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

在mybatis执行SQL语句之前进行拦击处理

比较适用于在分页时候进行拦截。对分页的SQL语句通过封装处理,处理成不同的分页sql。 实用性比较强。 import java.sql.Connection; import java.sql.Pre...
  • hfmbook
  • hfmbook
  • 2014年12月17日 19:41
  • 41626

MyBatis拦截器动态修改SQL语句及参数值(场景:查询中字段值中特殊字符自动转义)

拦截器基础: 配置

mybatis 拦截器拦截所有sql

package org.geekworld.core.mybatis; import com.alibaba.fastjson.JSON; import org.apache.ibatis.cach...

mybatise自定义插件或者叫mybatise拦截器,动态修改sql语句

package com.teamsun.net.common.utils; import java.lang.reflect.Constructor; import java.util.Prope...

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

Mybatis使用拦截器自动分页实现/使用反射替换sql代码分页

本文章内容代码来自互联网,扒拉下来使用无参数的分页成功,但是带参数的分页就抛出异常。本代码解决了该异常。使用mysql成功。oracle 没有环境。没有测试。这个是改造之后的,最后有详细注释的版本。 ...

Mybatis拦截器实现SQL性能监控

http://www.cnblogs.com/hanfight/p/4752782.html

Mybatis拦截器实现SQL性能监控

Mybatis拦截器只能拦截四类对象,分别为:Executor、ParameterHandler、StatementHandler、ResultSetHandler,而SQL数据库的操作都是从Exec...

在mybatis执行SQL语句之前进行拦截处理

比较适用于在分页时候进行拦截。对分页的SQL语句通过封装处理,处理成不同的分页sql。 实用性比较强。 [java] view plain copy print? i...
  • amorym
  • amorym
  • 2017年02月22日 15:48
  • 366

Mybatis SQL拦截器实现

主要功能:通过log4j配置mybatis的打印,只能输出到控制台,而并非真正能够实现sql的获取,本文主要通过拦截器实现sql的拦截,进而对sql进行相应的操作。 起因:因项目需要,服务器要配成双机...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:mybatis拦截器的使用(输出日志或sql语句)
举报原因:
原因补充:

(最多只允许输入30个字)