1. 程式人生 > 其它 >springboot配置基於redis的快取(一)

springboot配置基於redis的快取(一)

springboot配置基於redis的快取

一引入必要的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可以看到快取的結果

相關注解說明

  1. @EnableCaching

    開啟快取功能,一般放在啟動類上或者自定義的RedisConfig配置類上

  2. @CacheConfig

    使用@CacheConfig(cacheNames="cacheName")註解在類上,用來指定統一的value值,統一管理keys,這時可以在方法上省略value,如果在方法上寫了value,那麼以方法上的為準。

  3. @Cacheable

    根據方法對返回的結果進行快取,下次請求時,如果快取存在,直接返回快取資料,如果不存在,則執行方法,並把返回結果快取,多用於查詢方法上。

    屬性/方法名 解釋
    value 快取名,指定了快取放在那塊空間上
    cacheNames 與value差不多,二選一
    key 快取key,可以用SPEL標籤自定義
    keyGenerator key生成器
    cacheManager 快取管理器
    cacheResolver 快取解析器
    condition 條件符合則快取
    unless 條件符合不快取
    sync 是否使用非同步模式,預設false
  4. @CachePut

    此註解標註的方法,每次都會執行,並將結果存入指定的快取中。其它方法則可以直接讀取快取資料。一般用在新增方法上,屬性值同@Cacheable

  5. @CacheEvict

    此註解標註的方法會清空快取,一般用於更新或刪除方法上,屬性與@Cacheable差不多,下面是特有的

    屬性/方法名 解釋
    allEntries 是否清空所有快取,預設false,如果指定為true,則方法呼叫後立即清空所有的快取
    beforeInvocation 是否在執行方法之前就清空快取,預設為false,如果指定為true,剛方法執行前會清空所有快取
  6. @Caching

    可以實現在同一個方法上使用多種註解