Spring-Boot專案中配置redis註解快取
在pom中新增redis快取支援依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
在yml中新增redis配置
設定快取有效期為一天,配置類中使用
spring:
redis:
database: xx
host: xx.xx.xx.xx
port: 6379
password: xxxxx # 密碼(預設為空)
timeout: 6000ms # 連線超時時長(毫秒)
jedis:
pool:
max-active: 1000 # 連線池最大連線數(使用負值表示沒有限制)
max-wait: -1ms # 連線池最大阻塞等待時間(使用負值表示沒有限制)
max-idle: 10 # 連線池中的最大空閒連線
min-idle: 5 # 連線池中的最小空閒連線
activiti:
check-process-definitions: false
# spirng 快取管理引數配置
cache:
redis:
time-to-live: 86400000
修改redis配置類
序列化快取資料,解決亂碼問題(分別配置redisTemplate和註解快取)
@Configuration
public class RedisConfig {
@Resource
private RedisConnectionFactory factory;
@Value("${spring.cache.redis.time-to-live}")
private Duration timeToLive = Duration.ZERO;
/**
* 配置Jackson2JsonRedisSerializer序列化策略
* */
private Jackson2JsonRedisSerializer<Object> serializer() {
// 使用Jackson2JsonRedisSerializer來序列化和反序列化redis的value值
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
// 指定要序列化的域,field,get和set,以及修飾符範圍,ANY是都有包括private和public
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
// 指定序列化輸入的型別,類必須是非final修飾的,final修飾的類,比如String,Integer等會跑出異常
// objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
return jackson2JsonRedisSerializer;
}
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
// 配置序列化(解決亂碼的問題)
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
// 快取有效期
.entryTtl(timeToLive)
// 使用StringRedisSerializer來序列化和反序列化redis的key值
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
// 使用Jackson2JsonRedisSerializer來序列化和反序列化redis的value值
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(serializer()))
// 禁用空值
.disableCachingNullValues();
return RedisCacheManager.builder(factory)
.cacheDefaults(config)
.build();
}
}
修改VO類,實現序列化介面
實現序列化介面才能將實體類存入快取中
@Data
@TableName("sys_user_token")
public class SysUserTokenEntity implements Serializable {
private static final long serialVersionUID = 1L;
/**
* id
*/
@TableId
private Long id;
/**
* 使用者ID
*/
private Long userId;
/**
* 使用者token
*/
private String token;
/**
* 過期時間
*/
private Date expireDate;
/**
* 更新時間
*/
private Date updateDate;
/**
* 建立時間
*/
@TableField(fill = FieldFill.INSERT)
private Date createDate;
}
註解快取型別和用法
@Cacheable
@Cacheable 的作用 主要針對方法配置,能夠根據方法的請求引數對其結果進行快取
@Cacheable(value = CACHE_KEY, key = "#id",condition = "#result != null")
public Tasklog findById(String id){
return taskLogMapper.selectById(id);
}
引數 | 解釋 | example |
---|---|---|
value | 快取的名稱,在 spring 配置檔案中定義,必須指定至少一個 | 例如: @Cacheable(value=”mycache”) @Cacheable(value={”cache1”,”cache2”} |
key | 快取的 key,可以為空,如果指定要按照 SpEL 表示式編寫,如果不指定,則預設按照方法的所有引數進行組合 | @Cacheable(value=”testcache”,key=”#userName”) |
condition | 快取的條件,可以為空,使用 SpEL 編寫,返回 true 或者 false,只有為 true 才進行快取 | @Cacheable(value=”testcache”,condition=”#userName.length()>2”) |
@CachePut
@CachePut 的作用 主要針對方法配置,能夠根據方法的請求引數對其結果進行快取,和 @Cacheable 不同的是,它每次都會觸發真實方法的呼叫
@CachePut(value = CACHE_KEY, key = "#tasklog.id")
public Tasklog create(Tasklog tasklog){
taskLogMapper.insert(tasklog);
return tasklog;
}
引數 | 解釋 | example |
---|---|---|
value | 快取的名稱,在 spring 配置檔案中定義,必須指定至少一個 | @CachePut(value=”my cache”) |
key | 快取的 key,可以為空,如果指定要按照 SpEL 表示式編寫,如果不指定,則預設按照方法的所有引數進行組合 | @CachePut(value=”testcache”,key=”#userName”) |
condition | 快取的條件,可以為空,使用 SpEL 編寫,返回 true 或者 false,只有為 true 才進行快取 | @CachePut(value=”testcache”,condition=”#userName.length()>2”) |
@CacheEvict
@CachEvict 的作用 主要針對方法配置,能夠根據一定的條件對快取進行清空
@CacheEvict(value = CACHE_KEY, key = "#id")
public void delete(String id){
taskLogMapper.deleteById(id);
}
引數 | 解釋 | example |
---|---|---|
value | 快取的名稱,在 spring 配置檔案中定義,必須指定至少一個 | @CacheEvict(value=”my cache”) |
key | 快取的 key,可以為空,如果指定要按照 SpEL 表示式編寫,如果不指定,則預設按照方法的所有引數進行組合 | @CacheEvict(value=”testcache”,key=”#userName”) |
condition | 快取的條件,可以為空,使用 SpEL 編寫,返回 true 或者 false,只有為 true 才進行快取 | @CacheEvict(value=”testcache”,condition=”#userName.length()>2”) |
allEntries | 是否清空所有快取內容,預設為 false,如果指定為 true,則方法呼叫後將立即清空所有快取 | @CachEvict(value=”testcache”,allEntries=true) |
beforeInvocation | 是否在方法執行前就清空,預設為 false,如果指定為 true,則在方法還沒有執行的時候就清空快取,預設情況下,如果方法執行丟擲異常,則不會清空快取 | @CachEvict(value=”testcache”,beforeInvocation=true) |
在專案啟動類中上新增@EnableCaching註解,表明啟用快取功能。
@SpringBootApplication
@EnableCaching
public class Ch06CacheApplication {
public static void main(String[] args) {SpringApplication.run(Ch06CacheApplication.class, args);}
}
注意:設定註解快取不生效的情形
情形一:
@CachePut註解須加在有返回值的方法上
有些service的實現類中,由於框架的限制,其父類的更新方法是沒有返回值的。例如下面的方法中,雖然可以拿到key值,但註解快取是根據方法的返回值進行更新的,所以會造成資料庫更新了資料而快取中的資料並沒有更新。
@Override
@Transactional(rollbackFor = Exception.class)
@CachePut(value = Constant.UserCacheConstant.USERIDCACHE,key="#dto.id")
public void update(WarningRuleDTO dto) {
super.update(dto);
}
情形二:
加的註解快取的方法必須是spring通過反射呼叫的,方法間的呼叫不會生效。
由於Controller通過反射呼叫的update方法,繼而在呼叫update2方法,此時快取註解也是無法生效的。
@Override
@Transactional(rollbackFor = Exception.class)
public void update(WarningRuleDTO dto) {
update2();
}
@CachePut(value = Constant.UserCacheConstant.USERIDCACHE,key="#dto.id")
private WarningRuleDTO update2(WarningRuleDTO dto){
super.update(dto);
}
解決方法
既然沒辦法進行更新操作,那就根據value刪除對應的所有key值
@Override
@Transactional(rollbackFor = Exception.class)
@CacheEvict(value = Constant.UserCacheConstant.USERIDCACHE,allEntries = true)
public void update(WarningRuleDTO dto) {
super.update(dto);
}