最近在准备集成的基础框架使用Spring Boot2搭建,其中Redis的支持不仅仅是丰富了它的API,更是替换掉底层Jedis的依赖,取而代之换成了Lettuce(生菜)
jedis跟lettuce的区别
- Lettuce 和 Jedis 的定位都是Redis的client,所以他们当然都可以直接连接redis server。
- Jedis在实现上是直接连接的redis server,如果在多线程环境下是非线程安全的,这个时候只有使用连接池,为每个Jedis实例增加物理连接
- Lettuce的连接是基于Netty的,连接实例(StatefulRedisConnection)可以在多个线程间并发访问,应为StatefulRedisConnection是线程安全的,所以一个连接实例(StatefulRedisConnection)就可以满足多线程环境下的并发访问,当然这个也是可伸缩的设计,一个连接实例不够的情况也可以按需增加连接实例。
导入依赖
在 pom.xml 中spring-boot-starter-data-redis的依赖,Spring Boot2.x 后底层不在是Jedis如果做版本升级的朋友需要注意下,第二个commons-pool2依赖不能少(连接池使用)。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> </dependency>
配置文件
由于Spring Boot2.x 的改动,连接池相关配置需要通过spring.redis.lettuce.pool 进行配置了
spring:
redis:
# Redis开关/默认关闭
enabled: true
database: 0
password: #redis密码
host: 127.0.0.1
port: 6379
lettuce:
pool:
max-active: 100 # 连接池最大连接数(使用负值表示没有限制)
max-idle: 100 # 连接池中的最大空闲连接
min-idle: 50 # 连接池中的最小空闲连接
max-wait: 6000 # 连接池最大阻塞等待时间(使用负值表示没有限制)
timeout: 1000
具体配置类
RedisConfig
@Configuration
@EnableCaching // 开启缓存支持
public class RedisConfig extends CachingConfigurerSupport {
@Resource
private LettuceConnectionFactory lettuceConnectionFactory;
// 缓存管理器
@Bean
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(keySerializer()))//key序列化方式
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(valueSerializer()))//value序列化方式
.disableCachingNullValues()
.entryTtl(Duration.ofSeconds(30*60));//缓存过期时间
RedisCacheManager.RedisCacheManagerBuilder builder = RedisCacheManager.RedisCacheManagerBuilder
.fromConnectionFactory(lettuceConnectionFactory)
.cacheDefaults(config)
.transactionAware()
.withInitialCacheConfigurations(getRedisCacheConfigurationMap());
return builder.build();
}
private RedisSerializer<String> keySerializer() {
return new StringRedisSerializer();
}
private RedisSerializer<Object> valueSerializer() {
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
jackson2JsonRedisSerializer.setObjectMapper(om);
return jackson2JsonRedisSerializer;
// 设置序列化 两种方式区别不大
// return new GenericJackson2JsonRedisSerializer();
}
private Map<String, RedisCacheConfiguration> getRedisCacheConfigurationMap() {
Map<String, RedisCacheConfiguration> redisCacheConfigurationMap = new HashMap<>();
/**
* @CacheConfig(cacheNames = "SsoCache")
public class SsoCache{
@Cacheable(keyGenerator = "cacheKeyGenerator")
public String getTokenByGsid(String gsid)
}
//二者选其一,可以使用value上的信息,来替换类上cacheNames的信息
@Cacheable(value = "BasicDataCache",keyGenerator = "cacheKeyGenerator")
public String getTokenByGsid(String gsid)
*/
//SsoCache和BasicDataCache进行过期时间配置
redisCacheConfigurationMap.put("menuCache", this.getRedisCacheConfigurationWithTtl(24*60*60));
redisCacheConfigurationMap.put("BasicDataCache", this.getRedisCacheConfigurationWithTtl(30*60));
return redisCacheConfigurationMap;
}
private RedisCacheConfiguration getRedisCacheConfigurationWithTtl(Integer seconds) {
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig();
redisCacheConfiguration = redisCacheConfiguration.entryTtl(Duration.ofSeconds(seconds))
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(keySerializer()))//key序列化方式
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(valueSerializer()))//value序列化方式;
;
return redisCacheConfiguration;
}
@Bean(name = "cacheKeyGenerator")
public KeyGenerator cacheKeyGenerator() {
return new KeyGenerator() {
@Override
public Object generate(Object target, 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();
}
};
}
/**
* RedisTemplate配置
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) {
// 设置序列化
//
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setKeySerializer(keySerializer());
redisTemplate.setHashKeySerializer(keySerializer());
// redisTemplate.setHashValueSerializer(valueSerializer());
// redisTemplate.setValueSerializer(valueSerializer());
redisTemplate.setConnectionFactory(lettuceConnectionFactory);
return redisTemplate;
}
}
RedisCacheManager
public class RedisCacheManager implements CacheManager {
/**
* 用于shiro中用到的cache
*/
private ConcurrentMap<String, Cache> caches = new ConcurrentHashMap<>();
/**
* redis cache 工具类
*/
private RedisTemplate redisTemplate = SpringUtils.getBean("redisTemplate");
// @Autowired
// private RedisTemplate redisTemplate;
@Override
public <K, V> Cache<K, V> getCache(String name) throws CacheException {
Cache<K, V> cache = caches.get(name);
if (cache == null) {
synchronized (this) {
cache = new RedisCache<>(3600, redisTemplate);
caches.put(name, cache);
}
}
return cache;
}
}
来源:oschina
链接:https://my.oschina.net/u/3737136/blog/2987435