我提交了一份表格,让我们说这个表格包含
<input name="address" ..>
和
<input name="billingAddress" ..>
我有两个需要绑定的对象:
class Address {
String address;
..
}
class BillingAddress {
String address;
..
}
显然billingAddress
不会在没有魔法的情况下绑定BillingAddress
中的地址。
假设我在Address
和BillingAddress
中都有多个相同的字段,但在表单上我使用结算为结算输入添加前缀,即billingFirstName,billingLastName等。
是否有一些优雅的方式我可以绑定到BillingAddress
,我可以重用于类似的问题?
(或者有更好的方法来解决这个问题,然后我想出了什么?)
答案 0 :(得分:7)
如果您要使用多个ModelAttribute,则必须创建一个包装器对象,该对象包含每个ModelAttribute的实例。在你的情况下,我将创建一个名为“FormModel”的包装器对象,它包含一个Address实例和一个BillingAddress实例。
class FormModel {
private Address address;
private BillingAddress billingAddress;
// Getters and Setters
}
现在使用FormModel作为ModelAttribute。 在表单中,您可以定义输入元素,如:
<input name="address.address" ..>
<input name="billingAddress.address" ..>
控制器:
@RequestMapping(value = "/save", method = RequestMethod.POST)
public String save(Model model, @ModelAttribute() FormModel formModel) {
// process formModel.getAddress()
// process formModel.getBillingAddress()
return "redirect:home";
}
如果对Address和BillingAddress使用自定义验证器,则还必须创建一个调用AddressValidator和BillingAddressValidator的FormModelValidator:
public class FormModelValidator implements Validator {
private final AddressValidator addressValidator;
private final BillingAddressValidator billingAddressValidator;
public FormModelValidator(AddressValidator addressValidator,
BillingAddressValidator billingAddressValidator) {
this.addressValidator = addressValidator;
this.billingAddressValidator = billingAddressValidator;
}
public boolean supports(Class<?> clazz) {
return FormModel.class.equals(clazz);
}
public void validate(Object target, Errors errors) {
FormModel formModel = (FormModel) target;
try {
errors.pushNestedPath("address");
ValidationUtils.invokeValidator(this.addressValidator,
formModel.getAddress(), errors);
} finally {
errors.popNestedPath();
}
try {
errors.pushNestedPath("billingAddress");
ValidationUtils.invokeValidator(this.billingAddressValidator,
formModel.getBillingAddress(), errors);
} finally {
errors.popNestedPath();
}
}
}