二级缓存整合 Redis
目前我们实现的二级缓存是每个服务的,此时缓存是在单个服务器上,如果我们想要实现分布式缓存的话,此时我们就需要考虑 Redis 来做我们的缓存服务。
在 MyBatis 中,提供了一个针对 Cache 的接口,MyBatis 还提供了一个针对 Cache 接口的 Redis 实现类,该类存在在 myBatis-redis 包中。
pom.xml
<dependency>
<groupId>org.mybatis.caches</groupId>
<artifactId>mybatis-redis</artifactId>
<version>1.0.0-beta2</version>
</dependency>
编写代码
UserCacheMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="icu.wzk.mapper.UserCacheMapper">
<!--开启二级缓存-->
<cache type="org.mybatis.caches.redis.RedisCache"></cache>
<resultMap id="userMap" type="icu.wzk.model.WzkUser">
<result column="id" property="id"></result>
<result column="username" property="username"></result>
<result column="password" property="password"></result>
<result column="birthday" property="birthday"></result>
<collection property="orderList" ofType="icu.wzk.model.WzkOrder">
<result column="oid" property="id"></result>
<result column="ordertime" property="ordertime"></result>
<result column="total" property="total"></result>
</collection>
</resultMap>
<select id="findAll" resultMap="userMap" useCache="true">
select *,o.id oid from wzk_user u left join wzk_orders o on u.id=o.uid;
</select>
</mapper>
UserCacheMapper.java
public interface UserCacheMapper {
List<WzkUser> findAll();
}
redis.properties
redis.host=10.10.52.11
redis.port=31679
redis.connectionTimeout=5000
redis.password=
redis.database=0
测试代码
public class WzkicuCache05 {
public static void main(String[] args) throws IOException {
InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
.build(inputStream);
SqlSession sqlSession1 = sqlSessionFactory.openSession();
SqlSession sqlSession2 = sqlSessionFactory.openSession();
UserCacheMapper userCacheMapper1 = sqlSession1.getMapper(UserCacheMapper.class);
UserCacheMapper userCacheMapper2 = sqlSession2.getMapper(UserCacheMapper.class);
List<WzkUser> wzkUserList = userCacheMapper1.findAll();
for (WzkUser wu : wzkUserList) {
System.out.println(wu);
}
sqlSession1.close();
List<WzkUser> wzkUserList2 = userCacheMapper2.findAll();
for (WzkUser wu : wzkUserList2) {
System.out.println(wu);
}
sqlSession2.close();
}
}
运行结果
运行后可以看到数据正常输出,且代码运行多次后,请求都不会发出了,因为在 Redis 上缓存了。
源码分析
RedisCache 和其他的缓存方案基本是相似的,无非是实现了 Cache 接口,并使用 Jedis 操作缓存。
public final class RedisCache implements Cache {
private final String id;
private final JedisPool pool;
public RedisCache(final String id) {
if (id == null) {
throw new IllegalArgumentException("Cache instances require an ID");
}
this.id = id;
RedisConfig redisConfig = RedisConfigurationBuilder.getInstance().parseConfiguration();
pool = new JedisPool(
redisConfig,
redisConfig.getHost(),
redisConfig.getPort(),
redisConfig.getConnectionTimeout(),
redisConfig.getSoTimeout(),
redisConfig.getPassword(),
redisConfig.getDatabase(),
redisConfig.getClientName()
);
}
}
RedisCache 在启动的时候,由 MyBatis 的 CacheBuilder 创建,创建的方式很简单,就是调用 RedisCache 的带有 String 参数的构造方法,即 RedisCache(String id),而 RedisCache 的构造方法中,调用了 RedisConfigurationBuilder 来创建对象 RedisConfig 对象,并使用 RedisConfig 来创建 JedisPool。
RedisConfig 继承了 JedisPoolConfig,提供了多个参数:
private String host = Protocol.DEFAULT_HOST;
private int port = Protocol.DEFAULT_PORT;
private int connectionTimeout = Protocol.DEFAULT_TIMEOUT;
private int soTimeout = Protocol.DEFAULT_TIMEOUT;
private String password;
private int database = Protocol.DEFAULT_DATABASE;
private String clientName;
RedisConfig 对象是由 RedisConfigurationBuilder 创建的,从 classpath 下读取了 redis.properties 配置文件,并将该配置文件中内容设置到了 RedisConfig 对象中。
模板方法
在 RedisCache 中,有一个模板方法:
private Object execute(RedisCallback callback) {
Jedis jedis = pool.getResource();
try {
return callback.doWithRedis(jedis);
} finally {
jedis.close();
}
}
模板接口为 RedisCallback,接口中只实现了一个 doWithRedis 方法:
package org.mybatis.caches.redis;
import redis.clients.jedis.Jedis;
public interface RedisCallback {
Object doWithRedis(Jedis jedis);
}
总结
RedisCache 在启动的时候,由 MyBatis 的 CacheBuilder 创建。创建的方式是调用 RedisCache 的带有 String 参数的构造方法,即 RedisCache(String id)。RedisCache 的构造方法中,调用了 RedisConfigurationBuilder 来创建 RedisConfig 对象,并使用 RedisConfig 来创建 JedisPool。