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);
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM