环境: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中写内部类否则不生效。当然也可以直接实现接口。
@SpringBootConfigurationpublic 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方法用实体对象接收没问题,有个弊端就是需要所有的参数都自己解析,只解析部分另一部分有默认解析器解析还未找到方法。
@SpringBootConfigurationpublic 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("不支持当前日期时间格式"); }