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é)難精,陽哥說的對(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(這里說一下,你如果沒有引入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.然后訪問 http://localhost:8080/emp/1

500錯(cuò)誤,服務(wù)端有問題,仔細(xì)閱讀報(bào)錯(cuò)信息,是實(shí)體類沒有序列化導(dǎo)致的,好吧,那我就實(shí)現(xiàn)Serializable接口
6.練武不練功,到老一場(chǎng)空,實(shí)現(xiàn)序列化Serializable就可以了嗎?
是可以了,但這只是巧合,再去訪問,確實(shí)可以

去看redis

什么東西啊,看不懂…

但第二次以后確實(shí)走了緩存,離成功又近了一步
再去試一下查所有

也可以
緩存也有

7.為什么實(shí)現(xiàn)Serializable接口就可以了,這就得開始扒源碼了,開始練功…
去看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容器里,也就是說我們可以在我們自己的代碼里注入這兩個(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);
只多了這兩行代碼,其它什么都沒變。
為什么要用Jackson2JsonRedisSerializer呢?
因?yàn)镴ackson2JsonRedisSerializer實(shí)現(xiàn)了RedisSerializer接口

9.再訪問 http://localhost:8080/emp/1

觀察redis

key是我們要的key,value是我們要的value
再刷新頁面

不會(huì)吧?。?!
去緩存找,找到了,反序列化失敗…
轉(zhuǎn)換異常,看來不能用Jackson2JsonRedisSerializer,換成GenericJackson2JsonRedisSerializer
換了之后,刷新頁面

報(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 沒有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ù)來的,我查詢所有,是沒有參數(shù)的,這樣key就為空
if (params.length == 0) {
return SimpleKey.EMPTY;
}
這怎么行,開發(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è)試通過

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)問題
- SpringBoot整合Redis實(shí)現(xiàn)序列化存儲(chǔ)Java對(duì)象的操作方法
相關(guān)文章
Java Stopwatch類,性能與時(shí)間計(jì)時(shí)器案例詳解
這篇文章主要介紹了Java Stopwatch類,性能與時(shí)間計(jì)時(shí)器案例詳解,本篇文章通過簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-09-09
java實(shí)現(xiàn)一個(gè)掃描包的工具類實(shí)例代碼
很多框架,比如springmvc,mybatis等使用注解,為了處理注解,必然要對(duì)包進(jìn)行掃描,所以下面這篇文章主要給大家分享介紹了關(guān)于利用java如何實(shí)現(xiàn)一個(gè)掃描包的工具類,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下。2017-10-10
Java網(wǎng)絡(luò)通信基礎(chǔ)編程(必看篇)
下面小編就為大家?guī)硪黄狫ava網(wǎng)絡(luò)通信基礎(chǔ)編程(必看篇)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-05-05
Elasticsearch中FST與前綴搜索應(yīng)用實(shí)戰(zhàn)解析
這篇文章主要為大家介紹了Elasticsearch中FST與前綴搜索應(yīng)用實(shí)戰(zhàn)解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08

