将springboot与Redis一起使用时如何将Java对象序列化为json并将Json反向序列化为对象?
How to Serialize Java Object into json and Reverse Json to Object when using springboot with Redis?
我正在使用 SpringBoot 和 Redis 并且想将对象 UserDO 序列化为 Json,将其存储在 Redis 中,并获取 json 数据,将其反转为 UserDO 对象。
这是 UserDO
public class UserDO {
String name;
int age;
String password;
// Getters and Setters are not here
}
这就是我设置序列化程序的方式:
@Configuration
public class RedisTemplateConfiguration {
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
// 使用Jackson2JsonRedisSerialize 替换默认序列化
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
// 设置key和value的序列化规则
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
// 设置hashKey和hashValue的序列化规则
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
// 设置支持事物
//redisTemplate.setEnableTransactionSupport(true);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
}
当我使用 redisTemplate.opsForValue().set("user-service:user:2",userDO);
时有效
但是当我运行uo = (UserDO)redisTemplate.opsForValue().get("user-service:user:2")
我有一个 LinkedHashMap
@Test
void testSeriable(){
User user = new User();
user.setAge(18);
user.setName("William");
user.setPwd("testpwd");
redisTemplate.opsForValue().set("user:2", user);
System.out.println(redisTemplate.opsForValue().get("user:2").getClass());
Map<String, String> res = ((LinkedHashMap<String, String>)redisTemplate.opsForValue().get("user:2"));
System.out.println(res);
/*
class java.util.LinkedHashMap
{name=William, age=18, pwd=testpwd}
*/
redisTemplate.opsForList().leftPushAll("testkey", user, user, user);
List<User> list = redisTemplate.opsForList().range("testkey", 0, -1);
System.out.println(list);
/*
This works fine!
[{name=William, age=18, pwd=testpwd}, {name=William, age=18, pwd=testpwd}, {name=William, age=18, pwd=testpwd}]
*/
}
那么如何直接从 redisTemplate.opsForList().get() 获取用户?
您可以使用特定的 class 对象编写通用方法来序列化数据和反序列化数据
为此我正在使用
com.fasterxml.jackson.databind
您可以将其添加到您的 pom.xml
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.0</version>
</dependency>
并在您的 Redis impl class 中添加这两个方法
public final static String INVALID_SERIALIZATION_OR_DESERIALIZATION = "Invalid type passed for marshalling";
public String serializeData(T modelClass)
throws SerializationOrDeserializationException {
try {
return objectMapper.writeValueAsString(modelClass);
} catch (Exception e) {
LOGGER.error("{}", e);
throw new SerializationOrDeserializationException(INVALID_SERIALIZATION_OR_DESERIALIZATION);
}
}
public T deserializeData(String value, Class<T> type) {
try {
if (value == null) {
return null;
}
return objectMapper.readValue(value, type);
} catch (Exception e) {
LOGGER.error("{}", e);
throw new SerializationOrDeserializationException(INVALID_SERIALIZATION_OR_DESERIALIZATION);
}
}
并且您可以在其中创建自定义异常
public class SerializationOrDeserializationException extends RuntimeException {
public SerializationOrDeserializationException(String message) {
super(message);
}
}
然后您可以按照以下方式使用序列化反序列化
className.deserializeData('json_sring',User.class);
className.serializeData(userObject);
我认为您希望您的模板输入特定类型的密钥和模型,例如:
@Bean
public RedisTemplate<String, Person> redisTemplate() {
RedisTemplate<String, User> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory());
redisTemplate.setEnableTransactionSupport(true);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
return redisTemplate;
}
您的 DTO 对象需要一个主键,以便 SDR 可以使用它来构造一个键。默认情况下,它将是完全限定的 class 名称 +“:”+ 您的 PK。
我正在使用 SpringBoot 和 Redis 并且想将对象 UserDO 序列化为 Json,将其存储在 Redis 中,并获取 json 数据,将其反转为 UserDO 对象。 这是 UserDO
public class UserDO {
String name;
int age;
String password;
// Getters and Setters are not here
} 这就是我设置序列化程序的方式:
@Configuration
public class RedisTemplateConfiguration {
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
// 使用Jackson2JsonRedisSerialize 替换默认序列化
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
// 设置key和value的序列化规则
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
// 设置hashKey和hashValue的序列化规则
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
// 设置支持事物
//redisTemplate.setEnableTransactionSupport(true);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
}
当我使用 redisTemplate.opsForValue().set("user-service:user:2",userDO);
但是当我运行uo = (UserDO)redisTemplate.opsForValue().get("user-service:user:2")
我有一个 LinkedHashMap
@Test
void testSeriable(){
User user = new User();
user.setAge(18);
user.setName("William");
user.setPwd("testpwd");
redisTemplate.opsForValue().set("user:2", user);
System.out.println(redisTemplate.opsForValue().get("user:2").getClass());
Map<String, String> res = ((LinkedHashMap<String, String>)redisTemplate.opsForValue().get("user:2"));
System.out.println(res);
/*
class java.util.LinkedHashMap
{name=William, age=18, pwd=testpwd}
*/
redisTemplate.opsForList().leftPushAll("testkey", user, user, user);
List<User> list = redisTemplate.opsForList().range("testkey", 0, -1);
System.out.println(list);
/*
This works fine!
[{name=William, age=18, pwd=testpwd}, {name=William, age=18, pwd=testpwd}, {name=William, age=18, pwd=testpwd}]
*/
}
那么如何直接从 redisTemplate.opsForList().get() 获取用户?
您可以使用特定的 class 对象编写通用方法来序列化数据和反序列化数据
为此我正在使用
com.fasterxml.jackson.databind
您可以将其添加到您的 pom.xml
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.0</version>
</dependency>
并在您的 Redis impl class 中添加这两个方法
public final static String INVALID_SERIALIZATION_OR_DESERIALIZATION = "Invalid type passed for marshalling";
public String serializeData(T modelClass)
throws SerializationOrDeserializationException {
try {
return objectMapper.writeValueAsString(modelClass);
} catch (Exception e) {
LOGGER.error("{}", e);
throw new SerializationOrDeserializationException(INVALID_SERIALIZATION_OR_DESERIALIZATION);
}
}
public T deserializeData(String value, Class<T> type) {
try {
if (value == null) {
return null;
}
return objectMapper.readValue(value, type);
} catch (Exception e) {
LOGGER.error("{}", e);
throw new SerializationOrDeserializationException(INVALID_SERIALIZATION_OR_DESERIALIZATION);
}
}
并且您可以在其中创建自定义异常
public class SerializationOrDeserializationException extends RuntimeException {
public SerializationOrDeserializationException(String message) {
super(message);
}
}
然后您可以按照以下方式使用序列化反序列化
className.deserializeData('json_sring',User.class);
className.serializeData(userObject);
我认为您希望您的模板输入特定类型的密钥和模型,例如:
@Bean
public RedisTemplate<String, Person> redisTemplate() {
RedisTemplate<String, User> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory());
redisTemplate.setEnableTransactionSupport(true);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
return redisTemplate;
}
您的 DTO 对象需要一个主键,以便 SDR 可以使用它来构造一个键。默认情况下,它将是完全限定的 class 名称 +“:”+ 您的 PK。