redis 安装请参考 此文

1. 引入依赖

<dependency>  
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2. application.yml 配置文件中增加配置

spring:
redis:
# Redis数据库索引(默认为0)
database: 0
# Redis服务器地址
host: 10.150.1.71
# Redis服务器连接端口
port: 6379
# Redis服务器连接密码(默认为空)
#password:
pool:
# 连接池最大连接数(使用负值表示没有限制)
max-active: -1
# 连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: -1
# 连接池中的最大空闲连接
max-idle: 8
# 连接池中的最小空闲连接
min-idle: 0
# 连接超时时间(毫秒)
timeout: 15000

此处插一句嘴:在redis服务器的配置文件中,bind 属性绑定的IP,是指 redis 服务器对外暴露的IP,也就是其他应用需要用这个IP才能访问redis服务器

3. 程序主入口添加 @EnableCaching 注解

@SpringBootApplication(scanBasePackages = {"com.test"})
@ServletComponentScan
@EnableScheduling
@EnableCaching
public class Application {

private final static Logger LOGGER = LoggerFactory.getLogger(Application.class);

public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
LOGGER.info("applicatin sso started!");
}

}

至此 spring boot redis 配置缓存已经结束,使用 spring boot 提供的方法 @Cacheable  @CachePut 等即可进行缓存操作。


以下内容为实际项目中遇到的问题记录。

1. @Cacheable(value="a", key="b") 与 @Cacheable(cacheNames="a", key="b") 是等价的,因为 cacheNames 是 value 的一个别名。

2. 在不做任何自定义配置的情况下,你会发现 redis 中存储的 key 带有序列化的数据,比如

\xac\xed\x00\x05t\x00a

这样,根本原因是 spring boot 采用的 key 默认序列化的方式为 JdkSerializationRedisSerializer,解决方法就是自己写配置进行序列化

package com.test.sso.in;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
* Redis缓存配置类
*
* @author walli
*
*/
@Configuration
public class RedisConfig extends CachingConfigurerSupport {

// 缓存失效时间,单位 秒
private static final long DEFAULT_CACHE_EXPIRE_TIME = 1800L;

//自定义缓存key生成策略
// @Bean
// public KeyGenerator keyGenerator() {
// return new KeyGenerator(){
// @Override
// public Object generate(Object target, java.lang.reflect.Method method, Object... params) {
// StringBuffer sb = new StringBuffer();
// sb.append(target.getClass().getName());
// sb.append(method.getName());
// for(Object obj:params){
// sb.append(obj.toString());
// }
// return sb.toString();
// }
// };
// }
//缓存管理器
@Bean
public CacheManager cacheManager(RedisTemplate redisTemplate) {
RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
//设置缓存过期时间
cacheManager.setDefaultExpiration(DEFAULT_CACHE_EXPIRE_TIME);
return cacheManager;
}

@Bean
public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
StringRedisTemplate template = new StringRedisTemplate(factory);
//设置序列化工具
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
template.setKeySerializer(redisSerializer);
template.setHashKeySerializer(redisSerializer);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
template.setValueSerializer(jackson2JsonRedisSerializer);
template.setHashValueSerializer(jackson2JsonRedisSerializer);

template.afterPropertiesSet();
return template;
}
}

3. 经过上述配置之后,在 redis-cli 中输入 keys * 你会发现没有序列化的乱码了,但是目标的 key 与自己的预想并不一致,你会发现如果你配置的缓存为 @Cacheable(cacheNames="a", key="b"),redis 中实际存储的数据 key 会有两个,一个是 b, 另一个是 a~keys。其实这个是 spring boot 缓存实现方式的问题,b 即为你实际所需的缓存 key,而 a~keys 的类型为 ZSET,其中保存了所有的 cacheNames=a 的 keys。因此如果需要直接从redis中读取缓存值,直接使用 key=b 来读取就行了。