0


Jackson 2.x 系列【29】Spring Boot 集成之 Redis 序列化/反序列化

有道无术,术尚可求,有术无道,止于术。

本系列Jackson 版本 2.17.0

本系列Spring Boot 版本 3.2.4

源码地址:https://gitee.com/pearl-organization/study-jaskson-demo

文章目录

1. 前言

Redis

是一个常用的高性能非关系型内存数据库,接下来我们学习在

Spring Boot

中使用

Redis

时,集成基于

Jackson

序列化/反序列化

2. RedisTemplate

RedisTemplate

是在

Spring Boot

环境中和

Redis

打交道的一个模板类,简化了与

Redis

数据库的交互过程,我们可以更加便捷地进行

Redis

的各种操作,如数据存取、异常处理及序列化等。

StringRedisTemplate

RedisTemplate

的一个扩展,由于大多数针对

Redis

的操作都是基于字符串的,所以提供了一个专用的类来处理这些操作。

Spring Boot

自动配置中,已经帮我们注册了这个两个对象,使用时直接注入即可:

@AutoConfiguration@ConditionalOnClass(RedisOperations.class)@EnableConfigurationProperties(RedisProperties.class)@Import({LettuceConnectionConfiguration.class,JedisConnectionConfiguration.class})publicclassRedisAutoConfiguration{@Bean@ConditionalOnMissingBean(RedisConnectionDetails.class)PropertiesRedisConnectionDetailsredisConnectionDetails(RedisProperties properties){returnnewPropertiesRedisConnectionDetails(properties);}@Bean@ConditionalOnMissingBean(name ="redisTemplate")@ConditionalOnSingleCandidate(RedisConnectionFactory.class)publicRedisTemplate<Object,Object>redisTemplate(RedisConnectionFactory redisConnectionFactory){RedisTemplate<Object,Object> template =newRedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);return template;}@Bean@ConditionalOnMissingBean@ConditionalOnSingleCandidate(RedisConnectionFactory.class)publicStringRedisTemplatestringRedisTemplate(RedisConnectionFactory redisConnectionFactory){returnnewStringRedisTemplate(redisConnectionFactory);}}

3. RedisSerializer

Spring Data

声明了

RedisSerializer

接口,用于处理

Redis

序列化/反序列化,定义了相应的操作方法:

publicinterfaceRedisSerializer<T>{// 静态方法,直接返回不同类型的 RedisSerializer 实例staticRedisSerializer<Object>java(){returnjava((ClassLoader)null);}staticRedisSerializer<Object>java(@NullableClassLoader classLoader){returnnewJdkSerializationRedisSerializer(classLoader);}staticRedisSerializer<Object>json(){returnnewGenericJackson2JsonRedisSerializer();}staticRedisSerializer<String>string(){returnStringRedisSerializer.UTF_8;}staticRedisSerializer<byte[]>byteArray(){returnByteArrayRedisSerializer.INSTANCE;}// 序列化@Nullablebyte[]serialize(@NullableT value)throwsSerializationException;// 反序列化@NullableTdeserialize(@Nullablebyte[] bytes)throwsSerializationException;defaultbooleancanSerialize(Class<?> type){returnClassUtils.isAssignable(this.getTargetType(), type);}defaultClass<?>getTargetType(){returnObject.class;}}

默认提供了多种

RedisSerializer

实现:

在这里插入图片描述

简要说明

  • JdkSerializationRedisSerializer :默认配置,使用JDK自带的序列化机制将Java对象序列化为字节数组
  • OxmSerializer:用于序列化和反序列化XML数据
  • ByteArrayRedisSerializer:用于处理字节数组二进制数据,无需进行复杂的对象到字符串的转换,适用于大量二进制数据操作
  • StringRedisSerializer:将Java对象序列化为Redis可以存储的字符串形式
  • GenericToStringSerializer:通用的序列化器类,是将任意类型的数据对象转换为字符串形式,调用对象的toString()方法或自定义的序列化方法来获取字符串表示
  • GenericJackson2JsonRedisSerializer:将Java对象序列化为JSON格式的字符串形式,不需要设置类型信息,能够处理更多的动态类型,灵活性扩展性较低
  • Jackson2JsonRedisSerializer: 将Java对象序列化为JSON格式的字符串形式,必须提供要序列化对象的类型信息,每个类型都创建一个序列化器实例

3.1 JdkSerializationRedisSerializer

JdkSerializationRedisSerializer

使用

JDK

自带的序列化机制,序列化

Java

对象为字节数组,反序列化字节数组为

Java

对象,是默认的选项。使用时,

Java

对象需要实现

Serializable

接口,存储的数据是不可读的。

核心方法如下:

// 反序列化 publicObjectdeserialize(@Nullablebyte[] bytes){if(SerializationUtils.isEmpty(bytes)){returnnull;}else{try{returnthis.deserializer.convert(bytes);}catch(Exception var3){thrownewSerializationException("Cannot deserialize", var3);}}}// 序列化publicbyte[]serialize(@NullableObject object){if(object ==null){returnSerializationUtils.EMPTY_ARRAY;}else{try{return(byte[])this.serializer.convert(object);}catch(Exception var3){thrownewSerializationException("Cannot serialize", var3);}}}

这里使用默认提供的

RedisTemplate

进行存取操作:

@AutowiredRedisTemplate<Object,Object> redisTemplate;@TestvoidtestRedisTemplate(){UserVO userVO =newUserVO();
        userVO.setId(1699657986705854464L);
        userVO.setUsername("jack");
        userVO.setBirthday(newDate());List<String> roleList =newArrayList<>();
        roleList.add("管理员");
        roleList.add("经理");
        userVO.setRoleList(roleList);
        redisTemplate.opsForValue().set("userVO", userVO);// 查询UserVO o =(UserVO)redisTemplate.opsForValue().get("userVO");System.out.println(o);}

Redis

中可以看到存储的键值都是不可读的:

在这里插入图片描述

3.2 Jackson2JsonRedisSerializer

Jackson2JsonRedisSerializer

是基于

Jackson

实现的序列化器,序列化

Java

对象为

JSON

字符串,反序列化

JSON

字符串为

Java

对象。使用

JSON

字符串存储,结构清晰,容易阅读,存储的字节少,速度快,并且支持规则配置。

可以看到内部维护了一个

ObjectMapper 

publicclassJackson2JsonRedisSerializer<T>implementsRedisSerializer<T>{privateObjectMapper mapper;privatefinalJacksonObjectReader reader;privatefinalJacksonObjectWriter writer;// 序列化publicTdeserialize(@Nullablebyte[] bytes)throwsSerializationException{if(SerializationUtils.isEmpty(bytes)){returnnull;}else{try{returnthis.reader.read(this.mapper, bytes,this.javaType);}catch(Exception var3){thrownewSerializationException("Could not read JSON: "+ var3.getMessage(), var3);}}}// 反序列化publicbyte[]serialize(@NullableObject t)throwsSerializationException{if(t ==null){returnSerializationUtils.EMPTY_ARRAY;}else{try{returnthis.writer.write(this.mapper, t);}catch(Exception var3){thrownewSerializationException("Could not write JSON: "+ var3.getMessage(), var3);}}}}

4. 案例演示

接下来我们演示如何配置

Jackson2JsonRedisSerializer

4.1 创建 RedisTemplate

首先需要创建

RedisTemplate

并注册到容器中,指定泛型为

<String, Object>

,因为

Redis

是一个键值存储数据库,键直接使用字符串即可,而值一般都是多种类型的,统一用

Object

表示。

@Bean("redisTemplate")publicRedisTemplate<String,Object>redisTemplate(RedisConnectionFactory factory){RedisTemplate<String,Object> redisTemplate =newRedisTemplate<>();
        redisTemplate.setConnectionFactory(factory);// 设置连接工厂}

4.2 创建 ObjectMapper

创建

ObjectMapper

对象,可以根据需求进行相应的配置:

// 创建 ObjectMapperObjectMapper objectMapper =Jackson2ObjectMapperBuilder.json().serializationInclusion(JsonInclude.Include.NON_NULL)// 不为 null 才序列化.visibility(PropertyAccessor.FIELD,JsonAutoDetect.Visibility.ANY)// 可见性,只序列化任意修饰符的字段.indentOutput(true)// 美化格式.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)// 关闭某个特征.build();// 启用自动包含类型信息,用于反序列化时重建对象的实际类型
        objectMapper.activateDefaultTyping(
                objectMapper.getPolymorphicTypeValidator(),//  验证器,用于验证实际要反序列化的子类型是否有效ObjectMapper.DefaultTyping.NON_FINAL,// 定义哪些类型的对象需要添加额外的类型信息,NON_FINAL:非 final类都会包含JsonTypeInfo.As.PROPERTY);// 类型信息的包含方式 PROPERTY:类型信息作为JSON对象的一个属性

4.3 创建 Jackson2JsonRedisSerializer

创建

Jackson2JsonRedisSerializer

,并设置创建好的

ObjectMapper

对象:

// 创建 Jackson2JsonRedisSerializerJackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer =newJackson2JsonRedisSerializer<>(objectMapper,Object.class);

4.4 设置序列化器

设置

Key

的序列化器为

StringRedisSerializer

,设置值的序列化器为

Jackson2JsonRedisSerializer

// 设置键值的序列化器
        redisTemplate.setKeySerializer(newStringRedisSerializer());
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);// 设置Hash 键值的序列化器
        redisTemplate.setHashKeySerializer(newStringRedisSerializer());
        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);

最终代码如下所示:

@ConfigurationpublicclassRedisConfig{@Bean("redisTemplate")publicRedisTemplate<String,Object>redisTemplate(RedisConnectionFactory factory){// 创建 RedisTemplateRedisTemplate<String,Object> redisTemplate =newRedisTemplate<>();
        redisTemplate.setConnectionFactory(factory);// 设置连接工厂// 创建 ObjectMapperObjectMapper objectMapper =Jackson2ObjectMapperBuilder.json().serializationInclusion(JsonInclude.Include.NON_NULL)// 不为 null 才序列化.visibility(PropertyAccessor.FIELD,JsonAutoDetect.Visibility.ANY)// 可见性,只序列化任意修饰符的字段.indentOutput(true)// 美化格式.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)// 关闭某个特征.build();// 启用自动包含类型信息,用于反序列化时重建对象的实际类型
        objectMapper.activateDefaultTyping(
                objectMapper.getPolymorphicTypeValidator(),//  验证器,用于验证实际要反序列化的子类型是否有效ObjectMapper.DefaultTyping.NON_FINAL,// 定义哪些类型的对象需要添加额外的类型信息,NON_FINAL:非 final类都会包含JsonTypeInfo.As.PROPERTY);// 类型信息的包含方式 PROPERTY:类型信息作为JSON对象的一个属性// 创建 Jackson2JsonRedisSerializerJackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer =newJackson2JsonRedisSerializer<>(objectMapper,Object.class);// 设置键值的序列化器
        redisTemplate.setKeySerializer(newStringRedisSerializer());
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);// 设置Hash 键值的序列化器
        redisTemplate.setHashKeySerializer(newStringRedisSerializer());
        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);return redisTemplate;}}}

4.5 测试

注入

RedisTemplate

并执行存取操作:

@AutowiredRedisTemplate<String,Object> redisTemplate;

查看

Redis


在这里插入图片描述


本文转载自: https://blog.csdn.net/qq_43437874/article/details/137730379
版权归原作者 云烟成雨TD 所有, 如有侵权,请联系我们删除。

“Jackson 2.x 系列【29】Spring Boot 集成之 Redis 序列化/反序列化”的评论:

还没有评论