2012-04-04 11 views
5

Ultimi mvc molla, utilizzando freemarker.Confuso su come convalidare il modulo mvc di primavera, quali sono le mie opzioni?

Sperando che qualcuno potrebbe dirmi quali sono le mie opzioni sono in termini di convalida di un modulo con MVC primavera, e ciò che il consiglio modo sarebbe quello di fare questo.

Ho una forma che non mappa direttamente a un modello, ha campi di input che al momento della pubblicazione, verrà utilizzato per inizializzare 2 oggetti del modello che ho Sarà quindi necessario per convalidare, e se passano io li salverà .

Se falliscono, voglio tornare al modulo, pre-riempire i valori con ciò che l'utente è entrato e visualizzare i messaggi di errore.

Ho letto qua e là circa 2 metodi, una volta di che ho fatto e capire come funziona:

@RequestMapping(...., method = RequestMethod.POST) 
public ModelAndView myMethod(@Valid MyModel, BindingResult bindingResult) { 
    ModelAndView mav = new ModelAndView("some/view"); 
    mav.addObject("mymodel", myModel); 

    if(bindingResult.hasErrors()) { 
    return mav; 
    } 

} 

Ora, questo ha funzionato se il mio modulo mappato direttamente alla forma, ma nella mia situazione mi avere:

  1. campi modulo che non si associano a un modello specifico, hanno alcune proprietà di 2 modelli.

  2. prima della convalida occurrs, ho bisogno di creare i 2 modelli manualmente, impostare i valori dalla forma, e impostare manualmente alcune proprietà anche:

  3. chiamata validate su entrambi i modelli (model1, model2), e aggiungere questi messaggi di errore alla raccolta di errori che ho bisogno di passare alla stessa pagina di vista se le cose non funzionano.

  4. quando i posti di forma, devo fare alcune chiamate al database, e sulla base di questi risultati potrebbe essere necessario aggiungere ulteriori messaggi alla collezione errori.

Qualcuno può dirmi come eseguire questo tipo di convalida?

Pseudo codice qui sotto:

Model1 model1 = new Model1(); 
    Model2 model2 = new Model2(); 

    // manually or somehow automatically set the posted form values to model1 and model2. 

    // set some fields manually, not from posted form 
    model1.setProperty10(GlobalSettings.getDefaultProperty10()); 
    model2.setProperty11(GlobalSettings.getDefaultProperty11()); 

    // db calls, if they fail, add to errors collection 

    if(bindingResult.hasErrors()) { 
    return mav; 
    } 

    // validation passed, save 
    Model1Service.save(model1); 
    Model2Service.save(model2); 

    redirect to another view 

Aggiornamento

ho utilizzando le annotazioni JSR 303 sui miei modelli in questo momento, e sarebbe bello se posso usare quelli ancora.

Aggiornamento II

Si prega di leggere la descrizione di taglie sotto per un riepilogo di quello che sto cercando.

risposta

8

Sulla base di un'esperienza simile, proporrei quanto segue e sul lato ho un commento sull'ultimo passaggio sull'approccio che si desidera adottare. Io uso il tuo elenco numerato di passaggi.

Fase 1: Modulo Bean

Ci sono due modi per questo.L'approccio semplice è quello di definire una forma di fagiolo (che presumo che hai già fatto):

class MyModel { 
    private Model1 model1; 
    private Model2 model2; 
    // standard Java bean stuff 
} 

Un modo più preciso è quello di definire in realtà MyModel tale che io prenda in prestito solo i campi che richiedono da Model1 e Model2 ma Non sono sicuro se questo ti si adatta.

Fase 2: Associazione dati

primavera fa questo per voi, se si dispone di tale form struttura nella vista:

<form:form modelAttribute="myModel"> 
    <form:input path="model1.somePropertyToBeSet" /> 
</form:form> 

Fase 3: convalida

Utilizzando Spring custom validations, è possibile definire vincoli Om:

@interface Model1Constraint {} 
@interface Model2Constraint {} 

class MyModel1 { 

    @Model1Constraint 
    private Model1 model1; 

    @Model2Constraint 
    private Model2 model2; 

    // ... 

} 

quindi registrare i tuoi validatori personalizzati per i vincoli personalizzati:

class Model1ConstraintValidator implements ConstraintValidator<Model1Constraint, Model1> { 
// implementation of isValid and initalize 
} 

e lo stesso per Model2Constraint. Utilizzando i validatori personalizzati, è possibile verificare quale logica è necessario garantire prima che il MyModel venga passato al metodo di elaborazione delle richieste. Presumo anche che tu abbia usato <mvc:annotation-driven /> per far registrare a Spring i validatori; altrimenti, dovresti configurarli.

Fase 4: elaborazione modello personalizzato prima richiesta di trasformazione

La tua idea originale è quella di utilizzare alcuni dati legante per questo lavoro. Nella descrizione, si menziona anche che questa elaborazione dati non corrisponde a dipende dai dati provenienti dai dati del modulo.

Per quanto riguarda il design e la modularità, non credo che un raccoglitore di dati sia un buon posto per tale scopo. In secondo luogo, poiché non esiste alcuna dipendenza dei dati dal modulo, la ragione principale per te è consentire l'elaborazione degli errori di associazione dei dati.

Quindi, il mio suggerimento è che diciamo che ora sei in public ModelAndView myMethod(@Valid MyModel model, BindingResult bindingResult). Presumibilmente, hai accesso ad altri bean di servizio qui. Quindi, si può avere un metodo in qualche chicco di servizio che può refine o prepare (solo i nomi) l'model che hai popolato in questo punto. In base alle eccezioni o qualsiasi altro meccanismo che fa per te, è possibile utilizzare bindingResult per restituire nuovamente gli errori.

Come altro suggerimento, si può anche sfruttare il Spring interceptors se si desidera un altro modo DI/IoC per farlo. Ma in questo modo, si dovrebbe estrarre MyModel da ModelAndView in intercettazioni e procedere.

Spero che questo aiuti.

0

Hibernate Validator 4.2 supporta la validazione livello di metodo. Puoi rifattorizzare il tuo codice un po 'per passare i due modelli in un metodo e convalidarli.

http://java.dzone.com/articles/method-validation-spring-31

si può avere qualcosa di simile

public void persistUser(@NotNull @Valid Model1 model1, @NotNull @Valid Model2 model2) { 

     //continue ... 
} 
0

Questo è un problema insolito, come di solito ha più senso per convalidare l'input dell'utente, in quanto questo è il dato non possiamo controllo. Detto questo, e visto che sono sicuro che lo sapevi già ...

Un'opzione consisterebbe nell'utilizzare l'API di convalida JSR 303 direttamente per convalidare gli oggetti del modello dopo che sono stati compilati dall'input dell'utente, database , ecc ..

Ecco un esempio:

@RequestMapping(value=...) 
public String myMethod(MyForm form, Model m) { 

    ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); 
    Validator validator = factory.getValidator(); 

    Model1 model1 = createModel1FromUserInput(form); 
    Model2 model2 = createModel2FromUserInput(form); 

    Set<ConstraintViolation<?>> modelViolations = validator.validate(model1); 
    modelViolations.add(validator.validate(model2)); 
    if(modelViolations.size() != 0) { 
     m.addAttribute("violations", modelViolations); 
     m.addAttribute("form", myForm); // add the form back to the model so it is populated 
     return "formPage"; 
    } 
    return "successPage"; 
} 

Si può preferire di legarsi ad una primavera BindingResult o un insieme di errori. Non ho ancora testato il seguente codice, e non sono molto bene a lavorare direttamente con BindingResult, ti richiedono tweaking:

BindingResult result = ... // not sure about the constructor 
for(ConstraintViolation<?> violation : modelViolations) { 
     result.addError(new ObjectError(violation.getPropertyPath().toString(),violation.getMessage())); 
} 

Se si sta solo cercando di sputare gli errori sul JSP, quindi utilizzando un Set<ConstraintViolation> può funzionare abbastanza bene per le vostre esigenze:

<c:forEach items="${violations}" var="violation"> 
    ${violation.propertyPath}: ${violation.message} <br/> 
</c:forEach> 

Se si sta tentando di utilizzare tag di primavera <form:errors>, è necessario utilizzare il risultato vincolante.

HTH! Fammi sapere se hai altre domande. O se ho completamente mancato il segno su questa risposta, cercherò di chiarire.

Problemi correlati