springboot配置基於redis的快取(一)
阿新 • • 發佈:2021-06-22
springboot配置基於redis的快取
-
springboot為什麼要用快取?
https://docs.spring.io/spring-boot/docs/2.4.6/reference/htmlsingle/#boot-features-caching
-
springboot如何實現快取及Redis做快取的特性?
https://docs.spring.io/spring-boot/docs/2.4.6/reference/htmlsingle/#boot-features-caching-provider
一引入必要的maven依賴
<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>
配置RedisConfig
- 在application.yaml新增對應的redis配置資訊
# redis 配置 spring: redis: database: 0 cluster: max-redirects: 3 nodes: - 192.168.15.208:7001 - 192.168.15.208:7002 - 192.168.15.208:7003 - 192.168.15.208:7004 - 192.168.15.208:7005 - 192.168.15.208:7006 #password: 1234 lettuce: pool: max-active: 1000 max-wait: -1 max-idle: 10 min-idle: 5 timeout: 3000 data: redis: repositories: enabled: false
- 新增自動化配置類
/** * @author lyy * @date 2021/6/21 */ @Configuration @EnableCaching @SuppressWarnings("all") public class RedisConfig { @Bean @ConditionalOnMissingBean(name = "redisTemplate") public RedisTemplate<String, Object> redisTemplate( RedisConnectionFactory redisConnectionFactory) { Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(Object.class); ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); // 解決jackson2無法反序列化LocalDateTime的問題 om.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); om.registerModule(new JavaTimeModule()); om.activateDefaultTyping(om.getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.NON_FINAL); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(om); RedisTemplate<String, Object> template = new RedisTemplate<String, Object>(); template.setConnectionFactory(redisConnectionFactory); // template.setKeySerializer(jackson2JsonRedisSerializer); template.setKeySerializer(new StringRedisSerializer()); template.setValueSerializer(jackson2JsonRedisSerializer); template.setHashKeySerializer(jackson2JsonRedisSerializer); template.setHashValueSerializer(jackson2JsonRedisSerializer); template.afterPropertiesSet(); return template; } @Bean @ConditionalOnMissingBean(StringRedisTemplate.class) public StringRedisTemplate stringRedisTemplate( RedisConnectionFactory redisConnectionFactory) { StringRedisTemplate template = new StringRedisTemplate(); template.setConnectionFactory(redisConnectionFactory); return template; } //cacheManager只針對註解快取有效 //只使用redisTemplate不需要配置 @Bean public KeyGenerator keyGenerator() { return (o, method, objects) -> { StringBuilder sb = new StringBuilder(); sb.append(o.getClass().getName()); sb.append("." + method.getName() + "("); for (Object obj : objects) { sb.append(obj.toString()); } sb.append(")"); return sb.toString(); }; } @Bean public ObjectMapper objectMapper() { ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY); om.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); return om; } @Bean public Jackson2JsonRedisSerializer jackson2JsonRedisSerializer(ObjectMapper om) { Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); jackson2JsonRedisSerializer.setObjectMapper(om); return jackson2JsonRedisSerializer; } /** * springboot2.x中,RedisCacheManager已經沒有了單引數的構造方法 * 1.x中通過引數redisTemplate配置的方式不可行 */ @Bean public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory, RedisSerializer jackson2JsonRedisSerializer) { RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ofHours(1)) // 設定快取有效期一小時 .disableCachingNullValues() .computePrefixWith(cacheName -> "ants_sale_white".concat(":").concat(cacheName).concat(":")) .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())) .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer)); return RedisCacheManager.builder(redisConnectionFactory) .cacheDefaults(cacheConfiguration) .build(); } }
注意:需要先在RedisConfig加上@EnableCaching,表示開啟快取功能
啟用spring 註解快取
@Service(value = "UserServer")
@CacheConfig(cacheNames = "user")
public class UserServer implements com.ants.furun.sale_white_board.servers.api.UserServer {
@Override
@CachePut(key = "'ants-'+#userPo.id")
public UserPo addUser(UserPo userPo) {
return userPo;
}
@Override
@CacheEvict(key="'ants-'+#p0")
public int deleteUser(int id) {
return 0;
}
@Override
@Cacheable(key = "'ants-'+#p0")
public UserPo getUser(int id) {
return null;
}
}
其中#p0是指的第一個引數,#p1是第二個引數,以此類推。
此時我們檢視redis可以看到快取的結果
相關注解說明
-
@EnableCaching
開啟快取功能,一般放在啟動類上或者自定義的RedisConfig配置類上
-
@CacheConfig
使用@CacheConfig(cacheNames="cacheName")註解在類上,用來指定統一的value值,統一管理keys,這時可以在方法上省略value,如果在方法上寫了value,那麼以方法上的為準。
-
@Cacheable
根據方法對返回的結果進行快取,下次請求時,如果快取存在,直接返回快取資料,如果不存在,則執行方法,並把返回結果快取,多用於查詢方法上。
屬性/方法名 解釋 value 快取名,指定了快取放在那塊空間上 cacheNames 與value差不多,二選一 key 快取key,可以用SPEL標籤自定義 keyGenerator key生成器 cacheManager 快取管理器 cacheResolver 快取解析器 condition 條件符合則快取 unless 條件符合不快取 sync 是否使用非同步模式,預設false -
@CachePut
此註解標註的方法,每次都會執行,並將結果存入指定的快取中。其它方法則可以直接讀取快取資料。一般用在新增方法上,屬性值同@Cacheable
-
@CacheEvict
此註解標註的方法會清空快取,一般用於更新或刪除方法上,屬性與@Cacheable差不多,下面是特有的
屬性/方法名 解釋 allEntries 是否清空所有快取,預設false,如果指定為true,則方法呼叫後立即清空所有的快取 beforeInvocation 是否在執行方法之前就清空快取,預設為false,如果指定為true,剛方法執行前會清空所有快取 -
@Caching
可以實現在同一個方法上使用多種註解