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);
}