环境:jdk17、Spring Boot 3.1.3、fastjson2 2.0.41
pom依赖
17 UTF-8 UTF-8 3.1.3 2.0.41 org.springframework.boot spring-boot-starter-web com.alibaba.fastjson2 fastjson2-extension-spring6 ${fastjson2.version} org.springframework.boot spring-boot-starter-data-redis org.springframework.boot spring-boot-starter-parent ${spring-boot.version} pom import
在查找资料的过程中,RedisTemplate的序列化策略大部分是用jackson去实现的,这里我也在这里实现以下
import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator; import jakarta.annotation.Resource; 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; import org.springframework.data.redis.serializer.StringRedisSerializer; @Configuration public class RedisTemplateConfig { @Resource private RedisConnectionFactory redisConnectionFactory; @Bean public RedisTemplateredisTemplate() { // 自定义 String Object RedisTemplate template = new RedisTemplate<>(); // ObjectMapper 转译 ObjectMapper objectMapper = createObjectMapper(); // Json 序列化配置 Jackson2JsonRedisSerializer
如果key不采用stringRedisSerializer方式的话,存储的key会有双引号(“”)而且无法通过key去get到value
Tips:
new Jackson2JsonRedisSerializer<>(objectMapper, Object.class)这个方法是3.0才有的,不是3.0的话使用objectJackson2JsonRedisSerializer.setObjectMapper(objectMapper)才行,到3.0objectJackson2JsonRedisSerializer.setObjectMapper(objectMapper)这个方法已经过时了,所以采用new Jackson2JsonRedisSerializer<>(objectMapper, Object.class)这个方法比较好。
查看Jackson2JsonRedisSerializer的源码知道这个类是实现了RedisSerializer<>的,所以我们也要实现。
先定义一个Fastjson2RedisSerializer并实现RedisSerializer<>:
public class FastJson2RedisSerializerimplements RedisSerializer {}
然后去实现方法,这里加快速度,直接展示成品
import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONReader; import com.alibaba.fastjson2.JSONWriter; import com.alibaba.fastjson2.filter.Filter; import org.apache.commons.lang3.ArrayUtils; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.SerializationException; public class FastJson2RedisSerializerimplements RedisSerializer { static final Filter AUTO_TYPE_FILTER = JSONReader.autoTypeFilter( // 按需加上需要支持自动类型的类名前缀,范围越小越安全 "com.***.***" ); private final Class clazz; public FastJson2RedisSerializer(Class clazz) { super(); this.clazz = clazz; } @Override public byte[] serialize(T t) throws SerializationException { if (t == null) { return new byte[0]; } return JSON.toJSONBytes(t, JSONWriter.Feature.WriteClassName); } @Override public T deserialize(byte[] bytes) throws SerializationException { if (ArrayUtils.isEmpty(bytes)) { return null; } return JSON.parseObject(bytes, clazz, AUTO_TYPE_FILTER); } }
然后再去配置类中实现我们的fastjson2的序列化配置
import jakarta.annotation.Resource; 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.StringRedisSerializer; @Configuration public class RedisTemplateConfig { @Resource private RedisConnectionFactory redisConnectionFactory; @Bean public RedisTemplate
FastJson2RedisSerializer
import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONReader; import com.alibaba.fastjson2.JSONWriter; import com.alibaba.fastjson2.filter.Filter; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ArrayUtils; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.SerializationException; import java.util.Objects; @Slf4j public class FastJson2RedisSerializerimplements RedisSerializer { static final Filter AUTO_TYPE_FILTER = JSONReader.autoTypeFilter( // 按需加上需要支持自动类型的类名前缀,范围越小越安全 "com.***.***" ); private final Class clazz; public FastJson2RedisSerializer(Class clazz) { super(); this.clazz = clazz; } @Override public byte[] serialize(T t) throws SerializationException { if (Objects.isNull(t)) { return new byte[0]; } try { return JSON.toJSONBytes(t, JSONWriter.Feature.WriteClassName); } catch (Exception e) { log.error("Fastjson2 序列化错误:{}", e.getMessage()); throw new SerializationException("无法序列化: " + e.getMessage(), e); } } @Override public T deserialize(byte[] bytes) throws SerializationException { if (ArrayUtils.isEmpty(bytes)) { return null; } try { return JSON.parseObject(bytes, clazz, AUTO_TYPE_FILTER); } catch (Exception e) { log.error("Fastjson2 反序列化错误:{}", e.getMessage()); throw new SerializationException("无法反序列化: " + e.getMessage(), e); } } }