我正在尝试在我的百里香叶模板中使用一个实体,一个Order
的实例。Order
有几个可为空的字段,即CustomerOrderReference
。为了显式处理可空性,字段的 getter 返回Optional<CustomerOrderReference>
(正在使用值对象(,但是,setter 采用可为空的CustomerOrderReference
:
public class Order {
[...]
private CustomerOrderReference customerOrderReference;
[...]
public Optional<CustomerOrderReference> getCustomerOrderReference() {
return Optional.ofNullable(customerOrderReference);
}
public void setCustomerOrderReference(CustomerOrderReference customerOrderReference) {
this.customerOrderReference = customerOrderReference;
}
我正在百里香叶模板中绑定Order
:
<div class="form-group" >
<label th:text="#{order-creation.customer-order-reference}"
class="col-xs-12 col-sm-4 control-label"></label>
<div class="col-xs-12 col-sm-8">
<input th:field="*{customerOrderReference}" th:value="*{customerOrderReference}" class="form-control"
data-test-id="customer-order-reference" id="customer-order-reference"/>
</div>
</div>
我正在使用自定义解析器/打印机来处理来回发送的值:
public class CustomerOrderReferenceFormatter implements Parser<CustomerOrderReference>,
Printer<Optional<CustomerOrderReference>> {
@Override
public CustomerOrderReference parse(String text, Locale locale) {
return CustomerOrderReference.from(text).orElse(null);
}
@Override
public String print(Optional<CustomerOrderReference> object, Locale locale) {
if (object.isPresent()) {
return object.get().getValue();
}
return "";
}
}
这样做会导致模板解析错误:
java.lang.IllegalArgumentException: Source to convert from must be an instance of [net.xxx.order.model.order.CustomerOrderReference]; instead it was a [java.util.Optional]
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:187) ~[spring-core-5.2.1.RELEASE.jar:5.2.1.RELEASE]
at org.springframework.validation.AbstractPropertyBindingResult.formatFieldValue(AbstractPropertyBindingResult.java:130) ~[spring-context-5.2.1.RELEASE.jar:5.2.1.RELEASE]
at org.springframework.validation.AbstractBindingResult.getFieldValue(AbstractBindingResult.java:229) ~[spring-context-5.2.1.RELEASE.jar:5.2.1.RELEASE]
at org.springframework.web.servlet.support.BindStatus.<init>(BindStatus.java:129) ~[spring-webmvc-5.2.1.RELEASE.jar:5.2.1.RELEASE]
at org.springframework.web.servlet.support.RequestContext.getBindStatus(RequestContext.java:904) ~[spring-webmvc-5.2.1.RELEASE.jar:5.2.1.RELEASE]
at org.thymeleaf.spring5.context.webmvc.SpringWebMvcThymeleafRequestContext.getBindStatus(SpringWebMvcThymeleafRequestContext.java:227) ~[thymeleaf-spring5-3.0.11.RELEASE.jar:3.0.11.RELEASE]
at org.thymeleaf.spring5.util.FieldUtils.getBindStatusFromParsedExpression(FieldUtils.java:306) ~[thymeleaf-spring5-3.0.11.RELEASE.jar:3.0.11.RELEASE]
at org.thymeleaf.spring5.util.FieldUtils.getBindStatus(FieldUtils.java:253) ~[thymeleaf-spring5-3.0.11.RELEASE.jar:3.0.11.RELEASE]
at org.thymeleaf.spring5.util.FieldUtils.getBindStatus(FieldUtils.java:227) ~[thymeleaf-spring5-3.0.11.RELEASE.jar:3.0.11.RELEASE]
at org.thymeleaf.spring5.processor.AbstractSpringFieldTagProcessor.doProcess(AbstractSpringFieldTagProcessor.java:174) ~[thymeleaf-spring5-3.0.11.RELEASE.jar:3.0.11.RELEASE]
[...]
我知道错误意味着什么 - 但我不确定错误是如何发生的: 据我所知,注册的自定义格式化程序将用于处理类型(如Optional<CustomerOrderReference>
.但事实并非如此。
Thymeleaf/Spring MVC是否查看字段类型(CustomerOrderReference
(,因此无法处理Optional<CustomerOrderReference>
返回类型?
如何更改此行为(对 getter 和 setter/field 使用不同的返回类型(?
数据位于Optional
容器中的问题。一个特殊的容器类来保存值,该值可能为空,并受到NullPointerException
的保护。
默认情况下,百里香叶无法处理此类值。我相信您根本不应该在 Thymeleaf 模板中使用的 DTO 对象的获取器中使用Optional
。
尝试在创建这些 DTO 对象之前或在模板中使用 elvise 运算符${somparent?.somechild}
处理null
值。