1、增加redis依赖
<!-- redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2、增加Redis配置:
@Configuration
@EnableCaching
// 自动配置
@ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties(RedisProperties.class)
public class RedisConfigAdapter extends CachingConfigurerSupport {
/**
* 设置 redis 数据默认过期时间,默认1天
* 设置@cacheable 序列化方式
* @return
*/
@Bean
public RedisCacheConfiguration redisCacheConfiguration(){
FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);
RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig();
configuration = configuration.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(fastJsonRedisSerializer)).entryTtl(Duration.ofDays(1));
return configuration;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@Bean(name = "redisTemplate")
@ConditionalOnMissingBean(name = "redisTemplate")
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
//序列化
FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(Object.class);
// value值的序列化采用fastJsonRedisSerializer
template.setValueSerializer(fastJsonRedisSerializer);
template.setHashValueSerializer(fastJsonRedisSerializer);
// 全局开启AutoType,不建议使用
// ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
// 建议使用这种方式,小范围指定白名单
ParserConfig.getGlobalInstance().addAccept("com.tdou");
// ParserConfig.getGlobalInstance().addAccept("com.tdou.security.core.validate.code");
// key的序列化采用StringRedisSerializer
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
template.setConnectionFactory(redisConnectionFactory);
return template;
}
/**
* 自定义缓存key生成策略
* 使用方法 @Cacheable(keyGenerator="keyGenerator")
* @return
*/
@Bean
@Override
public KeyGenerator keyGenerator() {
return (target, method, params) -> {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append(method.getName());
for (Object obj : params) {
sb.append(JSON.toJSONString(obj).hashCode());
}
System.out.println("自定义缓存key生成策略 :" + sb.toString());
return sb.toString();
};
}
}
3、实现Mybatis接口org.apache.ibatis.cache.Cache
public class MybatisRedisCache implements Cache {
private static final Logger log = LoggerFactory.getLogger(MybatisRedisCache.class);
// 读写锁
private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(true);
private final String id; // cache instance id
@SuppressWarnings("rawtypes")
private RedisTemplate redisTemplate;
private static final long EXPIRE_TIME_IN_MINUTES = 30; // redis过期时间
private static final String CACHE_PREFIX = "Summer-MSP:"; // redis过期时间
public MybatisRedisCache(String id) {
if (id == null) {
throw new IllegalArgumentException("Cache instances require an ID");
}
log.info("==> redis cache id : " + id);
this.id = id;
}
@Override
public String getId() {
return id;
}
/**
* Put query result to redis
*
* @param key
* @param value
*/
@Override
@SuppressWarnings({ "unchecked", "rawtypes" })
public void putObject(Object key, Object value) {
RedisTemplate redisTemplate = getRedisTemplate();
ValueOperations opsForValue = redisTemplate.opsForValue();
String keyStr = getKey(key);
opsForValue.set(keyStr, value, EXPIRE_TIME_IN_MINUTES, TimeUnit.MINUTES);
log.info("==> put query result to redis : key = {} value = {}", keyStr, value);
}
/**
* Get cached query result from redis
*
* @param key
* @return
*/
@SuppressWarnings({ "rawtypes"})
@Override
public Object getObject(Object key) {
RedisTemplate redisTemplate = getRedisTemplate();
ValueOperations opsForValue = redisTemplate.opsForValue();
String keyStr = getKey(key);
Object object = opsForValue.get(keyStr);
log.info("==> get cached query result from redis by key : {}", keyStr);
log.info("==> get cached query result from redis : {}", object);
return object;
}
/**
* Remove cached query result from redis
*
* @param key
* @return
*/
@Override
@SuppressWarnings({ "unchecked", "rawtypes" })
public Object removeObject(Object key) {
RedisTemplate redisTemplate = getRedisTemplate();
String keyStr = getKey(key);
redisTemplate.delete(keyStr);
log.info("==> remove cached query result from redis by key : {}", keyStr);
return null;
}
/**
* Clears this cache instance
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public void clear() {
RedisTemplate redisTemplate = getRedisTemplate();
redisTemplate.execute((RedisCallback) connection -> {
connection.flushDb();
return null;
});
log.info("==> clear all the cached query result from redis");
}
@Override
public int getSize() {
return 0;
}
@Override
public ReadWriteLock getReadWriteLock() {
return readWriteLock;
}
@SuppressWarnings("rawtypes")
private RedisTemplate getRedisTemplate() {
if (redisTemplate == null) {
redisTemplate = ApplicationContextFactory.getBean("redisTemplate");
}
return redisTemplate;
}
public String getKey(Object key) {
StringBuilder sb = new StringBuilder();
sb.append(CACHE_PREFIX).append(key.toString().split(":")[2]);
return sb.toString();
}
}
4、修改MyBatis配置文件
<!-- 开启二级缓存,默认是false -->
<setting name="cacheEnabled" value="true" />
5、在mapper中配置缓存实现类