SpringBoot怎么整合Redis实现序列化存储Java对象

一、背景1、思考

通过我们前面的学习,我们已经可以往 Redis 中存入字符串,那么我们要往 Redis 中存入 Java 对象该怎么办呢?

2、方案

我们可以将 Java 对象转化为 JSON 对象,然后转为 JSON 字符串,存入 Redis,那么我们从 Redis 中取出该数据的时候,我们也只能取出字符串,并转为 Java 对象,这一系列的操作是不是显得有些麻烦呢?

二、源码分析

  • SpringBoot如何与Redis实现序列化存储Java对象

    以上是 RedisAutoConfiguration 类中的源码片段,可以看出 SpringBoot 对 Redis 做自动化配置的时候,在容器中注入了 redisTemplate 和 stringRedisTemplate

  • 其中,RedisTemplate<
    Object, Object>
    表示,key 的类型为 Object,value 的类型为 Object,但是我们往往需要的是 RedisTemplate<
    String, Object>
    ,这就需要我们重新注入一个 RedisTemplate 的 Bean,它的泛型为 RedisTemplate<
    String, Object>
    ,并设置 key,value 的序列化方式

  • 看到这个@ConditionalOnMissingBean注解后,就知道如果Spring容器中有了RedisTemplate对象了,这个自动配置的RedisTemplate不会实例化。因此,我们有能力编写自定义的配置类来为RedisTemplate进行配置。

三、注入RedisTemplate1、引入依赖<
!-- redis -->

<
dependency>

<
groupId>
org.springframework.boot<
/groupId>

<
artifactId>
spring-boot-starter-data-redis<
/artifactId>

<
/dependency>

以上引入了 redis 的依赖,其余依赖请自行添加

2、Redis 连接信息spring:
# Redis配置
redis:
host: 127.0.0.1
port: 6379
database: 10
jedis:
pool:
# 连接池最大连接数(使用负值表示没有限制)
max-active: 50
# 连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: 3000ms
# 连接池中的最大空闲连接数
max-idle: 20
# 连接池中的最小空闲连接数
min-idle: 5
# 连接超时时间(毫秒)
timeout: 5000ms 3、Redis 核心配置类

Redis 的核心配置我们放在 RedisConfig.java 文件中

package com.zyxx.redistest.common;


import com.fasterxml.jackson.annotation.JsonAutoDetect;

import com.fasterxml.jackson.annotation.PropertyAccessor;

import com.fasterxml.jackson.databind.ObjectMapper;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.data.redis.core.RedisTemplate;

import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;

import org.springframework.data.redis.serializer.RedisSerializer;

import org.springframework.data.redis.serializer.StringRedisSerializer;


/**
* @ClassName RedisConfig
* @Description
* @Author Lizhou
* @Date 2020-10-22 9:48:48
**/

@Configuration
public class RedisConfig {

/**
* RedisTemplate配置
*/
@Bean
public RedisTemplate<
Object, Object>
redisTemplate(RedisConnectionFactory redisConnectionFactory) {
// 配置redisTemplate
RedisTemplate<
Object, Object>
redisTemplate = new RedisTemplate<
>
();

redisTemplate.setConnectionFactory(redisConnectionFactory);

// 设置序列化
Jackson2JsonRedisSerializer<
Object>
jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<
>
(Object.class);

ObjectMapper om = new ObjectMapper();

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

om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);

jackson2JsonRedisSerializer.setObjectMapper(om);

// key序列化
redisTemplate.setKeySerializer(new StringRedisSerializer());

// value序列化
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);

// Hash key序列化
redisTemplate.setHashKeySerializer(new StringRedisSerializer());

// Hash value序列化
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);

redisTemplate.afterPropertiesSet();

return redisTemplate;

}
}

我们注入了一个名称为 redisTemplate,类型为 RedisTemplate<
String, Object>
的 Bean,key 采用 StringRedisSerializer 序列化方式,value 采用 Jackson2JsonRedisSerializer 序列化方式

4、Redis工具类

我们将对 Redis 进行的一系列操作放在 RedisUtils.java 文件中

package com.zyxx.redistest.common;


import lombok.extern.slf4j.Slf4j;

import org.apache.commons.lang3.StringUtils;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.data.redis.core.RedisTemplate;

import org.springframework.stereotype.Component;


/**
* @ClassName RedisUtils
* @Description
* @Author Lizhou
* @Date 2020-10-22 10:10:10
**/
@Slf4j
@Component
public class RedisUtils {

@Autowired
private RedisTemplate<
String, Object>
redisTemplate;


/**
* 根据key读取数据
*/
public Object get(final String key) {
if (StringUtils.isBlank(key)) {
return null;

}
try {
return redisTemplate.opsForValue().get(key);

} catch (Exception e) {
e.printStackTrace();

}
return null;

}

/**
* 写入数据
*/
public boolean set(final String key, Object value) {
if (StringUtils.isBlank(key)) {
return false;

}
try {
redisTemplate.opsForValue().set(key, value);

log.info("
存入redis成功,key:{},value:{}"
, key, value);

return true;

} catch (Exception e) {
log.error("
存入redis失败,key:{},value:{}"
, key, value);

e.printStackTrace();

}
return false;

}
}

我们写入了 get,set 两个方法用于测试

四、测试1、创建 Java 实体类 UserInfopackage com.zyxx.redistest.common;


import lombok.Data;


import java.io.Serializable;

import java.util.Date;


/**
* @ClassName UserInfo
* @Description
* @Author Lizhou
* @Date 2020-10-22 10:12:12
**/
@Data
public class UserInfo implements Serializable {
/**
* id
*/
private Integer id;

/**
* 姓名
*/
private String name;

/**
* 创建时间
*/
private Date createTime;

} 2、测试用例package com.zyxx.redistest;


import com.zyxx.redistest.common.RedisUtils;

import com.zyxx.redistest.common.UserInfo;

import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.boot.test.context.SpringBootTest;


import java.util.Date;


@SpringBootTest
class RedisTestApplicationTests {

@Autowired
private RedisUtils redisUtil;


@Test
void contextLoads() {
UserInfo userInfo = new UserInfo();

userInfo.setId(1);

userInfo.setName("
jack"
);

userInfo.setCreateTime(new Date());

// 放入redis
redisUtil.set("
user"
, userInfo);

// 从redis中获取
System.out.println("
获取到数据:"
+ redisUtil.get("
user"
));

}
}

我们向 Redis 中存入了一个 key 为 ”user“,value 为 UserInfo 对象的数据,然后再根据 key 获取该数据

3、测试结果

可以看出,我们往 Redis 中成功存入 Java 对象数据,并成功获取到了该对象。



一、SpringBoot整合Redis
在SpringBoot项目中实现Redis的使用,可以通过引入spring-boot-starter-data-redis依赖,之后配置application.properties文件中的redis相关信息(如host、port等),即可启用Redis。
二、Redis如何序列化Java对象
Redis本身只支持字符串类型的存储,但是可以通过将Java对象进行序列化转换成字符串后存储在Redis中。常用的Java对象序列化方案有:Java自带的序列化方式,JSON、Protobuf等。
三、引入RedisTemplate实现序列化存储
SpringBoot提供了RedisTemplate类,通过引入该类并设置相关序列化策略(如Jackson2JsonRedisSerializer)即可实现Java对象和Redis之间的序列化存储。
四、注意事项
在Java对象序列化存储过程中,需要注意对象可序列化性及占用Redis空间大小等问题。同时,为了防止数据错乱,需要对Redis中的key值进行前缀设置。