日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Spring Boot集成Redis,这个坑把我害惨了!

發布時間:2025/3/11 javascript 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring Boot集成Redis,这个坑把我害惨了! 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

最近項目中使用SpringBoot集成Redis,踩到了一個坑:從Redis中獲取數據為null,但實際上Redis中是存在對應的數據的。是什么原因導致此坑的呢?

本文就帶大家從SpringBoot集成Redis、所踩的坑以及自動配置源碼分析來學習一下SpringBoot中如何正確的使用Redis。

SpringBoot集成Redis

在SpringBoot項目中只需在pom文件中引入Redis對應的starter,配置Redis連接信息即可進行使用了。pom依賴引入:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId> </dependency>

對應application配置文件配置:

spring:redis:host:?127.0.0.1port:?6379database:?1password:?123456timeout:?5000

通過以上兩項配置即完成了Redis的集成,下面便是具體的使用,這里以單元測試的形式呈現。

@SpringBootTest @RunWith(SpringRunner.class) public?class?TokenTest?{@Autowiredprivate?RedisTemplate?redisTemplate;@Testpublic?void?getValue()?{Object?value?=?redisTemplate.opsForValue().get("1");System.out.println("value:"?+?value);} }

可以看到直接通過@Autowired注入RedisTemplate之后,即可調用RedisTemplate提供的方法操作。RedisTemplate提供了豐富的Redis操作方法,具體使用查看相應的API即可,這里不再拓展。

項目中遇到的坑

回歸到最開始的問題:從Redis中獲取數據為null,但實際上Redis中是存在對應的數據的。

其實問題表象很詭異,但問題的原因很簡單,就是Redis中存數據和取數據時采用了不同的RedisTemplate導致的。

在SpringBoot中,針對Redis的自動配置類默認會初始化兩個RedisTemplate,先來看一下RedisAutoConfiguration中源碼:

@Configuration @ConditionalOnClass({RedisOperations.class}) @EnableConfigurationProperties({RedisProperties.class}) @Import({LettuceConnectionConfiguration.class,?JedisConnectionConfiguration.class}) public?class?RedisAutoConfiguration?{@Bean@ConditionalOnMissingBean(name?=?{"redisTemplate"})public?RedisTemplate<Object,?Object>?redisTemplate(RedisConnectionFactory?redisConnectionFactory)?throws?UnknownHostException?{RedisTemplate<Object,?Object>?template?=?new?RedisTemplate();template.setConnectionFactory(redisConnectionFactory);return?template;}@Bean@ConditionalOnMissingBeanpublic?StringRedisTemplate?stringRedisTemplate(RedisConnectionFactory?redisConnectionFactory)?throws?UnknownHostException?{StringRedisTemplate?template?=?new?StringRedisTemplate();template.setConnectionFactory(redisConnectionFactory);return?template;} }

可以看到RedisAutoConfiguration中初始化了兩個RedisTemplate的bean。第一個Bean類型為RedisTemplate<Object, Object>,Bean的名稱為redisTemplate,而且是當容器中不存在對應的Bean name時才會進行初始化。第二Bean類型為StringRedisTemplate,Bean的名稱為stringRedisTemplate,該類繼承自RedisTemplate<String, String>。

也就說一個Bean是針對Object對象處理的,一個是針對String對象進行處理的。

導致出現坑的原因便是set時注入的是RedisTemplate<Object, Object>,而獲取時注入的是StringRedisTemplate。這么明顯的錯誤應該很容易排查的啊?

問題為什么隱藏的那么深?

如果直接是因為兩處類型不一致導致的,的確很好排查,看一下注入的RedisTemplate即可。

但問題難以排查,還因為另外一個因素:@Resource和@Autowired注入的問題。

默認情況下@Resource采用先根據bean名稱注入,找不到再根據類型注入,而@Autowired默認采用根據類型注入。項目獲取數據時采用了@Resource注入方式,如下:

@Resource private?RedisTemplate<String,?String>?redisTemplate;

而存儲時采用的是@Autowired注入的:

@Autowired private?RedisTemplate<String,?String>?redisTemplate;

上面兩種形式的注入,在只存在單個實例時好像并不是什么問題,要么其中一個直接報錯,要么注入成功。但當像上述場景,出現了兩個RedisTemplate時,問題就變得隱蔽了。

當采用@Autowired時,根據類型注入,直接注入了RedisTemplate<String, String>的bean,因為它們的類型都是String的。

而當使用@Resource注入時,默認采用的是根據名稱匹配,源碼中可以看到redisTemplate對應的類型為RedisTemplate<Object, Object>。因此,兩處注入了不同的RedisTemplate,于是就導致了獲取時獲取不到值的問題。

解決方案

找到問題的根源之后,解決問題便容易多了。

方案一,將@Resource的注入改為@Autowired。

方案二:將@Resource注入的bean名稱由redisTemplate改為stringRedisTemplate。當然根據具體業務場景還有其他解決方案。

小結

關于SpringBoot集成Redis其實很簡單,SpringBoot已經幫我們做了大多數的事情,但因為默認初始化了兩個RedisTemplate,再加上@Autowired和@Resource注解的區別就導致了問題的復雜度。因此,在使用的過程中盡量保持各處采用一致的規范,阿里Java開發手冊推薦使用@Resource注解。同時,當然少不了對源碼、注解等的使用的深入學習和了解。

往期推薦

文件寫入的6種方法,這種方法性能最好


線程池的7種創建方式,強烈推薦你用它...


求求你,別再用wait和notify了!


關注我,每天陪你進步一點點!

總結

以上是生活随笔為你收集整理的Spring Boot集成Redis,这个坑把我害惨了!的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。