2011-01-14 8 views
7

Sto cercando di bagnarmi i piedi con Spring MVC 3.0, e mentre riesco a farlo funzionare, non riesco a gestire questo particolare scenario in modo efficiente.Spring MVC 3.0: come convalidare la variabile di percorso globale per tutte le associazioni di richieste in modo efficiente?

Ho un controller con che gestisce "/ {studyName}/modulo" prefisso, e sembra qualcosa di simile: -

@Controller 
@RequestMapping(value = "/{studyName}/module") 
public class ModuleController { 

    @RequestMapping(...) 
    public ModelAndView getA(@PathVariable String studyName, ...) { 
     if (!validStudy(studyName)) { return bad request; } 
     ... 
    } 

    @RequestMapping(...) 
    public ModelAndView getB(@PathVariable String studyName, ...) { 
     if (!validStudy(studyName)) { return bad request; } 
     ... 
    } 

    @RequestMapping(...) 
    public ModelAndView getC(@PathVariable String studyName, ...) { 
     if (!validStudy(studyName)) { return bad request; } 
     ... 
    } 

    @RequestMapping(...) 
    public ModelAndView getD(@PathVariable String studyName, ...) { 
     if (!validStudy(studyName)) { return bad request; } 
     ... 
    } 
} 

Il problema con questo codice è, ho la convalida studyName sparsi in tutto oltre i metodi e possibilmente anche in altri metodi di controllo. C'è un modo in cui posso eseguire la validazione su studyName path variable tutto in un punto senza usare qualcosa come AOP? Come gestisci la convalida in questo modo?

Grazie.

risposta

2

Al momento, è un po 'complicato far sì che ciò accada automaticamente, ma è possibile. È necessario utilizzare un provider di convalida Bean (JSR-303) che implementa l'appendice C. Attualmente Apache BeanValidation o Hibernate Validator 4.2 (che è in versione beta).

Aggiungere l'implementazione di convalida del bean selezionata al classpath. Questa sarà l'implementazione di JSR-303 utilizzata da Spring MVC.

In secondo luogo, annotare il parametro metodo con @Valid e qualsiasi annotazione di vincolo, come @NonNull.

Questa sarà simile:

public ModelAndView getB(@Valid @NonNull @PathVariable String studyName, ...) { 

che dovrebbe funzionare. Dovresti quindi verificare gli errori Spring per qualsiasi problema.

In alternativa, se non si fanno uso di altri parametri di primavera, è possibile registrare un validatore con un'InitBinder in questo modo:

@InitBinder 
public void initBinder(WebDataBinder binder) { 
    binder.setValidator(new StudyNameValidator()); 
} 
+0

+1 a te. Ho guardato a @valid, ma nel mio caso, probabilmente dovrò creare la mia annotazione di convalida personalizzata perché devo controllare se lo studyName è registrato nel mio database, quindi non posso usare le convalide integrate dal validatore di hibernate. Per quanto riguarda il binding di un validatore, ho ancora bisogno di controllare "if (binder.hasErrors()) {do something}" in ogni metodo del controller, che è esattamente il problema che ho di fronte. Forse, questa è l'unica soluzione elegante disponibile al momento, ma mi fa davvero impazzire vedere lo stesso controllo ripetuto in ogni metodo. – limc

+0

Se la convalida è per verificare che qualcosa esista nel DB, supponendo che sia probabile, farei semplicemente la query e registrerò un metodo @ExceptionHandler per gestire il caso improbabile che non sia così. – GaryF

+1

Per quanto posso dire, non è ancora possibile utilizzare l'annotazione valida con PathVariable: https://jira.springsource.org/browse/SPR-6380 –

0

Creare una semplice classe di convalida:

public class StudyValidator { 
    public boolean validateStudy(String studyName) { 
     //your validate logic here 
    } 
} 

poi iniettarlo nel ModuleController:

class ModuleController { 
    private StudyValidator sv = new StudyValidator(); //use spring injection to populate. 
    boolean validStudy(String studyName) { 
     return sv.validateStudy(studyName); 
    } 
} 

Semplici.

+0

Sì, ma ho ancora bisogno di richiamare validStudy() in ogni metodo, che è esattamente il problema io faccia ora. – limc

+0

Penso che invocare un metodo sia molto meno malvagio, che passare attraverso la pazzia di configurazione di Spring e creare un'intera classe pazza per ridurre quella chiamata di linea. Perché stiamo rendendo le nostre vite così incredibilmente complesse nel nome della semplicità? –

+0

Ho frainteso l'obiettivo della domanda di essere la modularizzazione del codice comune da utilizzare in più controllori. La convalida dei bean di cui sopra sembra carina! :) – DrUseful

0

Hmmm, non è sicuro se avrebbe funzionato, ma si potrebbe essere in grado di l'annotazione @Valid come briefly mentioned in this link on validators.

Good Luck!

+0

Ho guardato @Valid, che sembra convalidare solo il modello usando hibernate validator 4 o la mia classe di validatore personalizzata. – limc

1

Creare una classe StudyName quindi disporre di WebArgumentResolver registrato per StudyName e la convalida viene eseguita qui.

public ModelAndView getA(@PathVariable StudyName studyName){ 
     ... 
    } 

    public class StudyNameResolver implements WebArgumentResolver{ 
     //have resolveArgument method do validation if resolved to a StudyName 
    } 
+0

+1 per rendermi consapevole di WebArgumentResolver. L'ho già visto prima, ma sono riluttante a utilizzarlo perché potrei dover creare alcuni risolutori personalizzati per questo particolare progetto. – limc

1

Sto iniziando a usare molla 3 e mi piace la soluzione di validare in questo modo: pubblico ModelAndView getB (@Valid @NonNull @PathVariable String studyName, ...) {

Tuttavia, una volta che il pathvariable è valido (in questo caso studyName = null) come si fa a prendere e la visualizzazione quell'errore?

Ho provato a utilizzare il risultato del binding ma non funziona. Inoltre, sai come visualizzare l'errore sul jsp?

Grazie

Problemi correlati