SSM下Mybatis使用Redis作为二级缓存

    xiaoxiao2023-11-28  141

    Mybatis使用Redis作为二级缓存

    SSM整合在这里不在阐述了,可以看我另一篇帖子、里边也集成了redis、quartz等

    git地址:ssm+redis+quartz 博客地址:ssm blog

    框架整合之后,我们直接上代码使用redis作为mybatis的二级缓存

    首先我们在pom.xml添加依赖commons-codec,我们使用里边的一个方法,按照一定的规则生成key

    DigestUtils.md5Hex(key) <common-codec.version>1.12</common-codec.version> <dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <version>${common-codec.version}</version> </dependency> 我们新建一个类实现Cache接口,重写里边的方法 package com.bootdu.redis; import org.apache.commons.codec.digest.DigestUtils; import org.apache.ibatis.cache.Cache; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.ValueOperations; import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; /** * 使用Redis缓存作为Mybatis二级缓存 */ public class RedisCache implements Cache { //slf4j的日志记录器 private static final Logger logger = LoggerFactory.getLogger(RedisCache.class); //缓存对象唯一标识 private final String id; //orm的框架都是按对象的方式缓存,而每个对象都需要一个唯一标识. //用于事务性缓存操作的读写锁 private static ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); //处理事务性缓存中做的 //操作数据缓存的--跟着线程走的 public static RedisTemplate redisTemplate; //Redis的模板负责将缓存对象写到redis服务器里面去 //缓存对象的是失效时间,60分钟 private static final long EXPRIRE_TIME_IN_MINUT = 60; //生成key private final String COMMON_CACHE_KEY = "com:bootdu:"; /** * 所有key */ private String getKeys() { return COMMON_CACHE_KEY + this.id + ":*"; } /** * 按照一定规则标识key */ private Object getKey(Object key) { return COMMON_CACHE_KEY + this.id + ":" + DigestUtils.md5Hex(String.valueOf(key)); } public static void setRedisTemplate(RedisTemplate redisTemplate) { RedisCache.redisTemplate = redisTemplate; } //构造方法---把对象唯一标识传进来 public RedisCache(String id) { if (id == null) { throw new IllegalArgumentException("缓存对象id是不能为空的"); } this.id = id; } @Override public String getId() { return this.id; } //给模板对象RedisTemplate赋值,并传出去 public RedisTemplate getRedisTemplate() { return redisTemplate; } /* *保存缓存对象的方法 */ @Override public void putObject(Object key, Object value) { try { RedisTemplate redisTemplate = getRedisTemplate(); //使用redisTemplate得到值操作对象 ValueOperations operation = redisTemplate.opsForValue(); //使用值操作对象operation设置缓存对象 operation.set(getKey(key), value, EXPRIRE_TIME_IN_MINUT, TimeUnit.MINUTES); //TimeUnit.MINUTES系统当前时间的分钟数 logger.debug("缓存对象保存成功,key{}", getKey(key)); } catch (Throwable t) { logger.error("缓存对象保存失败" + t, getKey(key)); } } /* *获取缓存对象的方法 */ @Override public Object getObject(Object key) { try { RedisTemplate redisTemplate = getRedisTemplate(); ValueOperations operations = redisTemplate.opsForValue(); Object result = operations.get(getKey(key)); logger.debug("获取缓存对象", getKey(key)); return result; } catch (Throwable t) { logger.error("缓存对象获取失败" + t, getKey(key)); return null; } } /* 删除缓存对象 */ @Override public Object removeObject(Object key) { try { RedisTemplate redisTemplate = getRedisTemplate(); redisTemplate.delete(getKey(key)); logger.debug("删除缓存对象成功!", getKey(key)); } catch (Throwable t) { logger.error("删除缓存对象失败!" + t, getKey(key)); } return null; } /* 清空缓存对象 当缓存的对象更新了的化,就执行此方法 */ @Override public void clear() { RedisTemplate redisTemplate = getRedisTemplate(); //回调函数 Set<String> keys = redisTemplate.keys(getKeys()); redisTemplate.delete(keys); logger.debug("清空缓存对象成功!", keys); } //可选实现的方法 @Override public int getSize() { return 0; } @Override public ReadWriteLock getReadWriteLock() { return readWriteLock; } }

    6.我们要使用一个RedisTemplate,然后将它注入到我们上边的类,在redis.xml配置文件种配置

    <bean id="stringRedisSerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer"/> <bean id="redisTemplate_mybatis" class="org.springframework.data.redis.core.RedisTemplate"> <property name="connectionFactory" ref="redisConnectionFactory"></property> <property name="keySerializer" ref="stringRedisSerializer"></property> <property name="valueSerializer"> <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/> </property> </bean>

    7.我们构造一个类去注入redisTemplate

    package com.bootdu.redis; import org.springframework.data.redis.core.RedisTemplate; /** * 构造一个RedisTemplate注入 */ public class MybatisRedisCacheTransfer { public void setRedisTemplate(RedisTemplate redisTemplate) { RedisCache.setRedisTemplate(redisTemplate); } } ---------------------------------------------------------------------- redis.xml 将redisTemplate_mybatis 注入到这里 <!--注入--> <bean class="com.bootdu.redis.MybatisRedisCacheTransfer"> <property name="redisTemplate" ref="redisTemplate_mybatis"></property> </bean>

    我们在需要使用缓存的接口对应的mapper.xml种配置这个缓存实现类 <!--使用Redis缓存作为MyBatis二级缓存--> <cache type="com.bootdu.redis.RedisCache"/>

    测试:页面可以请求到 我们看下控制台:第一请求进来的时候,我们看到,在缓存中没有找到执行了查询,然后并缓存到redis里边 我们刷新请求下,再看控制台: 这次没有sql执行 而是直接去了缓存种查询了,看到这样,就成功了

    至此我们整合redis作为mybatis二级缓存已经完成了,思路:

    1:创建一个类实现Mybatis Cache接口,重写里边的方法 2:构造一个RedisTemplate 注入RedisTemplate 3:在mapper接口对应的xml文件种配置标签,type写我们Cache接口的实现类 Ps:注意,我们实体Po一定要实现序列化接口,不然在反序列化的时候要抱异常

    最新回复(0)