自定義Redis緩存序列化機(jī)制

5.3?自定義Redis緩存序列化機(jī)制


?????????剛剛完成了Spring Boot整合Redis進(jìn)行了數(shù)據(jù)的緩存管理,但緩存管理的實(shí)體類數(shù)據(jù)使用的是JDK序列化方式,不便于使用可視化管理工具進(jìn)行查看和管理。


![image-20191231142353290](./images/image-20191231142353290.png)


接下來分別針對(duì)基于注解的Redis緩存實(shí)現(xiàn)和基于API的Redis緩存實(shí)現(xiàn)中的數(shù)據(jù)序列化機(jī)制進(jìn)行介紹,并自定義JSON格式的數(shù)據(jù)序列化方式進(jìn)行數(shù)據(jù)緩存管理?


5.3.1?自定義RedisTemplate


1.Redis API默認(rèn)序列化機(jī)制


?????????基于API的Redis緩存實(shí)現(xiàn)是使用RedisTemplate模板進(jìn)行數(shù)據(jù)緩存操作的,這里打開RedisTemplate類,查看該類的源碼信息?


```java

public class RedisTemplate<K, V>

extends RedisAccessor

???????????????????????????????? implementsRedisOperations, BeanClassLoaderAware {

?????? //聲明了key、value的各種序列化方式,初始值為空

???@Nullable

???private RedisSerializer keySerializer = null;

???@Nullable

???private RedisSerializer valueSerializer = null;

??? @Nullable

???private RedisSerializer hashKeySerializer = null;

???@Nullable

???private RedisSerializer hashValueSerializer = null;

?????? ...

?????? //進(jìn)行默認(rèn)序列化方式設(shè)置,設(shè)置為JDK序列化方式

???public void afterPropertiesSet() {

???????super.afterPropertiesSet();

???????boolean defaultUsed = false;

???????if(this.defaultSerializer == null) {

???????????this.defaultSerializer = new JdkSerializationRedisSerializer(

????????????? ?? this.classLoader !=null?this.classLoader:this.getClass().getClassLoader());

???????}

????????????? ...

??? }

?????? ...

}

```


?????????從上述RedisTemplate核心源碼可以看出,在RedisTemplate內(nèi)部聲明了緩存數(shù)據(jù)key、value的各種序列化方式,且初始值都為空;在afterPropertiesSet()方法中,判斷如果默認(rèn)序列化參數(shù)defaultSerializer為空,將數(shù)據(jù)的默認(rèn)序列化方式設(shè)置為JdkSerializationRedisSerializer?


??????? ??? 根據(jù)上述源碼信息的分析,可以得到以下兩個(gè)重要的結(jié)論:


(1)使用RedisTemplate進(jìn)行Redis數(shù)據(jù)緩存操作時(shí),內(nèi)部默認(rèn)使用的是JdkSerializationRedisSerializer序列化方式,所以進(jìn)行數(shù)據(jù)緩存的實(shí)體類必須實(shí)現(xiàn)JDK自帶的序列化接口(例如Serializable);


(2)使用RedisTemplate進(jìn)行Redis數(shù)據(jù)緩存操作時(shí),如果自定義了緩存序列化方式defaultSerializer,那么將使用自定義的序列化方式。


?????????另外,在RedisTemplate類源碼中,看到的緩存數(shù)據(jù)key、value的各種序列化類型都是RedisSerializer。進(jìn)入RedisSerializer源碼查看RedisSerializer支持的序列化方式(進(jìn)入該類后,使用Ctrl+Alt+左鍵單擊類名查看)?


![屏幕快照 2019-12-31 下午4.43.04](/Users/ericsun/Desktop/屏幕快照2019-12-31 下午4.43.04.png)


?????????可以看出,RedisSerializer是一個(gè)Redis序列化接口,默認(rèn)有6個(gè)實(shí)現(xiàn)類,這6個(gè)實(shí)現(xiàn)類代表了6種不同的數(shù)據(jù)序列化方式。其中,JdkSerializationRedisSerializer是JDK自帶的,也是RedisTemplate內(nèi)部默認(rèn)使用的數(shù)據(jù)序列化方式,開發(fā)者可以根據(jù)需要選擇其他支持的序列化方式(例如JSON方式)?




?2.自定義RedisTemplate序列化機(jī)制


?????????在項(xiàng)目中引入Redis依賴后,Spring

Boot提供的RedisAutoConfiguration自動(dòng)配置會(huì)生效。打開RedisAutoConfiguration類,查看內(nèi)部源碼中關(guān)于RedisTemplate的定義方式?


```java

public class RedisAutoConfiguration {

???@Bean

???@ConditionalOnMissingBean(

???????name = {"redisTemplate"}

??? )

???public RedisTemplateredisTemplate(RedisConnectionFactory

?????? ????????????????????????????????redisConnectionFactory) throws UnknownHostException {

???????RedisTemplate template = new RedisTemplate();

???????template.setConnectionFactory(redisConnectionFactory);

???????return template;

??? }

?????? ...

}

```


從上述RedisAutoConfiguration核心源碼中可以看出,在Redis自動(dòng)配置類中,通過Redis連接工廠RedisConnectionFactory初始化了一個(gè)RedisTemplate;該類上方添加了@ConditionalOnMissingBean注解(顧名思義,當(dāng)某個(gè)Bean不存在時(shí)生效),用來表明如果開發(fā)者自定義了一個(gè)名為redisTemplate的Bean,則該默認(rèn)初始化的RedisTemplate不會(huì)生效。


?????????如果想要使用自定義序列化方式的RedisTemplate進(jìn)行數(shù)據(jù)緩存操作,可以參考上述核心代碼創(chuàng)建一個(gè)名為redisTemplate的Bean組件,并在該組件中設(shè)置對(duì)應(yīng)的序列化方式即可?


?????????接下來,在項(xiàng)目中創(chuàng)建名為com.lagou.config的包,在該包下創(chuàng)建一個(gè)Redis自定義配置類RedisConfig,并按照上述思路自定義名為redisTemplate的Bean組件?


```java

@Configuration

public class RedisConfig {


???@Bean

???public RedisTemplate redisTemplate(RedisConnectionFactory

??????????????????????????????????????????????????????????????redisConnectionFactory) {

???????RedisTemplate template = new RedisTemplate();

???????template.setConnectionFactory(redisConnectionFactory);

???????//使用JSON格式序列化對(duì)象,對(duì)緩存數(shù)據(jù)key和value進(jìn)行轉(zhuǎn)換

???????Jackson2JsonRedisSerializer jacksonSeial = newJackson2JsonRedisSerializer(Object.class);


???????//解決查詢緩存轉(zhuǎn)換異常的問題

???????ObjectMapper om = new ObjectMapper();

???????om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);

???????om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);

???????jacksonSeial.setObjectMapper(om);

???????//設(shè)置RedisTemplate模板API的序列化方式為JSON

???????template.setDefaultSerializer(jacksonSeial);

???????return template;

??? }

}

```


?????????通過@Configuration注解定義了一個(gè)RedisConfig配置類,并使用@Bean注解注入了一個(gè)默認(rèn)名稱為方法名的redisTemplate組件(注意,該Bean組件名稱必須是redisTemplate)。在定義的Bean組件中,自定義了一個(gè)RedisTemplate,使用自定義的Jackson2JsonRedisSerializer數(shù)據(jù)序列化方式;在定制序列化方式中,定義了一個(gè)ObjectMapper用于進(jìn)行數(shù)據(jù)轉(zhuǎn)換設(shè)置?


????**3.效果測(cè)試**


?????????啟動(dòng)項(xiàng)目,項(xiàng)目啟動(dòng)成功后,通過瀏覽器訪問“http://localhost:8080/api/findCommentById?id=3”查詢id為3的用戶評(píng)論信息,并重復(fù)刷新瀏覽器查看同一條數(shù)據(jù)信息?


![image-20191231170732322](./images/image-20191231170732322.png)


查看控制臺(tái)打印的SQL查詢語句


![image-20191231170819323](./images/image-20191231170819323.png)


可以看出,執(zhí)行findById()方法正確查詢出用戶評(píng)論信息Comment,重復(fù)進(jìn)行同樣的查詢操作,數(shù)據(jù)庫只執(zhí)行了一次SQL語句,這說明定制的Redis緩存生效。


?????????使用Redis客戶端可視化管理工具Redis

Desktop Manager查看緩存數(shù)據(jù) :


<img src="./images/image-20191231170942007.png"

alt="image-20191231170942007" style="zoom:67%;" />




?????????執(zhí)行findById()方法查詢出用戶評(píng)論信息Comment正確存儲(chǔ)到了Redis緩存庫中,且緩存到Redis服務(wù)的數(shù)據(jù)已經(jīng)使用了JSON格式存儲(chǔ)展示,查看和管理也非常方便,說明自定義的Redis API模板工具RedisTemplate生效?

剛學(xué)了拉勾教育的《Java工程師高薪訓(xùn)練營》,看到剛學(xué)到的點(diǎn)就回答了。希望拉勾能給我推到想去的公司,目標(biāo):字節(jié)!!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容