正确解析的LocalDate导致BindingResult错误.为什么?



我被难住了。我有一个域类Period,具有两个LocalDate属性startend,以及相应的控制器方法和创建新周期的模板。

问题:即使请求模型显然正确地反序列化为具有两个正确的LocalDate属性的Period实例,I仍然BindingResult中得到错误,其中属性显然没有转换为LocalDate,而是保留为Strings。验证失败:

end: Failed to convert property value of type 'java.lang.String' to required type 'java.time.LocalDate' for property 'end'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [java.time.LocalDate] for value '2022-06-02'; nested exception is java.lang.IllegalArgumentException: Parse attempt failed for value [2022-06-02]
start: Failed to convert property value of type 'java.lang.String' to required type 'java.time.LocalDate' for property 'start'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [java.time.LocalDate] for value '2022-06-01'; nested exception is java.lang.IllegalArgumentException: Parse attempt failed for value [2022-06-01]

这是域类:

@Entity
@Table(name = "period")
class Period(

@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
val id: Long = 0,

@DateTimeFormat(pattern = "yyyy-MM-dd")
var start: LocalDate?,

@DateTimeFormat(pattern = "yyyy-MM-dd")
var end: LocalDate?,
)

这是用于创建新Period的控制器方法:

@PostMapping("/period/add")
fun updatePeriod(@ModelAttribute("period") @Validated period: Period, result: BindingResult, model: Model) : String {
if(result.hasErrors()){
result
.getFieldErrors()
.stream()
.forEach{f -> println(f.getField() + ": " + f.getDefaultMessage())};
return "add-period"
}
else {
periodRepository.save(period)
return "redirect:/period"
}

}

这是thyymleaf模板:

<!DOCTYPE html>
<html>
<head lang="en">
<title th:text="${title}"></title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
</head>
<body>
<h1 th:text="'New Period'"></h1>
<form action="#" th:action="@{/period/add}" th:object="${period}" method="post">
<table>
<tr>
<td>Start Date</td>
<td><input id="start" type="date"  name="start"
min="2000-01-01" max="2023-12-31"
th:value="*{start}"
th:field="*{start}"/></td>
</tr>
<tr>
<td>End Date</td>
<td><input id="end" type="date"  name="end"
min="2000-01-01" max="2023-12-31"
th:value="*{end}"
th:field="*{end}"/></td>
</tr>
</table>
<input type="submit" value="Submit" />
</form>

这是调试器在控制器中设置if(result.hasErrors()){断点时告诉我的内容。显然,period是具有两个LocalDate属性的Period实例,每个属性都有年、月和日(由-->表示)。在BindingResult内部也是如此。一切都很好!

然而,有两个错误拒绝用于创建日期的字符串值(由==>指示)。

this = {WebController@13784} nl.tracking.core.web.WebController@a4388f1
period = {Period@13787} nl.tracking.core.domain.Period@111cd8c3
id = 0
-->  start = {LocalDate@17522} "2022-06-01"
-->   year = 2022
-->   month = 6
-->   day = 1
end = {LocalDate@17523} "2022-06-02"
result = {BeanPropertyBindingResult@13788} "org.springframework.validation.BeanPropertyBindingResult: 2 errorsnField error in object 'period' on field 'end': rejected value [2022-06-02]; codes [typeMismatch.period.end,typeMismatch.end,typeMismatch.java.time.LocalDate,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [period.end,end]; arguments []; default message [end]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.time.LocalDate' for property 'end'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [java.time.LocalDate] for value '2022-06-02'; nested exception is java.lang.IllegalArgumentException: Parse attempt failed for value [2022-06-02]]nField error in object 'period' on field 'start': rejected value [2022-06-01]; codes [typeMismatch.period.start,typeMismatch.start,typeMismatch.java.time.LocalDate,typeMismatch]; arguments [org.springfra"
-->  target = {Period@13787} nl.tracking.core.domain.Period@111cd8c3
autoGrowNestedPaths = true
autoGrowCollectionLimit = 256
beanWrapper = {BeanWrapperImpl@17526} "org.springframework.beans.BeanWrapperImpl: wrapping object [nl.tracking.core.domain.Period@111cd8c3]"
conversionService = {WebConversionService@17527} "ConversionService converters =nt@org.springframework.format.annotation.DateTimeFormat java.lang.Long -> java.lang.String: org.springframework.format.datetime.DateTimeFormatAnnotationFormatterFactory@4a422ef1,@org.springframework.format.annotation.NumberFormat java.lang.Long -> java.lang.String: org.springframework.format.number.NumberFormatAnnotationFormatterFactory@35e37f8fnt@org.springframework.format.annotation.DateTimeFormat java.time.LocalDate -> java.lang.String: org.springframework.format.datetime.standard.Jsr310DateTimeFormatAnnotationFormatterFactory@1f4c8763,java.time.LocalDate -> java.lang.String : org.springframework.format.datetime.standard.TemporalAccessorPrinter@61841139nt@org.springframework.format.annotation.DateTimeFormat java.time.LocalDateTime -> java.lang.String: org.springframework.format.datetime.standard.Jsr310DateTimeFormatAnnotationFormatterFactory@1f4c8763,java.time.LocalDateTime -> java.lang.String : org.springframework.format.datetime.standard.TemporalAcces"
objectName = "period"
messageCodesResolver = {DefaultMessageCodesResolver@17529} 
errors = {ArrayList@17530}  size = 2
0 = {FieldError@17550} "Field error in object 'period' on field 'end': rejected value [2022-06-02]; codes [typeMismatch.period.end,typeMismatch.end,typeMismatch.java.time.LocalDate,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [period.end,end]; arguments []; default message [end]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.time.LocalDate' for property 'end'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [java.time.LocalDate] for value '2022-06-02'; nested exception is java.lang.IllegalArgumentException: Parse attempt failed for value [2022-06-02]]"
field = "end"
==>    rejectedValue = "2022-06-02"
bindingFailure = true
objectName = "period"
==>    source = {TypeMismatchException@17556} "org.springframework.beans.TypeMismatchException: Failed to convert property value of type 'java.lang.String' to required type 'java.time.LocalDate' for property 'end'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [java.time.LocalDate] for value '2022-06-02'; nested exception is java.lang.IllegalArgumentException: Parse attempt failed for value [2022-06-02]"
codes = {String[4]@17557} ["typeMismatch.pe...", "typeMismatch.en...", "typeMismatch.ja...", "typeMismatch"]
arguments = {Object[1]@17558} 
==>    defaultMessage = "Failed to convert property value of type 'java.lang.String' to required type 'java.time.LocalDate' for property 'end'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [java.time.LocalDate] for value '2022-06-02'; nested exception is java.lang.IllegalArgumentException: Parse attempt failed for value [2022-06-02]"
1 = {FieldError@17551} "Field error in object 'period' on field 'start': rejected value [2022-06-01]; codes [typeMismatch.period.start,typeMismatch.start,typeMismatch.java.time.LocalDate,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [period.start,start]; arguments []; default message [start]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.time.LocalDate' for property 'start'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [java.time.LocalDate] for value '2022-06-01'; nested exception is java.lang.IllegalArgumentException: Parse attempt failed for value [2022-06-01]]"
fieldTypes = {HashMap@17531}  size = 0
fieldValues = {HashMap@17532}  size = 0
suppressedFields = {HashSet@17533}  size = 0
nestedPath = ""
nestedPathStack = {ArrayDeque@17535}  size = 0
--> model = {BindingAwareModelMap@13789}  size = 2
"period" -> {Period@13787} nl.tracking.core.domain.Period@111cd8c3
key = "period"
value = {Period@13787} nl.tracking.core.domain.Period@111cd8c3
id = 0
-->    start = {LocalDate@17522} "2022-06-01"
-->     year = 2022
-->     month = 6
-->     day = 1
end = {LocalDate@17523} "2022-06-02"
"org.springframework.validation.BindingResult.period" -> {BeanPropertyBindingResult@13788} "org.springframework.validation.BeanPropertyBindingResult: 2 errorsnField error in object 'period' on field 'end': rejected value [2022-06-02]; codes [typeMismatch.period.end,typeMismatch.end,typeMismatch.java.time.LocalDate,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [period.end,end]; arguments []; default message [end]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.time.LocalDate' for property 'end'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [java.time.LocalDate] for value '2022-06-02'; nested exception is java.lang.IllegalArgumentException: Parse attempt failed for value [2022-06-02]]nField error in object 'period' on field 'start': rejected value [2022-06-01]; codes [typeMismatch.period.start,typeMismatch.start,typeMismatch.java.time.LocalDate,typeMismatch]; arguments [org.springfra"

这对我来说没有意义…我到处搜索S/O,但找不到解决方案。大多数人要么使用不匹配的@DateTimeFormat模式,要么缺乏thymleaf -extras-java8time。

我使用spring-boot 2.6.7和thymeleaf 3.0.15。我已经在依赖项中添加了thymleaf -extras-java8time。

我唯一要做的就是使用:

@field:DateTimeFormat(pattern = "yyyy-MM-dd")

代替:

@DateTimeFormat(pattern = "yyyy-MM-dd")

在我的域类。

相关内容

  • 没有找到相关文章

最新更新