mybatis plus使用redis作為二級緩存

建議緩存放到 service 層,你可以自定義自己的 BaseServiceImpl 重寫註解父類方法,繼承自己的實現。為了方便,這裡我們將緩存放到mapper層。mybatis-plus整合redis作為二級緩存與mybatis整合redis略有不同。

1. mybatis-plus開啟二級緩存

mybatis-plus.configuration.cache-enabled=true

2. 定義RedisTemplate的bean交給spring管理,這裡為了能將對象直接存取到redis中,進行了一些序列化的操作

@Bean(value = "redisTemplate")
 public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory) {
 RedisTemplate redisTemplate = new RedisTemplate<>();
 redisTemplate.setConnectionFactory(connectionFactory);
 //Use Jackson 2Json RedisSerializer to serialize and deserialize the value of redis (default JDK serialization)
 Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
 ObjectMapper objectMapper = new ObjectMapper();
 objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
 //將類名稱序列化到json串中
 objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
 //設置輸入時忽略JSON字符串中存在而Java對象實際沒有的屬性
 objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
 jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
 //Use String RedisSerializer to serialize and deserialize the key value of redis
 RedisSerializer redisSerializer = new StringRedisSerializer();
 //key
 redisTemplate.setKeySerializer(redisSerializer);
 redisTemplate.setHashKeySerializer(redisSerializer);
 //value
 redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
 redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
 redisTemplate.afterPropertiesSet();
 return redisTemplate;
 }

3. 自定義自己的緩存管理

package com.qctchina.headsetserver.config;
import com.qctchina.headsetserver.util.SpringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.cache.Cache;
import org.springframework.data.redis.connection.RedisServerCommands;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.CollectionUtils;
import java.util.Set;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
 * @author shuangyueliao
 * @create 2019/9/10 14:02
 * @Version 0.1
 */
@Slf4j
public class MybatisRedisCache implements Cache {
 // 讀寫鎖
 private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(true);
 //這裡使用了redis緩存,使用springboot自動注入
 private RedisTemplate redisTemplate;
 private String id;
 public MybatisRedisCache(final String id) {
 if (id == null) {
 throw new IllegalArgumentException("Cache instances require an ID");
 }
 this.id = id;
 }
 @Override
 public String getId() {
 return this.id;
 }
 @Override
 public void putObject(Object key, Object value) {
 if (redisTemplate == null) {
 //由於啟動期間注入失敗,只能運行期間注入,這段代碼可以刪除
 redisTemplate = (RedisTemplate) SpringUtil.getBean("redisTemplate");
 }
 if (value != null) {
 redisTemplate.opsForValue().set(key.toString(), value);
 }
 }
 @Override
 public Object getObject(Object key) {
 if (redisTemplate == null) {
 //由於啟動期間注入失敗,只能運行期間注入,這段代碼可以刪除
 redisTemplate = (RedisTemplate) SpringUtil.getBean("redisTemplate");
 }
 try {
 if (key != null) {
 return redisTemplate.opsForValue().get(key.toString());
 }
 } catch (Exception e) {
 e.printStackTrace();
 log.error("緩存出錯 ");
 }
 return null;
 }
 @Override
 public Object removeObject(Object key) {
 if (redisTemplate == null) {
 //由於啟動期間注入失敗,只能運行期間注入,這段代碼可以刪除
 redisTemplate = (RedisTemplate) SpringUtil.getBean("redisTemplate");
 }
 if (key != null) {
 redisTemplate.delete(key.toString());
 }
 return null;
 }
 @Override
 public void clear() {
 log.debug("清空緩存");
 if (redisTemplate == null) {
 redisTemplate = (RedisTemplate) SpringUtil.getBean("redisTemplate");
 }
 Set keys = redisTemplate.keys("*:" + this.id + "*");
 if (!CollectionUtils.isEmpty(keys)) {
 redisTemplate.delete(keys);
 }
 }
 @Override
 public int getSize() {
 if (redisTemplate == null) {
 //由於啟動期間注入失敗,只能運行期間注入,這段代碼可以刪除
 redisTemplate = (RedisTemplate) SpringUtil.getBean("redisTemplate");
 }
 Long size = redisTemplate.execute((RedisCallback) RedisServerCommands::dbSize);
 return size.intValue();
 }
 @Override
 public ReadWriteLock getReadWriteLock() {
 return this.readWriteLock;
 }
}

SpringUtil是手動獲取bean的工具類

@Component
public class SpringUtil implements ApplicationContextAware {
 private static ApplicationContext applicationContext;
 @Override
 public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
 SpringUtil.applicationContext = applicationContext;
 }
 public static Object getBean(String name){
 return applicationContext.getBean(name);
 }
 public static  T getBean(String name, Class clazz){
 return applicationContext.getBean(name, clazz);
 }
 public static  T getBean(Class clazz){
 return applicationContext.getBean(clazz);
 }
}

4. 在mapper上加上註解@CacheNamespace

@CacheNamespace(implementation= MybatisRedisCache.class,eviction=MybatisRedisCache.class)
public interface CommonMapper extends BaseMapper {

如果調用該mapper下的方法,那麼會使用redis緩存

mybatis plus使用redis作為二級緩存


分享到:


相關文章: