SpringBoot整合Redis Lettuce
阿新 • • 發佈:2018-12-12
最近在準備整合的基礎框架使用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; } }