SpringBoot集成Redis,并自定義對(duì)象序列化操作
SpringBoot項(xiàng)目使用redis非常簡(jiǎn)單,pom里面引入redis的場(chǎng)景啟動(dòng)器,在啟動(dòng)類上加@EnableCaching注解,項(xiàng)目啟動(dòng)會(huì)自動(dòng)匹配上redis,這樣項(xiàng)目中就可以愉快地使用了,
使用方法:要么使用@Cacheable一類的注解自動(dòng)緩存,要么使用RedisTemplate手動(dòng)緩存。
(前提是你的本機(jī)或者是遠(yuǎn)程主機(jī)要先搭好redis環(huán)境)
雖然SpringBoot好用,但這里也有好多坑,SpringBoot和MySQL一樣,易學(xué)難精,陽(yáng)哥說(shuō)的對(duì),練武不練功,到老一場(chǎng)空。
下面,我將詳細(xì)記錄整合步驟
1.創(chuàng)建一個(gè)SpringBoot項(xiàng)目
pom文件中引入cache和redis依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
2.新建cache數(shù)據(jù)庫(kù),創(chuàng)建員工表employee
寫好DAO,service,controller,配置文件application.yml中配好數(shù)據(jù)源和redis地址
spring: datasource: driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://localhost:3305/cache username: root password: 123456 redis: host: 127.0.0.1 port: 6379 password: hehuiredis177 mybatis: configuration: map-underscore-to-camel-case: true mapper-locations: - classpath:mybatis/mapper/*.xml debug: true
3.SpringBoot主啟動(dòng)類上加@EnableCaching注解
service類@Cacheable(cacheNames=“employee”)注解
@Service public class EmployeeService { @Autowired private EmployeeDao employeeDao; @Cacheable(cacheNames="employee") public List<Employee> findAll(){ System.out.println("查詢所有員工......"); return employeeDao.findAll(); } @Cacheable(cacheNames="employee--id") public Employee selectEmp(Integer id){ System.out.println("查詢員工:"+id); return employeeDao.selectById(id); } }
4.啟動(dòng)項(xiàng)目(application.yml加上debug:true可以將自動(dòng)配置報(bào)告打印在控制臺(tái)方便觀察)
項(xiàng)目啟動(dòng)時(shí),自動(dòng)配置報(bào)告提示Redis已經(jīng)matched(這里說(shuō)一下,你如果沒(méi)有引入redis而又在啟動(dòng)類上加了@EnableCaching注解,SpringBoot會(huì)自動(dòng)給你匹配一個(gè)SimpleCacheConfiguration緩存,它的底層用了一個(gè)key-value的Map,不能像redis一樣持久化,您得注意,好好權(quán)衡一下用不用,筆者不建議使用,像SQLite、H2這些一樣,玩具型的,只適合個(gè)人博客等非正式場(chǎng)合使用,有輕量級(jí)的優(yōu)點(diǎn),也有不可靠,不好管理的缺點(diǎn))
5.然后訪問(wèn) http://localhost:8080/emp/1
500錯(cuò)誤,服務(wù)端有問(wèn)題,仔細(xì)閱讀報(bào)錯(cuò)信息,是實(shí)體類沒(méi)有序列化導(dǎo)致的,好吧,那我就實(shí)現(xiàn)Serializable接口
6.練武不練功,到老一場(chǎng)空,實(shí)現(xiàn)序列化Serializable就可以了嗎?
是可以了,但這只是巧合,再去訪問(wèn),確實(shí)可以
去看redis
什么東西啊,看不懂…
但第二次以后確實(shí)走了緩存,離成功又近了一步
再去試一下查所有
也可以
緩存也有
7.為什么實(shí)現(xiàn)Serializable接口就可以了,這就得開(kāi)始扒源碼了,開(kāi)始練功…
去看RedisTemplate這個(gè)類
對(duì)象默認(rèn)實(shí)現(xiàn)序列化
怎么實(shí)現(xiàn)的呢?
接著往下看
默認(rèn)用的是jdk的序列化機(jī)制
所以實(shí)現(xiàn)Serializable接口就可以,巧合!??!
8.繼續(xù)練功
redis里這么亂,看不懂,這顯然不是我們想要的,我們要的是json,輕量易讀的json才是我們的目標(biāo),欲存json,必須改變序列化機(jī)制,把jdk的序列化替換掉
繼續(xù)讀源碼
找到RedisAutoConfiguration這個(gè)類,看它是怎么自動(dòng)配置的
里面有個(gè)內(nèi)部類RedisConfiguration
初始化的時(shí)候,把RedisTemplate和StringRedisTemplate放在了IOC容器里,也就是說(shuō)我們可以在我們自己的代碼里注入這兩個(gè)類,然后手動(dòng)緩存
而@Cacheable注解使用的是RedisTemplate,那么分析一下RedisTemplate
@Bean @ConditionalOnMissingBean(name = "redisTemplate") public RedisTemplate<Object, Object> redisTemplate( RedisConnectionFactory redisConnectionFactory) throws UnknownHostException { RedisTemplate<Object, Object> template = new RedisTemplate<Object, Object>(); template.setConnectionFactory(redisConnectionFactory); return template; }
RedisTemplate<Object, Object> template = new RedisTemplate<Object, Object>();
直接new了一個(gè)RedisTemplate然后把它返回,呵呵!就從這里入手
@ConditionalOnMissingBean(name = “redisTemplate”)
表示我們可以自定義RedisTemplate,我們有RedisTemplate,就用我們的,否則就用默認(rèn),我們不喜歡你的,要json就要自己配一個(gè)RedisTemplate
自己寫
package com.hehui.config; import java.net.UnknownHostException; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; /** * 自定義redis配置 * @author hehui * @date 2019年3月12日 * */ @Configuration public class MyRedisConfig { @Bean public RedisTemplate<Object, Object> redisTemplate( RedisConnectionFactory redisConnectionFactory) throws UnknownHostException { RedisTemplate<Object, Object> template = new RedisTemplate<Object, Object>(); template.setConnectionFactory(redisConnectionFactory); Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class); template.setDefaultSerializer(serializer); return template; } }
Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer<>(Object.class); template.setDefaultSerializer(serializer);
只多了這兩行代碼,其它什么都沒(méi)變。
為什么要用Jackson2JsonRedisSerializer呢?
因?yàn)镴ackson2JsonRedisSerializer實(shí)現(xiàn)了RedisSerializer接口
9.再訪問(wèn) http://localhost:8080/emp/1
觀察redis
key是我們要的key,value是我們要的value
再刷新頁(yè)面
不會(huì)吧?。?!
去緩存找,找到了,反序列化失敗…
轉(zhuǎn)換異常,看來(lái)不能用Jackson2JsonRedisSerializer,換成GenericJackson2JsonRedisSerializer
換了之后,刷新頁(yè)面
報(bào)錯(cuò)信息變了,這是不能讀取json,現(xiàn)在redis里的json是Jackson2JsonRedisSerializer序列化的,
GenericJackson2JsonRedisSerializer當(dāng)然不認(rèn)識(shí)咯,清了redis再試
好了。
10.試試查所有 http://localhost:8080/list
報(bào)錯(cuò)?。?!
SimpleKey and no properties discovered 沒(méi)有key 什么情況?
于是繼續(xù)讀源碼,看key是咋生成的
/** * Generate a key based on the specified parameters. */ public static Object generateKey(Object... params) { if (params.length == 0) { return SimpleKey.EMPTY; } if (params.length == 1) { Object param = params[0]; if (param != null && !param.getClass().isArray()) { return param; } } return new SimpleKey(params); }
是根據(jù)參數(shù)來(lái)的,我查詢所有,是沒(méi)有參數(shù)的,這樣key就為空
if (params.length == 0) { return SimpleKey.EMPTY; }
這怎么行,開(kāi)發(fā)中,不傳參的方法多的很,這樣生成key肯定不行撒
于是重寫key的生成策略,用【類名+方法名+參數(shù)名】這樣就可以保證key不為空
package com.hehui.config; import java.lang.reflect.Method; import java.net.UnknownHostException; import java.util.Arrays; import org.springframework.cache.annotation.CachingConfigurerSupport; import org.springframework.cache.interceptor.KeyGenerator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; /** * 自定義redis配置 * @author hehui * @date 2019年3月12日 * */ @Configuration public class MyRedisConfig extends CachingConfigurerSupport{ @Bean public RedisTemplate<Object, Object> redisTemplate( RedisConnectionFactory redisConnectionFactory) throws UnknownHostException { RedisTemplate<Object, Object> template = new RedisTemplate<Object, Object>(); template.setConnectionFactory(redisConnectionFactory); // Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class); GenericJackson2JsonRedisSerializer serializer = new GenericJackson2JsonRedisSerializer(); template.setDefaultSerializer(serializer); return template; } @Bean @Override public KeyGenerator keyGenerator() { return new KeyGenerator() { public Object generate(Object target, Method method, Object... objects) { StringBuilder sb = new StringBuilder(); sb.append(target.getClass().getName()).append(".").append(method.getName()).append(Arrays.toString(objects)); return sb.toString(); } }; } }
extends CachingConfigurerSupport并重寫keyGenerator方法
測(cè)試通過(guò)
redis
json中還帶有@Class相當(dāng)好。
11.好啦,相當(dāng)曲折地把redis整合并自定義配置到SpringBoot中。
源碼github地址:https://github.com/hehuihh/springboot_redis
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- Springboot下RedisTemplate的兩種序列化方式實(shí)例詳解
- SpringBoot自定義Redis實(shí)現(xiàn)緩存序列化詳解
- SpringBoot結(jié)合Redis實(shí)現(xiàn)序列化的方法詳解
- SpringBoot整合redis中的JSON序列化文件夾操作小結(jié)
- SpringBoot Redis配置Fastjson進(jìn)行序列化和反序列化實(shí)現(xiàn)
- springBoot集成redis的key,value序列化的相關(guān)問(wèn)題
- SpringBoot整合Redis實(shí)現(xiàn)序列化存儲(chǔ)Java對(duì)象的操作方法
相關(guān)文章
SpringMVC靜態(tài)資源訪問(wèn)問(wèn)題如何解決
這篇文章主要介紹了SpringMVC靜態(tài)資源訪問(wèn)問(wèn)題如何解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-11-11Java Stopwatch類,性能與時(shí)間計(jì)時(shí)器案例詳解
這篇文章主要介紹了Java Stopwatch類,性能與時(shí)間計(jì)時(shí)器案例詳解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-09-09java實(shí)現(xiàn)一個(gè)掃描包的工具類實(shí)例代碼
很多框架,比如springmvc,mybatis等使用注解,為了處理注解,必然要對(duì)包進(jìn)行掃描,所以下面這篇文章主要給大家分享介紹了關(guān)于利用java如何實(shí)現(xiàn)一個(gè)掃描包的工具類,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下。2017-10-10Java網(wǎng)絡(luò)通信基礎(chǔ)編程(必看篇)
下面小編就為大家?guī)?lái)一篇Java網(wǎng)絡(luò)通信基礎(chǔ)編程(必看篇)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-05-05kafka監(jiān)聽(tīng)問(wèn)題的解決和剖析
這篇文章主要給大家介紹了關(guān)于kafka監(jiān)聽(tīng)問(wèn)題的解決和剖析的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12Elasticsearch中FST與前綴搜索應(yīng)用實(shí)戰(zhàn)解析
這篇文章主要為大家介紹了Elasticsearch中FST與前綴搜索應(yīng)用實(shí)戰(zhàn)解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08解決JSON.toJSONString首字母大小寫的問(wèn)題
這篇文章主要介紹了解決JSON.toJSONString首字母大小寫的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-02-02