[转载]springboot自定义ObjectMapper序列化、配置序列化对LocalDateTime的支持

原文地址
背景
问题1:项目中使用默认自带的jackson进行前后端交互,实现数据对象的序列化和反序列化,默认的ObjectMapper采用小驼峰的格式,但是调用其他业务的http接口时,ObjectMapper需要使用蛇形的格式,因此就需要自定义ObjectMapper,然后封装RestTemplate。
问题2:前后端交互时,JSR310日期序列化时,格式错误;
注意点
自定义的ObjectMapper不能被IOC管理,因为Springboot默认的ObjectMapper生成条件是:只有当该实例不存在的时候才会创建!
自定义时,需要支持JSR310的日期,否则序列化LocalDateTime、LocalDate、LocalTime时,就会返回错误的格式。
使用springboot自带的jackson,是不支持JSR310的日期,可以通过下面方式解决

在实体类上增加 @JsonFormat(pattern = “yyyy-MM-dd”)

在controller方法参数中增加 @DateTimeFormat(pattern = “yyyy-MM-dd”)

自定义ObjectMapper

@Slf4j
public class JsonFormatUtils {
    private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm:ss");
    public static final ObjectMapper objectMapper = new ObjectMapper();

    static {
        //取消时间的转化格式,默认是时间戳,同时需要设置要表现的时间格式
        objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        objectMapper.configure(SerializationFeature.WRITE_DURATIONS_AS_TIMESTAMPS, false);
        objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
        JavaTimeModule javaTimeModule = new JavaTimeModule();   // 默认序列化没有实现,反序列化有实现
        javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DATE_TIME_FORMATTER));
        javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DATE_FORMATTER));
        javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(TIME_FORMATTER));
        objectMapper.registerModule(javaTimeModule);
        // 设置时区
        objectMapper.setTimeZone(TimeZone.getDefault());
        // 设置格式化输出
//        objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
        // 设置蛇形格式
        objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
    }

    public static String writeValueAsString(Object obj) {
        String result = null;
        try {
            result = objectMapper.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            log.error("objectMapper writeValueAsString exception, e:", e);
        }
        return result;
    }

    public static <T> T readValue(String str, Class<T> tClass) {
        T t = null;
        try {
            t = objectMapper.readValue(str, tClass);
        } catch (JsonProcessingException e) {
            log.error("objectMapper readValue exception, e:", e);
        }
        return t;
    }
}

封装RestTemplate

@Configuration
public class RestTemplateConfig {
    @Bean("otherRestTemplate")
    public RestTemplate algoRestTemplate() {
        // 使用apache的httpComponents,封装restTemplate
        ClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient());
        RestTemplate restTemplate = new RestTemplate(factory);
        // 使用自定义的ObjectMapper
        ObjectMapper objectMapper = JsonFormatUtils.objectMapper;
        MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
        messageConverter.setPrettyPrint(false);
        messageConverter.setObjectMapper(objectMapper);

        List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters();
        messageConverters.removeIf(item -> item.getClass().getName().equals(MappingJackson2HttpMessageConverter.class.getName()));
        messageConverters.add(messageConverter);
        return restTemplate;
    }

    private HttpClient httpClient() {
        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
        connectionManager.setMaxTotal(50);
        connectionManager.setDefaultMaxPerRoute(10);
        connectionManager.setValidateAfterInactivity(2000);
        RequestConfig requestConfig = RequestConfig.custom()
                .setSocketTimeout(10000)
                .setConnectTimeout(5000)
                .setConnectionRequestTimeout(1000)
                .build();
        return HttpClientBuilder.create().setDefaultRequestConfig(requestConfig).setConnectionManager(connectionManager).build();
    }
}

全局配置

底层默认是通过Jackson2ObjectMapperBuilderCustomizer创建的ObjectMapper

@Configuration
public class LocalDateTimeSerializerConfig {

    private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm:ss");


    @Bean
    public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
        Map<Class<?>, JsonSerializer<?>> serializers = new HashMap<>();
        serializers.put(LocalDateTime.class, new LocalDateTimeSerializer(DATE_TIME_FORMATTER));
        serializers.put(LocalDate.class, new LocalDateSerializer(DATE_FORMATTER));
        serializers.put(LocalTime.class, new LocalTimeSerializer(TIME_FORMATTER));

        Map<Class<?>, JsonDeserializer<?>> deserializers = new HashMap<>();
        deserializers.put(LocalDateTime.class, new LocalDateTimeDeserializer(DATE_TIME_FORMATTER));
        deserializers.put(LocalDate.class, new LocalDateDeserializer(DATE_FORMATTER));
        deserializers.put(LocalTime.class, new LocalTimeDeserializer(TIME_FORMATTER));
        return builder -> builder.serializersByType(serializers).deserializersByType(deserializers);
    }
}
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值