【spring boot】Controller @RequestMapping 数据绑定:接收 Date 类型参数时遇错,将 String 类型的参数转换成 Date 类型
前言
- spring boot 2.1.1.RELEASE
遇錯
Failed to convert value of type ‘java.lang.String’ to required type ‘java.util.Date’
Controller 中的接收 Date 類型參數(shù)時,會遇到這個錯誤。
@RequestMapping(path="/list", produces="text/plain;charset=UTF-8") public @ResponseBody String list(@RequestParam(name = "beginTime", required = false)Date beginTime,@RequestParam(name = "endTime", required = false)Date endTime) {... }遇錯時,請求是這樣的:
http://xxx/xxx/list?begingTime=2020-10-01 00:00:00&endTime=2020-11-01 00:00:00解決辦法
告知 spring boot 如何將 String 類型的參數(shù)轉(zhuǎn)換成 Date 類型。
@RequestMapping(path="/list", produces="text/plain;charset=UTF-8") public @ResponseBody String list(@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")@RequestParam(name = "beginTime", required = false)Date beginTime,@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")@RequestParam(name = "endTime", required = false)Date endTime) {... }擴大一下影響面的解決辦法
上面的方法是一個點一個點的將 String 類型的參數(shù)轉(zhuǎn)換成 Date 類型。這里來個一條線一條線的將 String 類型的參數(shù)轉(zhuǎn)換成 Date 類型。
在 list 方法所在的 Controller 中, 添加下面的方法:
@InitBinder public void initBinder(WebDataBinder binder, WebRequest request) {//轉(zhuǎn)換日期 注意這里的轉(zhuǎn)化要和傳進來的字符串的格式一直 如2015-9-9 就應(yīng)該為yyyy-MM-ddSimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//是否嚴格解析時間 false則嚴格解析 true寬松解析dateFormat.setLenient(false);// CustomDateEditor為自定義日期編輯器binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true)); }對同一 Controller 下的所有 Request 都會起作用, 有一個 initBinder 就夠了。
改進一下解決辦法
如果你想讓下面的請求都不報錯,就必須改進一下:
http://xxx/xxx/list?begingTime=2020-10-01 00:00:00&endTime=2020-11-01 00:00:00 http://xxx/xxx/list?begingTime=2020-10-01&endTime=2020-11-01 http://xxx/xxx/list?begingTime=2020-10-01 00&endTime=2020-11-01 00 http://xxx/xxx/list?begingTime=2020-10-01 00:00&endTime=2020-11-01 00:00此種情況下,必須自己寫一個 String 類型的參數(shù)轉(zhuǎn)換成 Date 類型的實現(xiàn)類,如下:
import java.beans.PropertyEditorSupport; import java.text.ParseException; import java.util.Date; import org.apache.commons.lang3.time.DateFormatUtils; import org.apache.commons.lang3.time.DateUtils; import org.springframework.lang.Nullable; import org.springframework.util.StringUtils;public class MultiformatDateEditor extends PropertyEditorSupport {private final String[] dateFormatPatterns;public MultiformatDateEditor(String... patterns) {this.dateFormatPatterns = patterns;}@Overridepublic void setAsText(@Nullable String text) throws IllegalArgumentException {if (!StringUtils.hasText(text)) {// Treat empty String as null value.setValue(null);}else {try {setValue(DateUtils.parseDate(text, this.dateFormatPatterns));}catch (ParseException ex) {throw new IllegalArgumentException("Could not parse date: " + ex.getMessage(), ex);}}}@Overridepublic String getAsText() {Date value = (Date) getValue();return (value != null ? DateFormatUtils.format(value, this.dateFormatPatterns[0]) : "");} }然后改造一下 initBinder 方法:
@InitBinder public void initBinder(WebDataBinder binder, WebRequest request) {String[] dateFormatPatterns = {"yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM-dd HH", "yyyy-MM-dd"};binder.registerCustomEditor(Date.class, new MultiformatDateEditor(dateFormatPatterns)); }作用到整個項目
盡管改造過一次了,還得每個需要的地方都要加一次,還是有點兒麻煩。本方法能夠作用到整個項目,將 String 類型的參數(shù)轉(zhuǎn)換成 Date 類型。
改用 ControllerAdvice 給每個 Controller 都加上 initBinder 。
import java.util.Date;import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.InitBinder; import org.springframework.web.context.request.WebRequest;@ControllerAdvice public class GobalWebDataBinder {@InitBinderpublic void initBinder(WebDataBinder binder, WebRequest request) {String[] dateFormatPatterns = {"yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM-dd HH", "yyyy-MM-dd"};binder.registerCustomEditor(Date.class, new MultiformatDateEditor(dateFormatPatterns));} }Spring Boot 專用的方式
Spring Boot 中 WebMvcAutoConfiguration 自動進行了一系列與 Web Mvc 相關(guān)的配置,里邊也包括添加 type Formatters。
WebMvcAutoConfiguration 下面的 WebMvcAutoConfigurationAdapter 下面的 addFormatters 做的就是這個事情:
@Override public void addFormatters(FormatterRegistry registry) {// 添加所有的 Converterfor (Converter<?, ?> converter : getBeansOfType(Converter.class)) {registry.addConverter(converter);}// 添加所有的 GenericConverterfor (GenericConverter converter : getBeansOfType(GenericConverter.class)) {registry.addConverter(converter);}// 添加所有的 Formatterfor (Formatter<?> formatter : getBeansOfType(Formatter.class)) {registry.addFormatter(formatter);} }利用這個特性,只添加一個 Converter<String, Date> (Formatter也可以),可以在整個項目范圍內(nèi)將 String 類型的參數(shù)轉(zhuǎn)換成 Date 類型。
比如,添加下面的配置。
import java.text.ParseException; import java.util.Date;import org.apache.commons.lang3.time.DateUtils; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.convert.converter.Converter;@Configuration public class MyWebMvcConfigurationSupportSpringBoot {@Beanpublic Converter<String, Date> createConverter() {return new Converter<String, Date>(){@Overridepublic Date convert(String source) {String[] dateFormatPatterns = {"yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM-dd HH", "yyyy-MM-dd"};try {return DateUtils.parseDate(source, dateFormatPatterns);} catch (ParseException ex) {throw new IllegalArgumentException("Could not parse date: " + ex.getMessage(), ex);}}};} }Spring MVC 專用的方式
與 Spring Boot 專用的方式 對等的也有 Spring MVC 專用的方式。
利用 WebMvcConfigurationSupport 特性添加一個 Converter<String, Date> (Formatter也可以),可實現(xiàn)在整個項目范圍內(nèi)將 String 類型的參數(shù)轉(zhuǎn)換成 Date 類型。
比如,添加下面的配置。
import java.text.ParseException; import java.util.Date;import org.apache.commons.lang3.time.DateUtils; import org.springframework.core.convert.converter.Converter; import org.springframework.format.FormatterRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;@Configuration public class MyWebMvcConfigurerSupportSpring extends WebMvcConfigurationSupport {@Overrideprotected void addFormatters(FormatterRegistry registry) {super.addFormatters(registry);registry.addConverter(new Converter<String, Date>(){@Overridepublic Date convert(String source) {String[] dateFormatPatterns = {"yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM-dd HH", "yyyy-MM-dd"};try {return DateUtils.parseDate(source, dateFormatPatterns);} catch (ParseException ex) {throw new IllegalArgumentException("Could not parse date: " + ex.getMessage(), ex);}}});} }參考
https://blog.csdn.net/weixin_38229356/article/details/81228923
https://www.cnblogs.com/yy3b2007com/p/11757900.html
http://www.javaadu.online/?p=652
https://blog.csdn.net/weixin_38229356/article/details/81228923
https://blog.csdn.net/andy_zhang2007/article/details/87432541
總結(jié)
以上是生活随笔為你收集整理的【spring boot】Controller @RequestMapping 数据绑定:接收 Date 类型参数时遇错,将 String 类型的参数转换成 Date 类型的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 大脚趾发麻警惕四种病是什么
- 下一篇: 百级分区背光:小米 86 寸 ES Pr