2011-01-12 15 views
4

ich ein Formular abgesendet haben, können Sie dieses Formular sagen enthältFeder mvc binden in zwei Objekte, die identische Felder haben

<input name="address" ..> 

und

<input name="billingAddress" ..> 

ich habe 2 Objekte, denen ich binden müssen:

class Address { 
    String address; 
    .. 
} 

class BillingAddress { 
    String address; 
    .. 
} 

offensichtlich billingAddress gewohnt binden Adresse ohne irgendeine Magie in BillingAddress.

können sagen, dass ich mehrere identische Felder in beiden Address und BillingAddress aber auf dem Formular haben Präfix i die Abrechnungseingänge mit Abrechnung, dh billingFirstName, billingLastName usw.

gibt es eine elegante Weise, die ich zu BillingAddress binden kann dass ich für ähnliche Probleme wiederverwenden kann?
(oder gibt es einen besseren Weg, dies dann zu lösen, was ich mit einfallen lassen?)

Antwort

6

Wenn Sie mehr als ein ModelAttribute verwenden Stab, müssen Sie ein Wrapper-Objekt erstellen, die von einer Instanz hält jedes ModelAttribute. In Ihrem Fall würde ich ein Wrapper-Objekt namens "FormModel" erstellen, das eine Instanz von Address und eine Instanz einer BillingAddress enthält.

class FormModel { 
    private Address address; 
    private BillingAddress billingAddress; 

    // Getters and Setters 
} 

Verwenden Sie jetzt FormModel als Ihr ModelAttribute. in Ihrem Formular können Sie Ihre Eingabe-Elemente wie definieren:

<input name="address.address" ..> 
<input name="billingAddress.address" ..> 

Controller:

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

    return "redirect:home"; 
} 

Wenn Sie benutzerdefinierte Validatoren für Adresse und Rechnungsanschrift zu verwenden, müssen Sie auch eine FormModelValidator erstellen, die den AddressValidator ruft und BillingAddressValidator:

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

} 
+0

, die mir ein neues Problem gibt;) ich versuche, die Rechnungsanschrift und AddressObjects zu validieren ihre eigenen Validatoren verwenden, aber die BindingResult Objekt bezieht sich auf das FormModel-Objekt und kann daher keines der fehlerhaften Felder von den anderen 2 Objekten darauf finden. – mkoryak

+0

Wenn ich Sie richtig verstehe, haben Sie benutzerdefinierte Validatoren für Adresse und Rechnungsadresse. In diesem Fall müssen Sie einen FormModelValidator erstellen, der Ihre benutzerdefinierten Validatoren aufruft. Ich habe ein Beispiel in meine Antwort oben hinzugefügt. –