自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

從零搭建Spring Boot腳手架:整合Redis作為緩存

存儲(chǔ) 存儲(chǔ)軟件 Redis
今天我們會(huì)把緩存也集成進(jìn)來(lái)。緩存是一個(gè)系統(tǒng)應(yīng)用必備的一種功能,除了在減輕數(shù)據(jù)庫(kù)的壓力之外。

[[338457]]

前言

 今天我們會(huì)把緩存也集成進(jìn)來(lái)。緩存是一個(gè)系統(tǒng)應(yīng)用必備的一種功能,除了在減輕數(shù)據(jù)庫(kù)的壓力之外。還在存儲(chǔ)一些短時(shí)效的數(shù)據(jù)場(chǎng)景中發(fā)揮著重大作用,比如存儲(chǔ)用戶Token、短信驗(yàn)證碼等等,目前緩存的選型還是比較多的,EHCACHE、HAZELCAST、CAFFEINE、COUCHBASE以及本文要整合的REDIS。接下來(lái)我們將會(huì)在kono腳手架項(xiàng)目中集成Spring Cache以及Redis。

Gitee: https://gitee.com/felord/kono day05 分支

GitHub: https://github.com/NotFound403/kono day05 分支

2. 整合目標(biāo)

使項(xiàng)目具有緩存功能,同時(shí)將默認(rèn)的JDK序列化修改為Jackson序列化以存儲(chǔ)一些對(duì)象,同時(shí)實(shí)現(xiàn)一些特定的個(gè)性化的緩存空間以滿足不同場(chǎng)景下的不同緩存TTL時(shí)間需求。

3. 依賴(lài)集成

目前只需要引入下面的依賴(lài)即可:

  1.  <dependency> 
  2.     <groupId>org.springframework.boot</groupId> 
  3.     <artifactId>spring-boot-starter-data-redis</artifactId> 
  4. </dependency> 
  5. <dependency> 
  6.     <groupId>org.springframework.boot</groupId> 
  7.     <artifactId>spring-boot-starter-cache</artifactId> 
  8. </dependency> 
  9. <dependency> 
  10.     <groupId>org.apache.commons</groupId> 
  11.     <artifactId>commons-pool2</artifactId> 
  12. </dependency> 

默認(rèn)情況下spring-data-redis使用高性能的lettuce客戶端實(shí)現(xiàn),當(dāng)然你可以替換為老舊的jedis。

4. 緩存及 Redis 配置

緩存以及Redis相關(guān)的配置項(xiàng)分別為spring.cache和spring.redis開(kāi)頭的配置,這里比較簡(jiǎn)單的配置為:

  1. spring: 
  2.   redis: 
  3.     host: localhost 
  4.     port: 6379 
  5.   cache: 
  6. #   type: REDIS 
  7.     redis: 
  8.     # 全局過(guò)期時(shí)間 
  9.       time-to-live: 120 

5. RedisTemplate 個(gè)性化

默認(rèn)情況下會(huì)有兩個(gè)模板類(lèi)被注入Spring IoC供我們使用,需要個(gè)性化配置來(lái)滿足實(shí)際的開(kāi)發(fā)。

一個(gè)是RedisTemplate<Object, Object>,主要用于對(duì)象緩存,其默認(rèn)使用JDK序列化,我們需要更改其序列化方式解決一些問(wèn)題,比如Java 8日期問(wèn)題、JSON序列化問(wèn)題。需要我們重寫(xiě)一下。

  1. /** 
  2.  * Redis的一些自定義配置. 
  3.  * 
  4.  * @author felord.cn 
  5.  * @since 2020 /8/17 20:39 
  6.  */ 
  7. @ConditionalOnClass(ObjectMapper.class) 
  8. @Configuration(proxyBeanMethods = false
  9. public class RedisConfiguration { 
  10.     /** 
  11.      * Redis template redis template. 
  12.      * 
  13.      * @param redisConnectionFactory the redis connection factory 
  14.      * @return the redis template 
  15.      */ 
  16.     @Bean("redisTemplate"
  17.     public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { 
  18.         RedisTemplate<Object, Object> template = new RedisTemplate<>(); 
  19.         template.setConnectionFactory(redisConnectionFactory); 
  20.         // 使用Jackson2JsonRedisSerialize 替換默認(rèn)序列化 
  21.         Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = initJacksonSerializer(); 
  22.         // 設(shè)置value的序列化規(guī)則和 key的序列化規(guī)則 
  23.         template.setValueSerializer(jackson2JsonRedisSerializer); 
  24.         template.setKeySerializer(new StringRedisSerializer()); 
  25.         template.afterPropertiesSet(); 
  26.         return template; 
  27.     } 
  28.  
  29.     /** 
  30.      * 處理redis序列化問(wèn)題 
  31.      * @return Jackson2JsonRedisSerializer 
  32.      */ 
  33.     private Jackson2JsonRedisSerializer<Object> initJacksonSerializer() { 
  34.         Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class); 
  35.         ObjectMapper om = new ObjectMapper(); 
  36.         om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); 
  37.         //以下替代舊版本 om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); 
  38.         om.activateDefaultTyping(om.getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.NON_FINAL); 
  39.         //bugFix Jackson2反序列化數(shù)據(jù)處理LocalDateTime類(lèi)型時(shí)出錯(cuò) 
  40.         om.disable(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS); 
  41.         // java8 時(shí)間支持 
  42.         om.registerModule(new JavaTimeModule()); 
  43.         jackson2JsonRedisSerializer.setObjectMapper(om); 
  44.         return jackson2JsonRedisSerializer; 
  45.     } 
  46.  

另一個(gè)是StringRedisTemplate,主要處理鍵值都是字符串的緩存,采用默認(rèn)就好。

6. 緩存?zhèn)€性化

使用Spring Cache做緩存的時(shí)候,有針對(duì)不同的key設(shè)置不同過(guò)期時(shí)間的場(chǎng)景。比如Jwt Token我想設(shè)置為一周過(guò)期,而驗(yàn)證碼我想設(shè)置為五分鐘過(guò)期。這個(gè)怎么實(shí)現(xiàn)呢?需要我們個(gè)性化配置RedisCacheManager。首先我通過(guò)枚舉來(lái)定義這些緩存及其TTL時(shí)間。例如:

  1. /** 
  2.  * 緩存定義枚舉 
  3.  * 
  4.  * @author felord.cn 
  5.  * @see cn.felord.kono.configuration.CacheConfiguration 
  6.  * @since 2020/8/17 21:40 
  7.  */ 
  8.  
  9. public enum CacheEnum { 
  10.  
  11.     /** 
  12.      * 用戶jwt token 緩存空間 ttl 7天 
  13.      */ 
  14.     JWT_TOKEN_CACHE("usrTkn", 7 * 24 * 60 * 60), 
  15.     /** 
  16.      * 驗(yàn)證碼緩存 5分鐘ttl 
  17.      */ 
  18.     SMS_CAPTCHA_CACHE("smsCode", 5 * 60); 
  19.  
  20.     /** 
  21.      * 緩存名稱(chēng) 
  22.      */ 
  23.     private final String cacheName; 
  24.     /** 
  25.      * 緩存過(guò)期秒數(shù) 
  26.      */ 
  27.     private final int ttlSecond; 
  28.  
  29.     CacheEnum(String cacheName, int ttlSecond) { 
  30.         this.cacheName = cacheName; 
  31.         this.ttlSecond = ttlSecond; 
  32.     } 
  33.  
  34.     public String cacheName() { 
  35.         return this.cacheName; 
  36.     } 
  37.  
  38.  
  39.     public int ttlSecond() { 
  40.         return this.ttlSecond; 
  41.     } 

這樣就能很清楚地描述個(gè)性化的緩存了。

然后我們通過(guò)向Spring IoC分別注入RedisCacheConfiguration和RedisCacheManagerBuilderCustomizer來(lái)個(gè)性化配置,你可以留意CacheEnum是如何工作的。如果你有其它的個(gè)性化需要也可以對(duì)這兩個(gè)配置類(lèi)進(jìn)行定制化。

  1. import cn.felord.kono.enumeration.CacheEnum; 
  2. import org.springframework.boot.autoconfigure.cache.CacheProperties; 
  3. import org.springframework.boot.autoconfigure.cache.RedisCacheManagerBuilderCustomizer; 
  4. import org.springframework.cache.annotation.EnableCaching; 
  5. import org.springframework.context.annotation.Bean; 
  6. import org.springframework.context.annotation.Configuration; 
  7. import org.springframework.data.redis.cache.RedisCacheConfiguration; 
  8. import org.springframework.data.redis.cache.RedisCacheManager; 
  9. import org.springframework.data.redis.core.RedisTemplate; 
  10. import org.springframework.data.redis.serializer.RedisSerializationContext; 
  11.  
  12. import java.time.Duration; 
  13. import java.util.EnumSet; 
  14. import java.util.stream.Collectors; 
  15.  
  16. /** 
  17.  * redis 緩存配置. 
  18.  * 
  19.  * @author felord.cn 
  20.  * @since 2020 /8/17 20:14 
  21.  */ 
  22. @EnableCaching 
  23. @Configuration 
  24. public class CacheConfiguration { 
  25.  
  26.  
  27.     /** 
  28.      * Redis cache configuration. 
  29.      * 
  30.      * @param redisTemplate the redis template 
  31.      * @return the redis cache configuration 
  32.      */ 
  33.     @Bean 
  34.     public RedisCacheConfiguration redisCacheConfiguration(RedisTemplate<Object, Object> redisTemplate, CacheProperties cacheProperties) { 
  35.          // 參見(jiàn) spring.cache.redis 
  36.         CacheProperties.Redis redisProperties = cacheProperties.getRedis(); 
  37.  
  38.         RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig() 
  39.                 // 緩存的序列化問(wèn)題 
  40.                 .serializeValuesWith(RedisSerializationContext.SerializationPair 
  41.                         .fromSerializer(redisTemplate.getValueSerializer())); 
  42.  
  43.         if (redisProperties.getTimeToLive() != null) { 
  44.             // 全局 TTL 時(shí)間 
  45.             redisCacheConfiguration = redisCacheConfiguration.entryTtl(redisProperties.getTimeToLive()); 
  46.         } 
  47.         if (redisProperties.getKeyPrefix() != null) { 
  48.             // key 前綴值 
  49.             redisCacheConfiguration = redisCacheConfiguration.prefixCacheNameWith(redisProperties.getKeyPrefix()); 
  50.         } 
  51.         if (!redisProperties.isCacheNullValues()) { 
  52.             // 默認(rèn)緩存null值 可以防止緩存穿透 
  53.             redisCacheConfiguration = redisCacheConfiguration.disableCachingNullValues(); 
  54.         } 
  55.         if (!redisProperties.isUseKeyPrefix()) { 
  56.             // 不使用key前綴 
  57.             redisCacheConfiguration = redisCacheConfiguration.disableKeyPrefix(); 
  58.         } 
  59.         return redisCacheConfiguration; 
  60.     } 
  61.  
  62.  
  63.     /** 
  64.      * Redis cache manager 個(gè)性化配置緩存過(guò)期時(shí)間. 
  65.      * @see RedisCacheManager,CacheEnum 
  66.      * @return the redis cache manager builder customizer 
  67.      */ 
  68.     @Bean 
  69.     public RedisCacheManagerBuilderCustomizer redisCacheManagerBuilderCustomizer(RedisCacheConfiguration redisCacheConfiguration) { 
  70.  
  71.         return builder -> builder.cacheDefaults(redisCacheConfiguration) 
  72.                 // 自定義的一些緩存配置初始化 主要是特定緩存及其ttl時(shí)間 
  73.                 .withInitialCacheConfigurations(EnumSet.allOf(CacheEnum.class).stream() 
  74.                         .collect(Collectors.toMap(CacheEnum::cacheName, 
  75.                                 cacheEnum -> redisCacheConfiguration.entryTtl(Duration.ofSeconds(cacheEnum.ttlSecond()))))); 
  76.     } 
  77.  

個(gè)性化的同時(shí)我們可以通過(guò)@EnableCaching開(kāi)啟Spring Cache緩存支持。關(guān)于Spring Cache的細(xì)節(jié)可以通過(guò)文章Spring Cache 詳解來(lái)了解。

 

驗(yàn)證Spring Cache Redis緩存?zhèn)€性化

 

請(qǐng)注意,只有通過(guò)Spring Cache操作緩存才會(huì)達(dá)到上圖的效果。命令行操作需要顯式的聲明指令。

7. 總結(jié)

最近事情比較多,所以難得抽出時(shí)間來(lái)搞一搞。如果你在實(shí)際開(kāi)發(fā)中遇到需要整合的功能也可以告訴我,同時(shí)如果你發(fā)現(xiàn)整合中的一些缺陷或者 Bug 請(qǐng)?zhí)峤? ISSUE。多多關(guān)注:碼農(nóng)小胖哥,跟我一起整合開(kāi)發(fā)腳手架。

 本文轉(zhuǎn)載自微信公眾號(hào)「碼農(nóng)小胖哥」,可以通過(guò)以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系碼農(nóng)小胖哥公眾號(hào)。碼農(nóng)小胖哥  

 

責(zé)任編輯:武曉燕 來(lái)源: 碼農(nóng)小胖哥
相關(guān)推薦

2021-07-13 18:42:38

Spring Boot腳手架開(kāi)發(fā)

2021-09-01 10:07:43

開(kāi)發(fā)零搭建Groovy

2021-03-09 17:11:09

數(shù)據(jù)庫(kù)腳手架開(kāi)發(fā)

2021-04-28 16:10:48

開(kāi)發(fā)腳手架 Spring

2021-03-11 14:16:47

Spring Boo開(kāi)發(fā)腳手架

2021-07-29 18:49:49

Spring開(kāi)發(fā)腳手架

2023-11-21 17:36:04

OpenFeignSentinel

2021-05-13 17:02:38

MDC腳手架日志

2021-04-13 14:47:53

認(rèn)證授權(quán)Java

2020-06-29 11:35:02

Spring BootJava腳手架

2021-04-20 19:24:16

腳手架 Java微信

2016-08-10 14:59:41

前端Javascript工具

2021-06-02 17:58:49

腳手架 冪等性前端

2021-02-19 22:43:50

開(kāi)發(fā)腳手架Controller

2017-04-17 10:35:40

Spring BooRedis 操作

2021-01-07 05:34:07

腳手架JDK緩存

2022-07-18 07:58:46

Spring工具工具類(lèi)

2021-12-23 10:35:32

SpringCloud腳手架架構(gòu)

2016-09-07 15:35:06

VueReact腳手架

2014-08-15 09:36:06

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)