springboot 获取当前日期_Springboot 关于日期时间格式化处理方式总结

项目中使用LocalDateTime系列作为DTO中时间的数据类型,但是SpringMVC收到参数后总报错,为了配置全局时间类型转换,尝试了如下处理方式。

注:本文基于Springboot2.x测试,如果无法生效可能是spring版本较低导致的。PS:如果你的Controller中的LocalDate类型的参数啥注解(RequestParam、PathVariable等)都没加,也是会出错的,因为默认情况下,解析这种参数是使用ModelAttributeMethodProcessor进行处理,而这个处理器要通过反射实例化一个对象出来,然后再对对象中的各个参数进行convert,但是LocalDate类没有构造函数,无法反射实例化因此会报错!!!

完成目标

请求入参为 String(指定格式)转 Date,支持get、post(content-type=application/json)

返回数据为Date类型转为指定的日期时间格式字符创

支持Java8 日期 API,如:LocalTime、localDate 和 LocalDateTime

GET请求及POST表单日期时间字符串格式转换

这种情况要和时间作为Json字符串时区别对待,因为前端json转后端pojo底层使用的是Json序列化Jackson工具(HttpMessgeConverter);而时间字符串作为普通请求参数传入时,转换用的是Converter,两者在处理方式上是有区别。

使用自定义参数转换器(Converter)

实现 org.springframework.core.convert.converter.Converter,自定义参数转换器,如下:

@Configuration

public class DateConverterConfig {

@Bean

public Converter localDateConverter() {

return new Converter() {

@Override

public LocalDate convert(String source) {

return LocalDate.parse(source, DateTimeFormatter.ofPattern("yyyy-MM-dd"));

}

};

}

@Bean

public Converter localDateTimeConverter() {

return new Converter() {

@Override

public LocalDateTime convert(String source) {

return LocalDateTime.parse(source, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

}

};

}

}

点评:以上两个bean会注入到spring mvc的参数解析器(好像叫做ParameterConversionService),当传入的字符串要转为LocalDateTime类时,spring会调用该Converter对这个入参进行转换。

注意:关于自定义的参数转换器 Converter,这里我遇到了一个坑,我再这里详细记录下,本来我的想法是为了代码精简,将上面匿名内部类的写法精简成lambda表达式的方式:

@Bean

@ConditionalOnBean(name = "requestMappingHandlerAdapter")

public Converter localDateConverter() {

return source -> LocalDate.parse(source, DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT));

}

当我再次启动项目时却出现了异常:

Caused by: java.lang.IllegalArgumentException: Unable to determine source type and target type for your Converter [com.example.demo126.config.MappingConverterAdapter$$Lambda$522/817994751]; does the class parameterize those types?

ff68e642f295bdf3cbeabed797210555.png

百思不得其解,在查阅了资料才得知一二:

web项目启动注册requestMappingHandlerAdapter的时候会初始化WebBindingInitializer

adapter.setWebBindingInitializer(getConfigurableWebBindingInitializer());

而ConfigurableWebBindingInitializer需要FormattingConversionService, 而FormattingConversionService会将所有的Converter添加进来,添加的时候需要获取泛型信息:

@Override

public void addFormatters(FormatterRegistry registry) {

for (Converter, ?> converter : getBeansOfType(Converter.class)) {

registry.addConverter(converter);

}

for (GenericConverter converter : getBeansOfType(GenericConverter.class)) {

registry.addConverter(converter);

}

for (Formatter> formatter : getBeansOfType(Formatter.class)) {

registry.addFormatter(formatter);

}

}

添加Converter.class 一般是通过接口获取两个泛型的具体类型

public ResolvableType as(Class> type) {

if (this == NONE) {

return NONE;

}

Class> resolved = resolve();

if (resolved == null || resolved == type) {

return this;

}

for (ResolvableType interfaceType : getInterfaces()) {

ResolvableType interfaceAsType = interfaceType.as(type);

if (interfaceAsType != NONE) {

return interfaceAsType;

}

}

return getSuperType().as(type);

}

Lambda表达式的接口是Converter,并不能得到具体的类型,在窥探了SpringMVC源码后才得知原来如此,既然指导了原因,那解决办法:

最简单的方法就是不适用Lambda表达式,还是老老实实的使用匿名内部类,这样就不会存在上述问题

或者就是等requestMappingHandlerAdapterbean注册完成之后再添加自己的converter就不会注册到FormattingConversionService中

@Bean

@ConditionalOnBean(name = "requestMappingHandlerAdapter")

public Converter localDateTimeConverter() {

return source -> LocalDateTime.parse(source, DateTimeUtils.DEFAULT_FORMATTER);

}

还可以对前端传递的string进行正则匹配,如yyyy-MM-dd HH:mm:ss、yyyy-MM-dd、 HH:mm:ss等,进行匹配。以适应多种场景。

@Component

public class DateConverter implements Converter {

@Override

public Date convert(String value) {

/**

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值