Redis反序列化或前后端传参时关于Date相关类的序列化和反序列化

转化的工具类

  • 因为多个地方要用 所以剥离出来
public class ObjectMapperUtils {

    public static void registerTimeModule(ObjectMapper objectMapper){
        //      objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        //      objectMapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE);


        JavaTimeModule javaTimeModule = new JavaTimeModule();


        /**
         * 演示:Date序列化为时间戳
         *
         * 通过继承JsonSerializer<Type> 抽象类(注意是泛型), 实现serialize方法实现
         * 要被序列化的内容是:第一个参数
         * 序列化的后内容是:jsonGenerator.writeString() 里的内容
         */
 /*       javaTimeModule.addSerializer(Date.class, new JsonSerializer<Date>() {
            @Override
            public void serialize(Date value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
                gen.writeString(String.valueOf(value.getTime()));
            }
        });
*/
        /**
         * 演示:时间戳反序列Date
         *
         * 通过继承JsonDeserializer<Type> 抽象类(注意是泛型), 实现deserialize 方法实现
         * 要被反序列化的内容:JsonParser.getText()
         * 反序列化后的内容是:返回值
         */
 /*
        javaTimeModule.addDeserializer(Date.class, new JsonDeserializer<Date>() {
            @Override
            public Date deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
                String value = p.getText();
                Long time=Long.valueOf(value);
                Date date=new Date(time);
                return date;
            }
        });
 */

        //LocalDateTime系列序列化和反序列化模块,继承自jsr310,我们在这里修改了日期格式
        javaTimeModule.addSerializer(LocalDateTime.class,new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)));
        javaTimeModule.addSerializer(LocalDate.class,new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)));
        javaTimeModule.addSerializer(LocalTime.class,new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));
        javaTimeModule.addDeserializer(LocalDateTime.class,new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)));
        javaTimeModule.addDeserializer(LocalDate.class,new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)));
        javaTimeModule.addDeserializer(LocalTime.class,new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));


        //Date序列化和反序列化
        javaTimeModule.addSerializer(Date.class, new JsonSerializer<Date>() {
            @Override
            public void serialize(Date date, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
                SimpleDateFormat formatter = new SimpleDateFormat(DEFAULT_DATE_TIME_FORMAT);
                String formattedDate = formatter.format(date);
                jsonGenerator.writeString(formattedDate);
            }
        });
        javaTimeModule.addDeserializer(Date.class, new JsonDeserializer<Date>() {
            @Override
            public Date deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
                SimpleDateFormat format = new SimpleDateFormat(DEFAULT_DATE_TIME_FORMAT);
                String date = jsonParser.getText();
                try {
                    return format.parse(date);
                } catch (ParseException e) {
                    throw new RuntimeException(e);
                }
            }
        });



        objectMapper.registerModule(javaTimeModule);
    }
}


前后端传参时的配置类


/**
 * spring传递对象时 转化时间类型
 */
@Configuration
public class DateConvertConfig {

    /** 默认日期时间格式 */
    public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
    /** 默认日期格式 */
    public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
    /** 默认时间格式 */
    public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";


    /**
     * 演示:时间戳转化为Date
     *
     * 注入转换器Converter< , >
     * 泛型的第一个参数是转换前的类型 泛型的第二个参数是转换后的类型
     */
/*
    @Bean
    public Converter<Long,Date> dateConverterByTimestap(){
        return new Converter<Long, Date>() {
            @Override
            public Date convert(Long source) {
                return new Date(source);
            }
        };
    }
*/

    /**
     * LocalDate转换器,用于转换RequestParam和PathVariable参数
     */
    @Bean
    public Converter<String, LocalDate> localDateConverter() {
        return new Converter<String, LocalDate>() {
            @Override
            public LocalDate convert(String source) {
                return LocalDate.parse(source, DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT));
            }
        };
    }

    /**
     * LocalDateTime转换器,用于转换RequestParam和PathVariable参数
     */
    @Bean
    public Converter<String, LocalDateTime> localDateTimeConverter() {
        return new Converter<String, LocalDateTime>() {
            @Override
            public LocalDateTime convert(String source) {
                return LocalDateTime.parse(source, DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT));
            }
        };
    }

    /**
     * LocalTime转换器,用于转换RequestParam和PathVariable参数
     */
    @Bean
    public Converter<String, LocalTime> localTimeConverter() {
        return new Converter<String, LocalTime>() {
            @Override
            public LocalTime convert(String source) {
                return LocalTime.parse(source, DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT));
            }
        };
    }

    /**
     * Date转换器,用于转换RequestParam和PathVariable参数
     */
    @Bean
    public Converter<String, Date> dateConverterByFormate() {
        return new Converter<String,Date>(){
            @Override
            public Date convert(String source) {
                SimpleDateFormat format = new SimpleDateFormat(DEFAULT_DATE_TIME_FORMAT);
                try {
                    return format.parse(source);
                } catch (ParseException e) {
                    throw new RuntimeException(e);
                }
            }
        };
    }

    /**
     * Json序列化和反序列化转换器,用于转换Post请求体中的json以及将我们的对象序列化为返回响应的json
     */
    @Bean
    public ObjectMapper objectMapper(){
        ObjectMapper objectMapper = new ObjectMapper();
        ObjectMapperUtils.registerTimeModule(objectMapper);
        return objectMapper;
    }


}

Redis种存储时

@Configuration
@EnableCaching
public class RedisConfig {

    @Bean
    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory){
        RedisTemplate<String, String> redisTemplate = new RedisTemplate<String,String>();
        redisTemplate.setConnectionFactory(factory);

        // 使用Jackson2JsonRedisSerialize 替换默认序列化
        /**Jackson序列化  json占用的内存最小 */
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        /**
         * 配置时间类的序列化与反序列化
         * /
        ObjectMapperUtils.registerTimeModule(om);
        jackson2JsonRedisSerializer.setObjectMapper(om);

        /**Jdk序列化   JdkSerializationRedisSerializer是最高效的*/
        // JdkSerializationRedisSerializer jdkSerializationRedisSerializer = new JdkSerializationRedisSerializer();

        /**String序列化*/
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

        //设置序列化类型
        /**将key value 进行stringRedisSerializer序列化*/
        redisTemplate.setKeySerializer(stringRedisSerializer);
        redisTemplate.setValueSerializer(stringRedisSerializer);

        /**将HashKey HashValue 进行序列化*/
        redisTemplate.setHashKeySerializer(stringRedisSerializer);
        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);

        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

    //配置Redis作二级缓存:注入redis中key的生成方式 到时可以在方法的注解上直接调用
    @Bean
    public KeyGenerator simpleKeyGenerator() {
        return (o, method, objects) -> {
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append(o.getClass().getSimpleName());
            stringBuilder.append(".");
            stringBuilder.append(method.getName());
            stringBuilder.append("[");
            for (Object obj : objects) {
                stringBuilder.append(obj.toString());
            }
            stringBuilder.append("]");

            return stringBuilder.toString();
        };
    }

    //配置Redis作二级缓存:配置CacheManager
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
        return new RedisCacheManager(
                RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory),
                //TODO 180
                this.getRedisCacheConfigurationWithTtl(60), // 默认策略,未配置的 key 会使用这个
                this.getRedisCacheConfigurationMap() // 指定 key 策略
        );
    }

    //配置Redis作二级缓存:自定缓存策略
    private Map<String, RedisCacheConfiguration> getRedisCacheConfigurationMap() {
        Map<String, RedisCacheConfiguration> redisCacheConfigurationMap = new HashMap<>();
        /**
         *可以通过@Cacheable、@CachPut、@CachEvict注解中的value找到对应方法 然后设置过期时间
         */
        //redisCacheConfigurationMap.put("注解中value的值", this.getRedisCacheConfigurationWithTtl(100));//单位是秒
        return redisCacheConfigurationMap;
    }

    //配置Redis作二级缓存:给自定缓存策略设置序列化方式以及过期时间
    private RedisCacheConfiguration getRedisCacheConfigurationWithTtl(Integer seconds) {
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper om = new ObjectMapper();
         /**
         * 配置时间类的序列化与反序列化
         * /
        ObjectMapperUtils.registerTimeModule(om);
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);


        RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig();
        redisCacheConfiguration = redisCacheConfiguration.serializeValuesWith(
                //设置序列化方式
                RedisSerializationContext
                        .SerializationPair
                        .fromSerializer(jackson2JsonRedisSerializer)
        ).entryTtl(Duration.ofSeconds(seconds));  //设置过期时间

        return redisCacheConfiguration;
    }

}
  • 注意

    • 一个类型只能默认生效一个转化器、一个序列化转化器、一个反序列化转化器
    • 要使用配置好的序列化和反序列化转化器 就要使用 @Autowried 注入 ObjectMapper 而不是自己 new 一个
  • 为什么要配置

    • 因为就拿 LocalDateTime 来说,在redis反序列化的时候LocalDateTime没有无参构造函数 所以就没法反序列化
    • 同时也为了前后端传参时方便,不然就要传递一个对象
  • 如何实现其他类型转化(比如BigInteger等)

    • 如何实现@RequestParam 注解处的转化
     @Bean
     public Converter<String, BigInteger> bigIntegerConverter() { 
    	return new Converter<String, BigInteger>(){  };
    }
    
    • 如何实现Json的序列化和反序列化
    SimpleModule simpleModule = new SimpleModule();
    
    //序列化(如果是数组类型也可以 比如 BigInteger[].class)
    simpleModule.addSerializer(BigInteger.class, ,new JsonSerializer<BigInteger>(){
    	
    });
    
    //反序列化
    simpleModule.addDeserializer(BigInteger.class, ,new JsonDeserializer<BigInteger>(){
    	
    });
    
    //注册该module
    mapper.registerModule(simpleModule)
    
发布了109 篇原创文章 · 获赞 47 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/weixin_43934607/article/details/103154703
今日推荐