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

接下來分別針對基于注解的Redis緩存實現(xiàn)和基于API的Redis緩存實現(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緩存實現(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ù)上述源碼信息的分析离咐,可以得到以下兩個重要的結(jié)論:
(1)使用RedisTemplate進(jìn)行Redis數(shù)據(jù)緩存操作時,內(nèi)部默認(rèn)使用的是JdkSerializationRedisSerializer序列化方式奉件,所以進(jìn)行數(shù)據(jù)緩存的實體類必須實現(xiàn)JDK自帶的序列化接口(例如Serializable)宵蛀;
(2)使用RedisTemplate進(jìn)行Redis數(shù)據(jù)緩存操作時,如果自定義了緩存序列化方式defaultSerializer县貌,那么將使用自定義的序列化方式术陶。
?????????另外,在RedisTemplate類源碼中煤痕,看到的緩存數(shù)據(jù)key梧宫、value的各種序列化類型都是RedisSerializer。進(jìn)入RedisSerializer源碼查看RedisSerializer支持的序列化方式(進(jìn)入該類后摆碉,使用Ctrl+Alt+左鍵單擊類名查看)?

?????????可以看出塘匣,RedisSerializer是一個Redis序列化接口,默認(rèn)有6個實現(xiàn)類巷帝,這6個實現(xiàn)類代表了6種不同的數(shù)據(jù)序列化方式忌卤。其中,JdkSerializationRedisSerializer是JDK自帶的楞泼,也是RedisTemplate內(nèi)部默認(rèn)使用的數(shù)據(jù)序列化方式驰徊,開發(fā)者可以根據(jù)需要選擇其他支持的序列化方式(例如JSON方式)?
?2.自定義RedisTemplate序列化機(jī)制
?????????在項目中引入Redis依賴后,Spring
Boot提供的RedisAutoConfiguration自動配置會生效堕阔。打開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自動配置類中超陆,通過Redis連接工廠RedisConnectionFactory初始化了一個RedisTemplate牺弹;該類上方添加了@ConditionalOnMissingBean注解(顧名思義,當(dāng)某個Bean不存在時生效)侥猬,用來表明如果開發(fā)者自定義了一個名為redisTemplate的Bean例驹,則該默認(rèn)初始化的RedisTemplate不會生效。
?????????如果想要使用自定義序列化方式的RedisTemplate進(jìn)行數(shù)據(jù)緩存操作退唠,可以參考上述核心代碼創(chuàng)建一個名為redisTemplate的Bean組件鹃锈,并在該組件中設(shè)置對應(yīng)的序列化方式即可?
?????????接下來,在項目中創(chuàng)建名為com.lagou.config的包瞧预,在該包下創(chuàng)建一個Redis自定義配置類RedisConfig屎债,并按照上述思路自定義名為redisTemplate的Bean組件?
```java
@Configuration
public class RedisConfig {
???@Bean
???public RedisTemplate redisTemplate(RedisConnectionFactory
??????????????????????????????????????????????????????????????redisConnectionFactory) {
???????RedisTemplate template = new RedisTemplate();
???????template.setConnectionFactory(redisConnectionFactory);
???????//使用JSON格式序列化對象仅政,對緩存數(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注解定義了一個RedisConfig配置類,并使用@Bean注解注入了一個默認(rèn)名稱為方法名的redisTemplate組件(注意盆驹,該Bean組件名稱必須是redisTemplate)圆丹。在定義的Bean組件中,自定義了一個RedisTemplate躯喇,使用自定義的Jackson2JsonRedisSerializer數(shù)據(jù)序列化方式辫封;在定制序列化方式中,定義了一個ObjectMapper用于進(jìn)行數(shù)據(jù)轉(zhuǎn)換設(shè)置?
????**3.效果測試**
?????????啟動項目廉丽,項目啟動成功后倦微,通過瀏覽器訪問“http://localhost:8080/api/findCommentById?id=3”查詢id為3的用戶評論信息,并重復(fù)刷新瀏覽器查看同一條數(shù)據(jù)信息?

查看控制臺打印的SQL查詢語句

可以看出正压,執(zhí)行findById()方法正確查詢出用戶評論信息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()方法查詢出用戶評論信息Comment正確存儲到了Redis緩存庫中,且緩存到Redis服務(wù)的數(shù)據(jù)已經(jīng)使用了JSON格式存儲展示嘉裤,查看和管理也非常方便郑临,說明自定義的Redis API模板工具RedisTemplate生效?
剛學(xué)了拉勾教育的《Java工程師高薪訓(xùn)練營》,看到剛學(xué)到的點就回答了价脾。希望拉勾能給我推到想去的公司牧抵,目標(biāo):字節(jié)!侨把!