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
可以實現在同一個方法上使用多種註解