繁体   English   中英

将springboot与Redis一起使用时,如何将Java对象序列化为json并将Json反转为对象?

[英]How to Serialize Java Object into json and Reverse Json to Object when using springboot with Redis?

我正在使用带有Redis的SpringBoot并且想将对象UserDO序列化为Json,将其存储在Redis中,并获取json数据,将其反转为UserDO对象。 这是用户DO

public class UserDO {
String name;
int age;
String password;

// Getters and Setters are not here 

这就是我设置序列化程序的方式:

@Configuration

公共类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() 获取 User 呢?

您可以编写通用方法来使用特定的类对象序列化数据和反序列化数据

为此,我正在使用

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 类中添加这两个方法

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 可以使用它来构造键。 默认情况下,它将是完全限定的类名 + ":" + 您的 PK。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM