DateTimeFormatterBuilder 的妙用:让springboot项目适配前端传入不同的数时间格式 实践
  • 创建时间:2025-04-01 / 最新修改时间:2025-04-01 10:14:59
  • 51
  • 0
转载请注明本文出处:http://limpire.cn/artifact/programming/practiceLog/243.html


DateTimeFormatterBuilder 的妙用:让springboot项目适配前端传入不同的时间格式

在项目实践中,经常遇到后端的bean字段类型是LocalDateTime,前端传入的格式可能是 2025-01-01 ,2025-01-01T10:10:00或者是2025-01-01 10:10:00.

那么我们怎么让后端在接受json反序列化时自动识别以上的格式,让它成功变为 LocalDateTime.

这时候就用到 DateTimeFormatterBuilder

DateTimeFormatter defaultFormatter = new DateTimeFormatterBuilder()
                .append(DateTimeFormatter.ISO_LOCAL_DATE) // 日期部分
                .optionalStart() // 可选部分开始
                .appendLiteral('T') // 时间部分前的'T'
                .append(DateTimeFormatter.ISO_LOCAL_TIME) // 时间部分
                .optionalEnd() // 可选部分结束
                .optionalStart() // 可选部分开始
                .appendLiteral(' ') // 时间部分前的' '
                .append(DateTimeFormatter.ISO_LOCAL_TIME) // 时间部分
                .optionalEnd() // 可选部分结束
                .parseDefaulting(ChronoField.HOUR_OF_DAY, 0) // 默认小时为0
                .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0) // 默认分钟为0
                .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0) // 默认秒为0
                .toFormatter();
  • 实例一个DateTimeFormatterBuilder
  • optionalStart()optionalEnd() 为一个区间,在区间里面调用appendLiteral('T') 即可代表已T作为分割符号,把后部分视为时间,再经过append(DateTimeFormatter.ISO_LOCAL_TIME)对时间格式进行解析.
  • parseDefaulting 用到默认时间,这样就可以匹配缺时间的字符串.

把他注册到springboot项目中

以下是完整代码


@Configuration
public class DateTimeFormatConfig implements WebMvcConfigurer {


    private static final String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
    private static final String DATE_PATTERN = "yyyy-MM-dd";

    /**
     * 使用此方法, 以下 spring-boot: jackson时间格式化 配置 将会失效
     * spring.jackson.time-zone=GMT+8
     * spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
     * 原因: 会覆盖 @EnableAutoConfiguration 关于 WebMvcAutoConfiguration 的配置
     */
    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        ObjectMapper objectMapper = converter.getObjectMapper();
        // 生成JSON时,将所有Long转换成String
        SimpleModule simpleModule = new SimpleModule();
        simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
        simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
        //序列化LocalDateTime
        JsonSerializer<? super LocalDateTime> localDateTimeSerializer = new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DATE_TIME_PATTERN));
        simpleModule.addSerializer(LocalDateTime.class, localDateTimeSerializer);

        //反序列化时,自动把确实的时间部分添加默认值
        // 定义日期时间格式,支持"yyyy-MM-dd"和"yyyy-MM-ddTHH:mm:ss"
        DateTimeFormatter defaultFormatter = new DateTimeFormatterBuilder()
                .append(DateTimeFormatter.ISO_LOCAL_DATE) // 日期部分
                .optionalStart() // 可选部分开始
                .appendLiteral('T') // 时间部分前的'T'
                .append(DateTimeFormatter.ISO_LOCAL_TIME) // 时间部分
                .optionalEnd() // 可选部分结束
                .optionalStart() // 可选部分开始
                .appendLiteral(' ') // 时间部分前的' '
                .append(DateTimeFormatter.ISO_LOCAL_TIME) // 时间部分
                .optionalEnd() // 可选部分结束
                .parseDefaulting(ChronoField.HOUR_OF_DAY, 0) // 默认小时为0
                .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0) // 默认分钟为0
                .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0) // 默认秒为0
                .toFormatter();

        //反序列化LocalDateTime
       //JsonDeserializer<LocalDateTime> localDateTimeDeserializer=new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DATE_TIME_PATTERN));
        JsonDeserializer<LocalDateTime> localDateTimeDeserializer=new LocalDateTimeDeserializer(defaultFormatter);
        simpleModule.addDeserializer(LocalDateTime.class,localDateTimeDeserializer);

        objectMapper.registerModule(simpleModule);
        // 时间格式化
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        objectMapper.setDateFormat(new SimpleDateFormat(DATE_TIME_PATTERN));
        // 设置格式化内容
        converter.setObjectMapper(objectMapper);
        converters.add(0, converter);
    }

请说:

昵称 Email

评论:

吃不起海鲜就买海鲜味的酱油

回车换行很爽,代表着一个段落或者一个小结的完成,打印出来之后就是一个可触摸的成品.围着这种意境,一起来技术性打酱油.

文章列表
分类目录
友情链接