一·、简介
无意间了解到Mybatis也有拦截器,所以利用空闲时间了解了一下Mybatis拦截器的使用及一些应用场景。
二、拦截器介绍
Mybatis的拦截器是通过动态代理来实现的,Mybatis提供了Interceptor接口让用户自定义插件。但是Mybatis只提供了以下四个核心对象的拦截。
- Executor
这是Mybatis的执行器,用于执行增删改查的操作,还包含了提交、回滚的事务操作,开发者可以选择拦截其中任意方法,添加自己的功能。 - StatementHandler
StatementHandler负责具体编译并执行Sql语句,也就是说如果你想要在改变要执行的sql语句,就必须要在parpre方法执行前改变。 - ParameterHandler
ParameterHandler负责sql语句的参数映射。其中只有setParameters方法需要拦截,该方法负责将参数映射到占位符 - ResultSetHandler
ResultSetHandler负责处理sql的结果集。
这4个对象的执行顺序为Executor->StatementHandler->ParameterHandler->ResultSetHandler。
三、应用场景
Mybatis拦截器可以用来自定义分页功能,数据权限管理,监控sql执行性能等等。使用拦截器实现分页,权限管理,就不需要将分页sql,权限等业务需要硬编码到代码中。
四、Interceptor接口
public interface Interceptor {
Object intercept(Invocation invocation) throws Throwable;
Object plugin(Object target);
void setProperties(Properties properties);
}
Interceptor 接口是Mybatis提供给我们自定义拦截器的接口,其中有3个方法
1.intercept方法,这个方法就是我们用来实现自己业务逻辑的方法,Invocation 对象中包含了代理对象和被拦截方法的参数。调用Invocation 对象中的proceed()方法就可以继续执行目标方法。
2.plugin方法,这个方法是用来生成代理对象的,Mybatis会调用这个方法获取一个对象,执行目标方法。这个方法通常只需要调用Plugin类的wrap静态方法即可。如Plugin.wrap(target,this)。wrap方法的作用是通过反射获取拦截器注解,判断拦截器拦截的是否是Executor,StatementHandler,ParameterHandler,ResultSetHandler4个对象中的方法,是则返回代理对象,不是则返回目标对象。
3.setProperties方法用于获取配置文件中配置到拦截器中的属性。
例如:
<plugins>
<plugin interceptor="FrameWork.util.SqlInvocation">
<property name="name" value="knight"></property>
</plugin>
</plugins>
这样的功能使Mybatis在没有Spring的支持下也可以从配置文件中获取属性。
五、拦截器注解
Mybatis提供了@Intercepts和@Signature两个注解来指定拦截方法。
@Intercepts标识类是一个拦截器,其中可以包含多个@Signature。
@Signature定义了当前拦截器的切入点,该注解有3个参数,type代表拦截哪个类,method代表拦截的方法,args包含了被拦截方法中的参数。
六、自定义分页插件
package FrameWork.bean;
import java.util.HashMap;
/**
* Created by forget on 2019/9/29.
* 分页实体类
*/
public class Page {
//分页sql
private String sql;
//总页数
private Integer totalPage=0;
//当前页数,默认当前页数为1
private Integer indexPage=1;
//每页页数,默认页数为10
private Integer pageNum=10;
//查询参数
private HashMap<String,Object> params=new HashMap();
private int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getSql() {
return sql;
}
public void setSql(String sql) {
this.sql = sql;
}
public Integer getTotalPage() {
return totalPage;
}
public void setTotalPage(Integer total) {
this.totalPage = total%this.pageNum==0?total/this.pageNum:total/this.pageNum+1;
}
public Integer getIndexPage()