概述
拦截器:我们可以拦截某些方法的调用,我们可以选择在这些被拦截的方法执行前后加上某些逻辑,也可以在执行这些被拦截的方法时执行自己的逻辑而不再执行被拦截的方法。
Mybatis拦截器:就是为了供用户在某些时候可以实现自己的逻辑而不必去动Mybatis固有的逻辑。默认情况下,MyBatis 允许使用插件来拦截的方法调用包括:
Executor (update, query, flushStatements, commit, rollback,
getTransaction, close, isClosed)
ParameterHandler (getParameterObject, setParameters)
ResultSetHandler (handleResultSets, handleOutputParameters)
* StatementHandler (prepare, parameterize, batch, update, query)
Mybatis 提供的Interceptor接口
对于拦截器Mybatis为我们提供了一个Interceptor接口,通过实现该接口就可以定义我们自己的拦截器。我们先来看一下这个接口的定义:
public interface Interceptor {
Object intercept(Invocation invocation) throws Throwable;
Object plugin(Object target);
void setProperties(Properties properties);
}
Interceptor接口提供三个方法:
- plugin方法是拦截器用于封装目标对象的,通过该方法我们可以返回目标对象本身,也可以返回一个它的代理。
- 当返回的是代理的时候我们可以对其中的方法进行拦截来调用intercept方法,当然也可以调用其他方法,这点将在后文讲解。
- setProperties方法是用于在Mybatis配置文件中指定一些属性的。
- 定义自己的Interceptor最重要的是要实现plugin方法和intercept方法,在plugin方法中我们可以决定是否要进行拦截进而决定要返回一个什么样的目标对象。而intercept方法就是要进行拦截的时候要执行的方法。
不想介绍的太多,实践出真理
自定义插件
需求设计
把Mybatis所有执行的sql都记录下来。
代码实现
通过对 MyBatis org.apache.ibatis.executor.statement.StatementHandler 中的prepare 方法进行拦截即可。
自定义一个类,实现 org.apache.ibatis.pluginInterceptor 接口,代码如下:
package com.shxt.interceptor;
import java.sql.Connection;
import java.util.Properties;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.log4j.Logger;
@Intercepts(@Signature(type=StatementHandler.class,method="prepare",args={Connection.class, Integer.class}))
public class SQLStatsInterceptor implements Interceptor {
private final Logger logger = Logger.getLogger(this.getClass());
@Override
public Object intercept( Invocation invocation ) throws Throwable {
StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
BoundSql boundSql = statementHandler.getBoundSql();
String sql = boundSql.getSql();
this.logger.info("mybatis intercept sql:" + sql);
return invocation.proceed();
}
@Override
public Object plugin( Object target ) {
return Plugin.wrap(target, this);
}
@Override
public void setProperties( Properties properties ) {
String dialect = properties.getProperty("dialect");
this.logger.info("mybatis intercept dialect:"+ dialect);
}
}
这样一个插件就开发完成了,接下来需要在 mybatis-config.xml 文件中增加 plugins节点,完整配置如下:
<?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>
<!-- 加载属性文件 -->
<properties resource="jdbc.properties"/>
<plugins>
<plugin interceptor="com.shxt.interceptor.SQLStatsInterceptor">
<property name="dialect" value="mysql" />
</plugin>
</plugins>
<!-- 配置数据库的环境 -->
<environments default="development">
<environment id="development">
<!-- 事务管理器:保证数据的完整性和一致性 -->
<!-- 框架:默认情况下CUD操作需要手动提交事务 -->
<transactionManager type="JDBC" />
<!-- 使用的是连接池:百度Java如何实行连接池的原理? -->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.mysql.driver}" />
<property name="url" value="${jdbc.mysql.url}" />
<property name="username" value="${jdbc.mysql.username}" />
<property name="password" value="${jdbc.mysql.password}" />
</dataSource>
</environment>
</environments>
<!-- 加载映射文件 -->
<mappers>
<mapper resource="com/shxt/model/SkillMapper.xml"/>
</mappers>
</configuration>
配置Log4J属性文件
在这里我参考了网上的一些资料
# Global logging configuration
log4j.rootLogger=info,stdout,database
# MyBatis logging configuration...
# 如果显示SQL语句,那么这个位置需要配置为命名空间
# log4j.logger.com.shxt.model.Skill=TRACE
# 控制台输出
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
### 把日志信息写入到数据库###
log4j.appender.database=org.apache.log4j.ConsoleAppender
log4j.appender.database.layout=org.apache.log4j.PatternLayout
log4j.appender.database.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss:SSS}[%p]: %m%n
log4j.appender.database=org.apache.log4j.jdbc.JDBCAppender
log4j.appender.database.driver=com.mysql.jdbc.Driver
log4j.appender.database.URL=jdbc:mysql://127.0.0.1:3306/cy42_mss?useUnicode=true&characterEncoding=UTF-8
log4j.appender.database.user=root
log4j.appender.database.password=shxt
log4j.appender.database.sql=INSERT INTO log (class,method,createtime,loglevel,msg) VALUES ('%C','%M','%d{yyyy-MM-dd hh:mm:ss}','%p','%m')
log4j.appender.database.layout=org.apache.log4j.PatternLayout
计划是后面讲解一下MyBatis的分页拦截器