spring mvc绑定到2个具有相同字段的对象

mko*_*yak 4 data-binding spring-mvc

我提交一份表格,让我们说这个表格包含

<input name="address" ..>
Run Code Online (Sandbox Code Playgroud)

<input name="billingAddress" ..>
Run Code Online (Sandbox Code Playgroud)

我有2个对象需要绑定到:

class Address {
   String address;
   ..
}

class BillingAddress {
   String address;
   ..
}
Run Code Online (Sandbox Code Playgroud)

没有一些魔法,显然billingAddress不会绑定到地址BillingAddress.

假设我在两者中都有多个相同的字段Address,BillingAddress但在表单上我将计费输入前缀为billing,即billingFirstName,billingLastName等.

是否有一些优雅的方式,我可以绑定BillingAddress,我可以重用类似的问题?
(还是有更好的方法可以解决这个问题,然后我想出了什么?)

Flo*_*ser 7

如果您想要使用多个ModelAttribute,则必须创建一个包装器对象,该对象包含每个ModelAttribute的实例.在你的情况下,我将创建一个名为"FormModel"的包装器对象,它包含一个Address实例和一个BillingAddress实例.

class FormModel {
  private Address address;
  private BillingAddress billingAddress;

  // Getters and Setters
}
Run Code Online (Sandbox Code Playgroud)

现在使用FormModel作为ModelAttribute.在您的表单中,您可以定义输入元素,如:

<input name="address.address" ..>
<input name="billingAddress.address" ..>
Run Code Online (Sandbox Code Playgroud)

控制器:

@RequestMapping(value = "/save", method = RequestMethod.POST)
public String save(Model model, @ModelAttribute() FormModel formModel) {
   // process formModel.getAddress()
   // process formModel.getBillingAddress()

   return "redirect:home";
}
Run Code Online (Sandbox Code Playgroud)

如果对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();
        }
    }

}
Run Code Online (Sandbox Code Playgroud)