问题分析
在处理 HTTP GET 请求时,如果尝试接收一个 LocalDateTime 类型的参数,可能会遇到序列化或反序列化的问题。这是因为 URL 参数通常是字符串形式,而 LocalDateTime 是 Java 中的一个日期时间对象,需要适当的格式化才能正确解析。不然可以会出现如下错误:
Failed to convert value of type 'java.lang.String' to required type 'java.time.LocalDateTime'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [java.time.LocalDateTime] for value '2024-08-08 22:22:22'; nested exception is java.lang.IllegalArgumentException: Parse attempt failed for value [2024-08-08 22:22:22]
解决方案
一、LocalDateTime 转换器(全局)
get请求的话, 不走反序列化,而是直接将String的值塞给对应的类型,默认是没有转换器,会抛出异常。
配置了转换器后,当用LocalDateTime接收get请求参数的时候,就会进入这个转换器中。
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@Component
public class StringToLocalDateTimeConverter implements Converter<String, LocalDateTime> {
private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
@Override
public LocalDateTime convert(String source) {
return LocalDateTime.parse(source, formatter);
}
}
二、显示参数处理
如果不想使用自定义转换器,可以在控制器方法中显式地处理字符串参数,并手动转换为 LocalDateTime:
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@RestController
public class MyController {
@GetMapping("/test1")
public void resolveRequestParamDateTime(@RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime localDateTime) {
log.info("localDateTime:{}", localDateTime);
}
private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
@GetMapping("/test2")
public String getDateTime(@RequestParam("date") String dateString) {
LocalDateTime date = LocalDateTime.parse(dateString, formatter);
// 处理逻辑
return "Received date: " + date;
}
}
三、application.yml配置
application.yml配置 SpringBoot2.3.x以及更高的版本,springmvc增加了日期时间格式配置,既可以解决LocalDateTime类型参数解析,也可以解决Date类型参数解析
spring:
mvc:
date: yyyy-MM-dd
time: HH:mm:ss
date-time: yyyy-MM-dd HH:mm:ss
四、LocalDateTimeConfig
在Spring IOC容器中注入Converter,SpringBoot会自动将IOC容器中的Converter放到GenericConversionService中
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
@Configuration
public class LocalDateTimeConfig {
@Bean
public Converter<String, LocalDateTime> stringToLocalDateTimeConverter() {
return new Converter<String, LocalDateTime>() {
@Override
public LocalDateTime convert(String source) {
return LocalDateTime.parse(source, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
}
};
}
@Bean
public Converter<String, LocalDate> stringToLocalDateConverter() {
return new Converter<String, LocalDate>() {
@Override
public LocalDate convert(String source) {
return LocalDate.parse(source, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
}
};
}
@Bean
public Converter<String, LocalTime> stringToLocalTimeConverter() {
return new Converter<String, LocalTime>() {
@Override
public LocalTime convert(String source) {
return LocalTime.parse(source, DateTimeFormatter.ofPattern("HH:mm:ss"));
}
};
}
}