SpringBoot 2.x 集成 Redis
添加依賴
此處redis客戶端使用jedis。
<!-- redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<exclusions>
<exclusion>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</exclusion>
<exclusion>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- redis 客戶端使用jedis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
-
Jedis
直接連接 redis server。在多線程環境下是非線程安全的,需要使用連接池,為每個Jedis實例增加物理連接。
-
Lettuce
連接基於Netty,連接實例可以在多個線程間並發訪問。因為連接實例是線程安全的,所以一個連接實例就可以滿足多線程環境下的並發訪問。
添加配置
2.0 版本之前的一些配置已被移除。使用jedis就配置jedis(如下配置),使用lettuce換下名稱即可。
# REDIS (RedisProperties)
# Redis數據庫索引(默認為0)
spring.redis.database=0
# Redis服務器地址
spring.redis.host=127.0.0.1
# Redis服務器連接端口
spring.redis.port=6379
# Redis服務器連接密碼(默認為空)
spring.redis.password=
# 連接超時時間(毫秒)
spring.redis.timeout=0ms
# 連接池最大連接數(使用負值表示沒有限制)
spring.redis.jedis.pool.max-active=8
# 連接池最大阻塞等待時間(使用負值表示沒有限制)
spring.redis.jedis.pool.max-wait=-1ms
# 連接池中的最大空閑連接
spring.redis.jedis.pool.max-idle=8
# 連接池中的最小空閑連接
spring.redis.jedis.pool.min-idle=0
添加redis配置類
-
SpringBoot1.5x之前,Redis配置類如下:
@Configuration @EnableCaching public class RedisConfig extends CachingConfigurerSupport { @Bean public KeyGenerator keyGenerator() { return new KeyGenerator() { @Override public Object generate(Object target, Method method, Object... params) { StringBuilder sb = new StringBuilder(); 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 redisCacheManager = new RedisCacheManager(redisTemplate); return redisCacheManager; } }
-
SpringBoot2.0 Redis配置類如下(普遍使用了build模式),
@Configuration @EnableCaching public class RedisConfig extends CachingConfigurerSupport { @Bean public CacheManager cacheManager(RedisConnectionFactory connectionFactory) { RedisCacheManager redisCacheManager = RedisCacheManager.builder(connectionFactory).build(); return redisCacheManager; } @Bean public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(redisConnectionFactory); // key序列化 redisTemplate.setKeySerializer(new StringRedisSerializer()); // value序列化 redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer(Object.class)); redisTemplate.afterPropertiesSet(); return redisTemplate; } }
緩存管理器
- RedisCacheManager
- SimpleCacheManager
- NoOpCacheManager
- ConcurrentMapCacheManager
- CompositeCacheManager
- EhCacheCacheManager
序列化器
- GenericToStringSerializer:使用Spring轉換服務進行序列化;
- JacksonJsonRedisSerializer:使用Jackson 1,將對象序列化為JSON;
- Jackson2JsonRedisSerializer:使用Jackson 2,將對象序列化為JSON;
- JdkSerializationRedisSerializer:使用Java序列化;
- OxmSerializer:使用Spring O/X映射的編排器和解排器(marshaler和unmarshaler)實現序列化,用於XML序列化;
- StringRedisSerializer:序列化String類型的key和value。
redis使用
-
自動根據方法生成緩存
訪問
/api/user/{id}
接口,會將結果緩存。代碼如下:@RestController @RequestMapping(value = "/api") public class StudentController { @Autowired OmsUserRepository omsUserRepository; @GetMapping(value = "/user") public List<OmsUser> getAllUser() { return this.omsUserRepository.findAll(); } @GetMapping(value = "/user/{id}") @Cacheable(value = "user-key") public OmsUser getUserById(@PathVariable("id") String id) { return omsUserRepository.findById(id).get(); } }
-
@Cacheable
表明spring在調用方法之前,首先應該在緩存中查找方法的返回值。如果這個值能夠找到,就會返回緩存的值。否則的話,這個方法就會被調用,返回值會放到緩存之中。
-
@CachePut
表明spring應該將方法的返回值放到緩存中。在方法的調用前不會檢查緩存,方法始終都會被調用。
-
@CacheEvict
表明spring應該在緩存中清除一個或多個條目
-
@Caching
這是一個分組的注解,能夠同時應用多個其它的緩存注解。
自定義key
@Cacheable
和@CachePut
都有一個名為key屬性,可使用spel表達式獲取值。#root.args
:傳遞給緩存方法的參數,形式為數組#root.caches
:該方法執行時所對應的緩存,形式為數組#root.target
:目標對象#root.targetClass
:目標對象的類,等同#root.target.class
#root.method
:緩存方法#root.methodName
:緩存方法的名字,等同root.method.name
#result
:方法調用的返回值,不能用在@Cacheable
注解上#Argument
:任意的方法參數名(如#argName
)或參數索引(如#a0
或#p0
)
條件化緩存
@Cacheable
和@CachePut
提供了兩個屬性用以實現條件化緩存:unless
和condition
,這兩個屬性都接受一個SpEL表達式。-
unless
僅阻止將對象放進緩存,在這個方法被調用的時候,依然會去緩存中進行查找,如果找到了匹配的值,就會返回找到的值。
-
condition
如果表達式計算結果為
false
,那么在這個方法調用的過程中,緩存是被禁用的。即在這個方法被調用的時候,不會去緩存進行查找,同時返回值也不會放進緩存中。
-
-
使用 Template(模版)
模版種類:
- StringRedisTemplate
- RedisTemplate
測試代碼:
@RunWith(SpringRunner.class) @SpringBootTest public class TestRedis { @Autowired private StringRedisTemplate stringRedisTemplate; @Autowired private RedisTemplate redisTemplate; @Test public void test() throws Exception { // set stringRedisTemplate.opsForValue().set("key", "value"); // get String value = stringRedisTemplate.opsForValue().get("key"); Assert.assertEquals("value", value); } @Test public void testObj() throws Exception { User user = new User("king", "boy", 18); ValueOperations<String, User> operations = redisTemplate.opsForValue(); // set operations.set("obj.user.key", user); // get User user2 = operations.get("obj.user.key"); Assert.assertEquals(user.getName(), user2.getName()); Assert.assertEquals(user.getSex(), user2.getSex()); Assert.assertEquals(user.getAge(), user2.getAge()); } }
測試代碼中
User user2 = operations.get("obj.user.key")
會報錯java.util.LinkedHashMap cannot be cast to User
。修改redis配置類,如下:@Configuration @EnableCaching public class RedisConfig extends CachingConfigurerSupport { @Bean public CacheManager cacheManager(RedisConnectionFactory connectionFactory) { RedisCacheManager redisCacheManager = RedisCacheManager.builder(connectionFactory).build(); return redisCacheManager; } @Bean public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(redisConnectionFactory); // key序列化 redisTemplate.setKeySerializer(new StringRedisSerializer()); // value序列化 // 使用Jackson ,將對象序列化為JSON Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); //json 轉對象類,不設置默認的會將json轉成hashmap ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(om); redisTemplate.setValueSerializer(jackson2JsonRedisSerializer); redisTemplate.afterPropertiesSet(); return redisTemplate; } }
-
共享 session
-
添加依賴
<dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session-data-redis</artifactId> </dependency>
-
session配置
@Configuration @EnableRedisHttpSession(maxInactiveIntervalInSeconds = 86400*30) public class SessionConfig { }
-
測試
@RequestMapping("/uid") String uid(HttpSession session) { UUID uid = (UUID) session.getAttribute("uid"); if (uid == null) { uid = UUID.randomUUID(); } session.setAttribute("uid", uid); return session.getId(); }
第一次訪問后生成session,第二次及以后訪問獲取到session值相同。redis存儲session形式如下圖:
-