package com.corecmd.webapp.tiansjportal.common.utils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.ibatis.cache.Cache;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* @author CoreCmd
* @date 2021/7/5
* @apiNote
*/
@Slf4j
public class MyBatisRedisCache implements Cache {
//命名空间全名称
private String id;
private RedisTemplate<Object, Object> redisTemplate;
//统一的缓存前缀
private final String MYBATIS_CACHE_PREFIX = "tiansjportal-mybatis-cache";
private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
public MyBatisRedisCache(String id) {
if (id == null) {
throw new IllegalArgumentException("缓存实例需要一个id");
}
this.id = id;
}
@Override
public String getId() {
return id;
}
@Override
public void putObject(Object key, Object value) {
try {
redisTemplate = getRedisTemplate();
String strKey = generateRedisKey(key);
redisTemplate.opsForHash().put(MYBATIS_CACHE_PREFIX + ":" + id, strKey, "1");
redisTemplate.opsForValue().set(strKey, value, 30, TimeUnit.MINUTES);
} catch (Exception e) {
log.info("Redis put failed, key=" + key.toString(), e);
}
}
private RedisTemplate<Object, Object> getRedisTemplate() {
if (Objects.isNull(redisTemplate)) {
synchronized (RedisTemplate.class){
if (Objects.isNull(redisTemplate)){
redisTemplate = ApplicationContextHolder.getBean("redisTemplate");
}
}
}
//序列化为String,为后续操作统一前缀的缓存准备
RedisSerializer stringSerializer = new StringRedisSerializer();
redisTemplate.setKeySerializer(stringSerializer);
redisTemplate.setHashKeySerializer(stringSerializer);
// value序列化方式采用jackson
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
// hash的value序列化方式采用jackson
redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
@Override
public Object getObject(Object key) {
try {
redisTemplate = getRedisTemplate();
String strKey = generateRedisKey(key);
return redisTemplate.opsForValue().get(strKey);
} catch (Exception e) {
log.info("Redis get failed, fail over to db", e);
return null;
}
}
@Override
public Object removeObject(Object key) {
log.info("移除缓存:"+key);
try {
redisTemplate = getRedisTemplate();
String strKey = generateRedisKey(key);
redisTemplate.delete(strKey);
} catch (Exception e) {
log.info("从redis清除缓存异常", e);
}
return null;
}
@Override
public void clear() {
try {
redisTemplate = getRedisTemplate();
String hsKey = MYBATIS_CACHE_PREFIX + ":" + id;
Map<Object, Object> idMap = redisTemplate.opsForHash().entries(hsKey);
log.info("清空缓存:"+hsKey);
if (!idMap.isEmpty()) {
Set<Object> keySet = idMap.keySet();
Set<String> keys = new HashSet<>(keySet.size());
keySet.forEach(item -> keys.add(item.toString()));
redisTemplate.delete(keys);
redisTemplate.delete(hsKey);
}
} catch (Exception e) {
log.error("清空缓存失败", e);
}
}
@Override
public int getSize() {
redisTemplate = getRedisTemplate();
Set<Object> keys = redisTemplate.keys(MYBATIS_CACHE_PREFIX + ":*");
return keys != null ? keys.size() : 0;
}
private String generateRedisKey(Object key) {
return this.id + ":" + DigestUtils.sha256Hex(key.toString().getBytes());
}
}
redis实现mybatis自定义缓存
最新推荐文章于 2022-12-05 20:25:37 发布