最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot混合使用StringRedisTemplate和RedisTemplate的坑及解決

 更新時間:2023年12月20日 16:01:18   作者:程序新視界  
這篇文章主要介紹了SpringBoot混合使用StringRedisTemplate和RedisTemplate的坑及解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教

但在實踐中,有朋友遇到這樣的問題,就是存儲到Redis數(shù)據(jù)取不到值。

兩種Template的源碼分析

這是為什么呢?是因為他同時使用了StringRedisTemplate和RedisTemplate在Redis中存儲和讀取數(shù)據(jù)。

它們最重要的一個區(qū)別就是默認采用的序列化方式不同(在課程中已經(jīng)講到)。

這里我們再來回顧一下相關(guān)源碼,StringRedisTemplate的部分源碼如下:

public class StringRedisTemplate extends RedisTemplate<String, String> {

	/**
	 * Constructs a new <code>StringRedisTemplate</code> instance. {@link #setConnectionFactory(RedisConnectionFactory)}
	 * and {@link #afterPropertiesSet()} still need to be called.
	 */
	public StringRedisTemplate() {
		setKeySerializer(RedisSerializer.string());
		setValueSerializer(RedisSerializer.string());
		setHashKeySerializer(RedisSerializer.string());
		setHashValueSerializer(RedisSerializer.string());
	}
    
}

通過該源碼我們可以看到StringRedisTemplate采用的是RedisSerializer.string()來序列化Redis中存儲數(shù)據(jù)的Key的。

下面再來看看RedisTemplate中默認采用什么形式來序列化對應(yīng)的Key。

public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperations<K, V>, BeanClassLoaderAware {
    // 省略其他源碼
	private @Nullable RedisSerializer<?> defaultSerializer;
	private @Nullable ClassLoader classLoader;

	/*
	 * (non-Javadoc)
	 * @see org.springframework.data.redis.core.RedisAccessor#afterPropertiesSet()
	 */
	@Override
	public void afterPropertiesSet() {

		super.afterPropertiesSet();

		boolean defaultUsed = false;

		if (defaultSerializer == null) {

			defaultSerializer = new JdkSerializationRedisSerializer(
					classLoader != null ? classLoader : this.getClass().getClassLoader());
		}

		if (enableDefaultSerializer) {

			if (keySerializer == null) {
				keySerializer = defaultSerializer;
				defaultUsed = true;
			}
			// 省略其他源碼
		}

		if (enableDefaultSerializer && defaultUsed) {
			Assert.notNull(defaultSerializer, "default serializer null and not all serializers initialized");
		}

		if (scriptExecutor == null) {
			this.scriptExecutor = new DefaultScriptExecutor<>(this);
		}

		initialized = true;
	}
	// 省略其他源碼
    
}

我們可以看到RedisTemplate使用的序列化類為defaultSerializer,默認情況下為JdkSerializationRedisSerializer。

如果未指定Key的序列化類,keySerializer與defaultSerializer采用相同的序列化類。

通過上述兩個Template的分析我們就可以看出它們在Redis存儲的Key,采用了不同的序列化方法。

而且JdkSerializationRedisSerializer序列化時會在Key的前面添加一些特殊字符。

還原測試

下面先看一個單元測試:

@Slf4j
@SpringBootTest
class RedisDifferentTemplateTest {
	@Resource
	private RedisTemplate<String, Object> redisTemplate;

	@Resource
	private StringRedisTemplate stringRedisTemplate;

	@Test
	void testSimple() {
		redisTemplate.opsForValue().set("myWeb", "www.choupangxia.com");
		Assertions.assertEquals("www.choupangxia.com", redisTemplate.opsForValue().get("myWeb"));

		Assertions.assertEquals("www.choupangxia.com",stringRedisTemplate.opsForValue().get("myWeb"));
	}
}

在上述方法中先通過redisTemplate存儲一個key為myWeb的數(shù)據(jù)到Redis中,隨后通過redisTemplate獲取并判斷斷言,可以成功通過。

但隨后通過stringRedisTemplate獲取同樣的key的值,則拋出異常,異常信息如下:

org.opentest4j.AssertionFailedError: 

Expected :www.choupangxia.com

Actual   :null

 <Click to see difference>

也就是說獲取的結(jié)果為null。

那么,我們再通過Redis客戶端看一下兩種形式存儲到redis中key的值的情況。

image

我們可以看到通過StringRedisTemplate存儲的數(shù)據(jù)Key為“myWeb”,而RedisTemplate存儲的Key為“\xAC\xED\x00\x05t\x00\x05myWeb”,這也就是為什么默認情況下兩者存儲的數(shù)據(jù)沒辦法混合使用了。

解決方案

那么,如果在生產(chǎn)環(huán)境中想通用StringRedisTemplate和RedisTemplate進行字符串的處理該怎么辦?

此時就需要指定統(tǒng)一的Key的序列化處理類,比如在RedisTemplate序列化時指定與StringRedisTemplate相同的類。

在上述單元測試中添加如下方法:

@BeforeEach
void init() {
	redisTemplate.setKeySerializer(RedisSerializer.string());
}

也就是設(shè)置RedisTemplate也使用RedisSerializer.string()來序列化Key。注意此處使用的是Junit5。

這樣就解決問題了嗎?沒有。因為RedisTemplate的Value也是采用默認的序列化類,也要進行統(tǒng)一修改。

因此上面的方法變成如下:

@BeforeEach
void init() {
	redisTemplate.setKeySerializer(RedisSerializer.string());
	redisTemplate.setValueSerializer(RedisSerializer.string());
}

總結(jié)

經(jīng)過上述步驟,關(guān)于SpringBoot中混合使用StringRedisTemplate和RedisTemplate的坑已經(jīng)填平了。

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。 

相關(guān)文章

  • MyBatis框架搭建時依賴包引入異常的問題解決

    MyBatis框架搭建時依賴包引入異常的問題解決

    在使用IDEA環(huán)境搭建MyBatis框架時,可能會因為依賴包版本過低導(dǎo)致兼容性問題,本文就來介紹一下MyBatis框架搭建時依賴包引入異常的問題解決,感興趣的可以來了解一下
    2024-10-10
  • Spring?Boot集成Elasticsearch全過程

    Spring?Boot集成Elasticsearch全過程

    這篇文章主要介紹了Spring?Boot集成Elasticsearch全過程,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-07-07
  • Java高級架構(gòu)之FastDFS分布式文件集群詳解

    Java高級架構(gòu)之FastDFS分布式文件集群詳解

    這篇文章主要介紹了Java高級架構(gòu)之FastDFS分布式文件集群詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-04-04
  • 詳解mall整合SpringBoot+MyBatis搭建基本骨架

    詳解mall整合SpringBoot+MyBatis搭建基本骨架

    這篇文章主要介紹了詳解mall整合SpringBoot+MyBatis搭建基本骨架,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-08-08
  • Java責任鏈模式詳解

    Java責任鏈模式詳解

    責任鏈模式(Chain?of?Responsibility?Pattern)是一種行為型設(shè)計模式,它用于將請求的發(fā)送者和接收者解耦,使得多個對象都有機會處理這個請求,本文將詳細介紹?Java?中的責任鏈模式,包括其概念、結(jié)構(gòu)、實現(xiàn)方式以及應(yīng)用案例等,需要的朋友可以參考下
    2023-05-05
  • Eclipse開發(fā)JavaWeb項目配置Tomcat的方法步驟

    Eclipse開發(fā)JavaWeb項目配置Tomcat的方法步驟

    本文主要介紹了Eclipse開發(fā)JavaWeb項目配置Tomcat的方法步驟,首先介紹eclipse開發(fā)JavaWeb項目需要配置的相關(guān)環(huán)境,使用tomcat軟件在本地搭建服務(wù)器,然后再在eclipse環(huán)境下配置tomcat,感興趣的可以了解一下
    2021-08-08
  • SpringBoot集成gRPC微服務(wù)工程搭建實踐的方法

    SpringBoot集成gRPC微服務(wù)工程搭建實踐的方法

    這篇文章主要介紹了SpringBoot集成gRPC微服務(wù)工程搭建實踐的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-01-01
  • 詳解JVM系列之對象的鎖狀態(tài)和同步

    詳解JVM系列之對象的鎖狀態(tài)和同步

    鎖和同步是java多線程編程中非常常見的使用場景。為了鎖定多線程共享的對象,Java需要提供一定的機制來實現(xiàn)共享對象的鎖定。當?shù)诙€線程進入同一個區(qū)域的時候,必須等待第一個線程解鎖該對象。JVM是怎么做到的呢?快來一起看看吧。
    2021-06-06
  • Spring?Boot?3.1中整合Spring?Security和Keycloak的方法

    Spring?Boot?3.1中整合Spring?Security和Keycloak的方法

    本文介紹在最新的SpringBoot3.1版本之下,如何將Keycloak和Spring?Security一起跑起來,文中結(jié)合實例代碼給大家介紹的非常詳細,需要的朋友參考下吧
    2023-06-06
  • Java實現(xiàn)分布式鎖的3種方法總結(jié)

    Java實現(xiàn)分布式鎖的3種方法總結(jié)

    分布式鎖是一種用于保證分布式系統(tǒng)中多個進程或線程同步訪問共享資源的技術(shù),同時它又是面試中的常見問題,所以我們本文就重點來看分布式鎖的具體實現(xiàn),希望對大家有所幫助
    2023-09-09

最新評論

龙门县| 明光市| 清水县| 皋兰县| 淮南市| 宁津县| 三台县| 分宜县| 青浦区| 沛县| 特克斯县| 邯郸市| 内乡县| 城步| 云南省| 西昌市| 闽侯县| 东明县| 天长市| 会东县| 万荣县| 榆林市| 岑溪市| 牡丹江市| 洞头县| 米易县| 布尔津县| 通河县| 鄯善县| 许昌县| 特克斯县| 车险| 新津县| 剑阁县| 贡觉县| 汾西县| 通化市| 渝北区| 大港区| 岳阳县| 永德县|