作者 王勇

使用redis作为mybatis的二级缓存

... ... @@ -3,6 +3,7 @@ package com.sunyo.wlpt.message.bus.service;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.scheduling.annotation.EnableAsync;
... ... @@ -12,6 +13,7 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
/**
* @author 子诚
*/
@EnableCaching
@SpringBootApplication
@MapperScan("com.sunyo.wlpt.message.bus.service.mapper")
@EnableFeignClients
... ...
package com.sunyo.wlpt.message.bus.service.cache;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
/**
* @author 子诚
* Description:用来获取springboot创建好的工厂
* 时间:2020/8/6 9:31
*/
@Component
public class ApplicationContextUtils implements ApplicationContextAware {
/**
* 保留下来工厂
*/
private static ApplicationContext context;
/**
* 将创建好工厂以参数形式传递给这个类
*
* @param applicationContext 上下文
* @throws BeansException
*/
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
{
context = applicationContext;
}
/**
* 提供在工厂中获取对象的方法 例如:RedisTemplate redisTemplate
*
* @param beanName bean的名称
* @return
*/
public static Object getBean(String beanName)
{
return context.getBean(beanName);
}
}
... ...
package com.sunyo.wlpt.message.bus.service.cache;
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.serializer.StringRedisSerializer;
import org.springframework.util.DigestUtils;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* @author 子诚
* Description:自定义Redis作为mybatis二级缓存实现
* 时间:2020/8/6 9:37
*/
public class RedisCache implements Cache {
/**
* slf4j的日志记录器
*/
private static final Logger logger = LoggerFactory.getLogger(RedisCache.class);
/**
* 用于事务性缓存操作的读写锁
*/
private static final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
/**
* 缓存对象的是失效时间,30分钟
*/
private static final long CACHE_TIME_IN_MINT = 30;
/**
* 当前放入缓存的mapper的namespace
*/
private final String id;
/**
* 必须存在构造方法
*/
public RedisCache(String id)
{
this.id = id;
}
/**
* 返回cache唯一标识
*/
@Override
public String getId()
{
return this.id;
}
/**
* 缓存放入值 redis RedisTemplate StringRedisTemplate
*
* @param key hash_key
* @param value hash_value
*/
@Override
public void putObject(Object key, Object value)
{
RedisTemplate redisTemplate = getRedisTemplate();
// 使用redis的hash类型作为缓存存储模型
redisTemplate.opsForHash().put(id.toString(), key.toString(), value);
redisTemplate.expire(id.toString(), CACHE_TIME_IN_MINT, TimeUnit.MINUTES);
}
/**
* 缓存中中获取数据
*/
@Override
public Object getObject(Object key)
{
RedisTemplate redisTemplate = getRedisTemplate();
//根据key 从redis的hash类型中获取数据
return redisTemplate.opsForHash().get(id.toString(), key.toString());
}
/**
* 注意:这个方法为mybatis保留方法 默认没有实现 后续版本可能会实现
*
* @param key hash_key
* @return
*/
@Override
public Object removeObject(Object key)
{
RedisTemplate redisTemplate = getRedisTemplate();
redisTemplate.delete(key);
return null;
}
@Override
public void clear()
{
logger.info("清空->{}<-缓存", id);
RedisTemplate redisTemplate = getRedisTemplate();
// 清空 namespace
redisTemplate.delete(id.toString());
}
/**
* 用来计算缓存数量
*/
@Override
public int getSize()
{
RedisTemplate redisTemplate = getRedisTemplate();
// 获取hash中key value数量
return redisTemplate.opsForHash().size(id.toString()).intValue();
}
/**
* 封装redisTemplate
*
* @return RedisTemplate
*/
private RedisTemplate getRedisTemplate()
{
//通过application工具类获取redisTemplate
RedisTemplate redisTemplate = (RedisTemplate) ApplicationContextUtils.getBean("redisTemplate");
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
return redisTemplate;
}
/**
* 封装一个对key进行md5处理方法
*/
private String getKeyToMD5(String key)
{
return DigestUtils.md5DigestAsHex(key.getBytes());
}
@Override
public ReadWriteLock getReadWriteLock()
{
return readWriteLock;
}
}
... ...
<?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="com.sunyo.wlpt.message.bus.service.mapper.BusExchangeMapper">
<!-- 使用Redis做mybatis的二级缓存 -->
<cache type="com.sunyo.wlpt.message.bus.service.cache.RedisCache"/>
<resultMap id="BaseResultMap" type="com.sunyo.wlpt.message.bus.service.domain.BusExchange">
<!--@mbg.generated-->
<!--@Table bus_exchange-->
... ...
<?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="com.sunyo.wlpt.message.bus.service.mapper.BusQueueMapper">
<!-- 使用Redis做mybatis的二级缓存 -->
<cache type="com.sunyo.wlpt.message.bus.service.cache.RedisCache"/>
<resultMap id="BaseResultMap" type="com.sunyo.wlpt.message.bus.service.domain.BusQueue">
<!--@mbg.generated-->
<!--@Table bus_queue-->
... ...
<?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="com.sunyo.wlpt.message.bus.service.mapper.BusServerMapper">
<!-- 使用Redis做mybatis的二级缓存 -->
<cache type="com.sunyo.wlpt.message.bus.service.cache.RedisCache"/>
<resultMap id="BaseResultMap" type="com.sunyo.wlpt.message.bus.service.domain.BusServer">
<!--@mbg.generated-->
<!--@Table bus_server-->
... ... @@ -237,5 +239,4 @@
from bus_server
where server_name = #{serverName,jdbcType=VARCHAR}
</select>
</mapper>
... ...
<?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="com.sunyo.wlpt.message.bus.service.mapper.RoutingKeyMapper">
<!-- 使用Redis做mybatis的二级缓存 -->
<cache type="com.sunyo.wlpt.message.bus.service.cache.RedisCache"/>
<resultMap id="BaseResultMap" type="com.sunyo.wlpt.message.bus.service.domain.RoutingKey">
<!--@mbg.generated-->
<!--@Table routing_key-->
... ...
<?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="com.sunyo.wlpt.message.bus.service.mapper.UserMessageBindingMapper">
<!-- 使用Redis做mybatis的二级缓存 -->
<cache type="com.sunyo.wlpt.message.bus.service.cache.RedisCache"/>
<resultMap id="BaseResultMap" type="com.sunyo.wlpt.message.bus.service.domain.UserMessageBinding">
<!--@mbg.generated--><!--@Table user_message_binding-->
<id column="id" jdbcType="VARCHAR" property="id"/>
... ... @@ -65,7 +67,7 @@
where id = #{id,jdbcType=VARCHAR}
</delete>
<!-- 根据服务器id,删除配置关系-->
<!-- 根据服务器id,删除配置关系-->
<delete id="deleteByServerId" parameterType="java.lang.String">
<!--@mbg.generated-->
delete
... ...
<?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="com.sunyo.wlpt.message.bus.service.mapper.VirtualHostMapper">
<!-- 使用Redis做mybatis的二级缓存 -->
<cache type="com.sunyo.wlpt.message.bus.service.cache.RedisCache"/>
<resultMap id="BaseResultMap" type="com.sunyo.wlpt.message.bus.service.domain.VirtualHost">
<!--@mbg.generated-->
<!--@Table virtual_host-->
... ... @@ -123,7 +125,7 @@
<!--@mbg.generated-->
delete
from virtual_host
where server_id = #{serverId,jdbcType=VARCHAR}
where server_id = #{serverId,jdbcType=VARCHAR}
</delete>
<insert id="insert" parameterType="com.sunyo.wlpt.message.bus.service.domain.VirtualHost">
... ...