这是我参与11月更文挑战的第5天,活动详情查看:2021最后一次更文挑战
前言
在前后端交互过程中,日期类型的参数是绕不过的的一种类型,但是日期类型的数据有多种多样的格式,但是默认的情况下,日期类型的转换多数情况下就会出错.
Failed to convert value of type 'java.lang.String' to required type 'java.util.Date'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [java.util.Date] for value '2021-12-12'; nested exception is java.lang.IllegalArgumentException
日期参数处理的多种方式
日期参数的处理包含两个部分,一是@RequestBody
参数的解析方式
@PostMapping("/typeBody")
public ResultVo typeBody(@RequestBody StudentSimpleDto dto){
return R.success(dto);
}
StudentSimpleDto.java中有日期参数
@Data
public class StudentSimpleDto {
@JsonFormat(pattern = "yyyy-MM-dd hh:mm:ss", timezone = "GMT+8")
private LocalDateTime birthdate;
}
二是非@RequestBody
参数的解析方式
@PostMapping("/type")
public ResultVo token(Date date, LocalDate localDate ){
return R.success("Date",date,"LocalDate",localDate);
}
(一) 在对象的参数上使用@JsonFormat
public class Dto{
@JsonFormat(pattern = "yyyy-MM-dd hh:mm:ss", timezone = "GMT+8")
private Date createtime;
}
只适用于接收为对象类型,springboot的默认JSON解析器为Jackson,这个注解是Jackson的,非Jackson不管用,非RequestBody
接收的参数无效,适合个别日期参数有特殊的格式
该方案的进阶方案就是配置Jackson的
ObjectMapper
配置,不想写.
(二) 在@ControllerAdvice
的@InitBinder
中添加Converter
@ControllerAdvice
public class RequestHandler {
@InitBinder
public void initBinder(WebDataBinder binder) {
GenericConversionService genericConversionService = (GenericConversionService) binder.getConversionService();
if (genericConversionService != null) {
genericConversionService.addConverter(new Converter<String, Date>(){
@Override
public Date convert(String source) {
try {
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(source);
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
});
// //可以添加多个Converter
}
}
}
可以新增多个Converter,比如<String,LocalDate>
但是只是用于入参数据解析
(三) 实现WebMvcConfigurer
类,重写addFormatters
方法(个人认为最好)
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
//LocalDate 类型
registry.addFormatter(new LocalDateFormatter());
//LocalDateTime
registry.addFormatter(new LocalDateTimeFormatter());
//Date
registry.addFormatter(new DateFormatter());
}*/
}
该实现能支持非RequestBody
和RequestBody
的参数,且可以用于软件数据的解析,也能用户返回数据的格式化,我认为是最好的一种方式.
其中LocalDateFormatter
,LocalDateTimeFormatter
,DateFormatter
为自定义方法.
DateFormatter.java
public class DateFormatter implements Formatter<Date> {
//年月日
String pattern_date ="^[\\d]{4}-[\\d]{1,2}-[\\d]{1,2}$";
//年月日时分秒
String pattern_datetime ="^[\\d]{4}-[\\d]{1,2}-[\\d]{1,2}[ ][\\d]{1,2}:[\\d]{1,2}:[\\d]{1,2}$";
//秒
String pattern_second ="^[\\d]{10}$";
//毫秒
String pattern_millsecond ="^[\\d]{13}$";
SimpleDateFormat sdf_date =new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat sdf_datetime =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@Override
public Date parse(String s, Locale locale) throws ParseException {
if(StringUtils.isEmpty(s)){
return null;
}
if (Pattern.matches(pattern_date,s)) {
return sdf_date.parse(s);
}
if (Pattern.matches(pattern_datetime,s)) {
return sdf_datetime.parse(s);
}
if (Pattern.matches(pattern_second,s)) {
return new Date(Long.parseLong(s)*1000);
}
if (Pattern.matches(pattern_millsecond,s)) {
return new Date(Long.parseLong(s));
}
throw new CustomException("未能识别的日期格式");
}
@Override
public String print(Date date, Locale locale) {
return sdf_datetime.format(date);
}
}
LocalDateTimeFormatter.java
public class LocalDateTimeFormatter implements Formatter<LocalDateTime> {
@Override
public String print(LocalDateTime localDateTime, Locale locale) {
return localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
}
@Override
public LocalDateTime parse(String s, Locale locale) {
if(StringUtils.isEmpty(s)){
return null;
}
return LocalDateTime.parse(s, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
}
}
LocalDateFormatter.java
public class LocalDateFormatter implements Formatter<LocalDate> {
@Override
public String print(LocalDate localDate, Locale locale) {
return localDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
}
@Override
public LocalDate parse(String s, Locale locale) {
if(StringUtils.isEmpty(s)){
return null;
}
return LocalDate.parse(s, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
}
}
作者:ZOUZDC
链接:https://juejin.cn/post/7028963866063306760
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。