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

时间:2011-01-12 05:19:59

标签: data-binding spring-mvc

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

<input name="address" ..>

<input name="billingAddress" ..>

我有两个需要绑定的对象:

class Address {
   String address;
   ..
}

class BillingAddress {
   String address;
   ..
}

显然billingAddress不会在没有魔法的情况下绑定BillingAddress中的地址。

假设我在AddressBillingAddress中都有多个相同的字段,但在表单上我使用结算为结算输入添加前缀,即billingFirstName,billingLastName等。

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

1 个答案:

答案 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();
        }
    }

}