Mybatis插件介绍
Mybatis
作为优秀的开源框架,本身具有非常强大的灵活性,在四大组件Executor
,StatementHandler
,ParamterHandler
,ResultSetHandler
处提供了简单易用的插件扩展机制。Mybatis
对持久层的操作就借助于这四大组件,并且支持插件对四大组件进行拦截,插件的本质就是拦截器,用来增强功能,增强功能本质上是通过动态代理实现,换句话说,Mybatis
的四大对象都是代理对象。
四大组件的结构图:
Mybatis
所有允许拦截的方法如下:
- 执行器Executor (update、query、commit、rollback等方法);
- SQL语法构建器StatementHandler (prepare、parameterize、batch、updates query等方 法);
- 参数处理器ParameterHandler (getParameterObject、setParameters方法);
- 结果集处理器ResultSetHandler(handleResultSets、handleOutputParameters等方法);
插件执行原理
MyBatis
在启动时可以加载插件,并保存插件实例到相关对象(InterceptorChain
,拦截器链) 中。待准备工作做完后,MyBatis
处于就绪状态。我们在执行SQL
时,需要先通过DefaultSqlSessionFactory
创建SqlSession
。Executor
实例会在创建 SqlSession
的过程中被创建,Executor
实例创建完毕后,MyBatis
会通过JDK
动态代理为实例生成代理类。这样,插件逻辑即可在Executor
相关方法被调用前执行。
自定义拦截器
自定义拦截器核心就是我们自定义一个类实现Interceptor
接口,并实现里边的关键方法:
Intercept
方法,插件的核心方法plugin
方法,生成target
的代理对象setProperties
方法,传递插件所需参数
1.在之前项目的基础上定义MyPlugin.java
类
@Intercepts({
//注意看这个大花括号,也就这说这里可以定义多个@Signature对多个地方拦截,都用这个拦截器
@Signature(type = StatementHandler.class,method = "prepare", args = {Connection.class, Integer.class})
})
public class MyPlugin implements Interceptor {
/**
* 拦截方法:只要被拦截得目标对象的目标方法被执行时,该方法就会执行
*/
@Override
public Object intercept(Invocation invocation) throws Throwable {
System.out.println("自定义逻辑,对方法进行了增强");
return invocation.proceed();
}
/**
* 将当前的拦截器生成代理对象存到拦截器链中
*/
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
/**
* 获取配置文件参数
*/
@Override
public void setProperties(Properties properties) {
System.out.println("获取到的配置文件的参数是:"+properties);
}
}
这里主要介绍@Signature
的三个属性
type
:指拦截哪个接口method
: 指拦截哪个具体的方法args
:声明该方法的参数,必须按接口定义的顺序写,主要为了在有方法重载的情况下精确定位到我们要拦截的方法
- 在
sqlMapConfig.xml
中注册我们自定义的插件:
<plugins>
<plugin interceptor="com.lagou.plugin.MyPlugin">
<!-- 设置参数,这里随便定义的 -->
<property name="name" value="tom"/>
</plugin>
</plugins>
这里我们自定义的插件只是简单的在控制台打印了一句话,并没有做什么具体的逻辑,只是为了演示效果,接下来我们随便运行一个查询方法,查看结果:
首先是插件初始化阶段,控制台先打印了我们定义的参数:
然后我们拦截的是查询方法,所以我们具体的增强逻辑是在我们只想查询动作之前进行的:
可以看出我们的增强逻辑是在执行sql
语句之前执行的。
常用插件介绍
pageHelper分页插件
分页助手PageHelper
是将分页的复杂操作进行封装,使用简单的方式即可获得分页的相关数据,极大的简化开发。
- 首先在
pom.xml
中添加依赖
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>3.7.5</version>
</dependency>
<dependency>
<groupId>com.github.jsqlparser</groupId>
<artifactId>jsqlparser</artifactId>
<version>0.9.1</version>
</dependency>
- 在
mybatis
核心配置文件sqlMapConfig.xml
中注册PageHelper
插件
<plugins>
<plugin interceptor="com.github.pagehelper.PageHelper">
<property name="dialect" value="mysql"/>
</plugin>
</plugins>
- 具体使用方法,新建
PageHelperTest.java
测试类
public class PageHelperTest {
private UserMapper userMapper;
@Before
public void before() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession(true);
userMapper = sqlSession.getMapper(UserMapper.class);
}
@Test
public void pageHelperTest() throws IOException {
//设置分页参数
PageHelper.startPage(2, 3);
List<User> userList = userMapper.findAll();
for (User user : userList) {
System.out.println(user);
}
PageInfo<User> userPageInfo = new PageInfo<User>(userList);
System.out.println("总条数:"+userPageInfo.getTotal());
System.out.println("总页数:"+userPageInfo.getPages());
System.out.println("当前页:"+userPageInfo.getPageNum());
System.out.println("每页展示条数:"+userPageInfo.getPageSize());
}
}
关键代码
PageHelper.startPage(2, 3);
必须放在我们的查询语句之前。
测试结果:
说明
文章内容输出来源:拉勾教育Java高薪训练营课程归纳总结