自定義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)練營(yíng)》,看到剛學(xué)到的點(diǎn)就回答了。希望拉勾能給我推到想去的公司,目標(biāo):字節(jié)!!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,461評(píng)論 6 532
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,538評(píng)論 3 417
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,423評(píng)論 0 375
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,991評(píng)論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,761評(píng)論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,207評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,268評(píng)論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,419評(píng)論 0 288
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,959評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,782評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,983評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,528評(píng)論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,222評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,653評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,901評(píng)論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,678評(píng)論 3 392
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,978評(píng)論 2 374