LocalDateTime与前端字符串时间数据交互问题
在接收参数上加注解: @JsonFormat(timezone = “GMT+8”, pattern = “yyyy-MM-dd HH:mm:ss”)默认反序列化也就是处理接收的LocalDateTime时间格式为:yyyy-MM-dd’T’HH:mm:ss.SSSX。默认的序列化也就是后端返回前端LocalDateTime的时间格式为:yyyy-MM-dd’T’HH:mm:ss。在返回参数上加注
环境:JDK17 / SpringBoot 3.2.4
- 注解方式
在接收参数上加注解: @JsonFormat(timezone = “GMT+8”, pattern = “yyyy-MM-dd HH:mm:ss”)
在返回参数上加注解:@JsonFormat(pattern = “yyyy-MM-dd HH:mm:ss”)
- 全局配置方式
- GET请求,LocalDateTime接收前端字符串类型时间数据解析
自定义Converter
public class LocalDateTimeConverter implements Converter<String, LocalDateTime> {
private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSX");
@Override
public LocalDateTime convert(String source) {
return LocalDateTime.parse(source,formatter);
}
}
自定义Formatter
public class LocalDateTimeFormatter implements Formatter<LocalDateTime> {
private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSX");
@Override
public LocalDateTime parse(String text, Locale locale) throws ParseException {
return LocalDateTime.parse(text, formatter);
}
@Override
public String print(LocalDateTime object, Locale locale) {
return DateUtils.formatLocalDateTime(object,"yyyy-MM-dd'T'HH:mm:ss");
}
}
自定义Mvc配置,覆写addFormatters方法,注册Formatter或Converter
注:在自定义LocalDateTimeConverter 和LocalDateTimeFormatter时不要直接在MvcConfiguration中写内部类否则不生效。当然也可以直接实现接口。
@SpringBootConfiguration
public class MvcConfiguration implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
//方法1:
registry.addFormatter(new LocalDateTimeFormatter());
//方法2:
registry.addConverter(new LocalDateTimeConverter());
//方法3:
registry.addFormatter(new Formatter<LocalDateTime>() {
@Override
public String print(LocalDateTime object, Locale locale) {
return //LocalDateTime转String ;
}
@Override
public LocalDateTime parse(String text, Locale locale) {
return //String转LocalDateTime;
}
});
}
}
controller接收参数
@GetMapping(value="/")
public Response<?> acceptTime(TimeDTO params){
//用对象接收,对象中的部分属性类型为LocalDateTime
}
@GetMapping(value="/")
public Response<?> acceptTime(@RequestParam LocalDateTime time){
}
其它方法:在Mvc配置中注册自定义的参数解析器
目前测试Get方法用实体对象接收没问题,有个弊端就是需要所有的参数都自己解析,只解析部分另一部分有默认解析器解析还未找到方法。
@SpringBootConfiguration
public class MvcConfiguration implements WebMvcConfigurer {
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(new HandlerMethodArgumentResolver() {
@Override
public boolean supportsParameter(MethodParameter parameter) {
//这里定义需要解析的类型,注:parameter.getParameterType()获取到的是controller中方法上参数的类型,
//如果是用@RequestParam或@ModelAttribute注解的则会用mvc默认的解析器
return true;
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
Object object = parameter.getParameterType().getDeclaredConstructor().newInstance();
Map<String, String[]> params = webRequest.getParameterMap();
for (Field field : parameter.getParameterType().getDeclaredFields()) {
String fieldName = field.getName();
if (!params.containsKey(fieldName)) {
//只对有值的参数做解析
continue;
}
field.setAccessible(true);
//解析LocalDateTime字段
if (LocalDateTime.class.isAssignableFrom(field.getType())) {
String fieldValue = params.get(fieldName)[0];
LocalDateTime dateTime = LocalDateTime.parse(fieldValue);
field.set(object, dateTime);
}
//解析其它类型的参数...
}
return object;
}
});
}
}
- POST请求,时间参数为Body中的Json数据,LocalDateTime接收并解析以及反回LocalDateTime数据问题
自定义Bean jsonObjectMapper 对LocalDateTime做序列化和返序列化
默认反序列化也就是处理接收的LocalDateTime时间格式为:yyyy-MM-dd’T’HH:mm:ss.SSSX
默认的序列化也就是后端返回前端LocalDateTime的时间格式为:yyyy-MM-dd’T’HH:mm:ss
JavaTimeModule继承SimpleModule,注册多个SimpleModule会被最后一个覆盖。
@Bean
public ObjectMapper jsonObjectMapper() {
ObjectMapper mapper = new ObjectMapper();
//设置时间类型的不以时间戳序列化
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
//忽略前端多传的参数
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
JavaTimeModule timeModule = new JavaTimeModule();
//LocalDateTime序列化,并默认返回前端的字符串格式
timeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
//LocalDateTime反序列化
timeModule.addDeserializer(LocalDateTime.class, new StdDeserializer<>(LocalDateTime.class) {
@Override
public LocalDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
String text = jsonParser.getText();
//这里提供一个方法用于适配几种格式的字符串转LocalDateTime
return DateUtils.formatStringToLocalDate(text);
}
});
mapper.registerModule(timeModule);
return mapper;
}
formatStringToLocalDate(String text)
public static LocalDateTime formatStringToLocalDate(String time) {
//0[1-9]表示01到09,1[0-2]表示10到12,中间的|表示或,[12][0-9]表示10到29,3[01]表示30和31
String regexToDay = "^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$";
if (time.matches(regexToDay)) {
return formatStringToLocalDate(time, "yyyy-MM-dd");
}
//s+:匹配一个或多个空白字符(空格、制表符等)
String regexToSecond = "^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])\s+(0[0-9]|1[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$";
if (time.matches(regexToSecond)) {
return formatStringToLocalDate(time, "yyyy-MM-dd HH:mm:ss");
}
String regexStandard = "^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])T(0[0-9]|1[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])\.\d{3}(Z)$";
if (time.matches(regexStandard)) {
return formatStringToLocalDate(time, "yyyy-MM-dd HH:mm:ss.SSSX");
}
throw new BusinessException("不支持当前日期时间格式");
}
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)