2014-07-15 13 views
14

Di seguito è riportato il metodo mappato con cui ho problemi, indipendentemente dal valore che viene passato, la convalida restituisce "convalida passata".Spring MVC con hibernate Validator per convalidare il tipo base singolo

@RequestMapping(value = "test", method = RequestMethod.POST) 
@ResponseBody 
public String getTest(@RequestBody @Valid @Max(32) long longValue, BindingResult result) { 
    if (result.hasErrors()) { 
    return "failed validation"; 
    } else { 
    return "passed validation"; 
    } 
} 

So che il @Max funziona con la mia domanda perché lo uso per la validazione su oggetti personalizzati che restituiscono un sacco di dati al controllore. Solo in questo caso non esegue la validazione, dove chiamo @Valid e il tipo di validazione sull'oggetto nei parametri del metodo.

Non è consentito con il sistema di verifica dell'ibernazione?

Spero di non dover definire un oggetto che contiene solo un valore lungo solo per poter eseguire la convalida su di esso.

risposta

3

Spero di non dover definire un oggetto che contiene solo una lunga valore solo in modo che posso fare funzionare la validazione su di esso.

Definizione di un chicco di avvolgimento sarebbe IMHO essere la mossa più intelligente, come hibernate-validator è completamente incentrata sulla nozione di fagioli, ed è, dopo tutto, un'implementazione di riferimento della specifica convalida di fagioli. Uno dei principali motivatori delle specifiche è riconoscere la convalida come una preoccupazione trasversale che si estende tra diversi livelli di app e fornire un meccanismo per gestirlo con garbo. Questo è il motivo per cui è centrato attorno ai fagioli, sono gli oggetti che vengono passati attraverso i livelli.

D'altra parte, la convalida primitves modo pianificato non è un grosso problema, dopo tutto, il codice può essere semplicemente qualcosa di simile

@RequestMapping(value = "test", method = RequestMethod.POST) 
@ResponseBody 
public String getTest(@RequestBody long longValue, BindingResult result) { 
    if (longValue > 32) { 
    result.rejectValue("longValue", "error.longValue", "longValue max constrained failed"); 
    return "failed validation"; 
    } else { 
    return "passed validation"; 
    } 
} 

Quindi, a mio parere, andare per la validazione programmatico se abbastanza semplice, o semplicemente avvolgere il valore.

+0

Non penso che l'opzione wrapper sarebbe l'opzione migliore nel mio caso, perché dovrei avere un wrapper per ogni annotazione che si applica a primitive, String e tutti gli altri singoli tipi di base. E convalidandolo nel codice penso che andrebbe bene, ma vorrei mantenere una certa coerenza sul modo in cui convalidare gli oggetti. Vorrei convalidare tutti i tipi di oggetti con il validatore di ibernazione o qualcuno di loro ... Quindi non ero disposto ad ascoltare che il validatore di ibernazione non convalida questo tipo di cose: P Grazie comunque per la tua risposta! – jscherman

2

No, non è consentito. Tuttavia, la specifica JSR-303 (che implementa le implementazioni di validatore) è intesa per la convalida dei bean, vedere here

2

Innanzitutto, come dichiarato da altre risposte, Hibernate Validator non consente di convalidare direttamente le primitive come nell'esempio in la domanda. Per utilizzare Hibernate Validator, definire una nuova classe contenente un valore lungo è esattamente ciò che è necessario per utilizzare Hibernate Validator.

Secondo, e il più importante, mentre la convalida programmatica è qualcosa che funziona ed è abbastanza semplice, non è pulita e manutenibile. Lasciatemi illustrare questo con alcuni esempi:

@RequestMapping(value = "testA", method = RequestMethod.POST) 
@ResponseBody 
public String getTestA(@RequestBody long longValue, BindingResult result) { 
    if (longValue > 32) { 
    result.rejectValue("longValue", "error.longValue", "longValue max constrained failed"); 
    return "failed validation for test A"; 
    } else { 
    return "passed validation for test A"; 
    } 
} 


@RequestMapping(value = "testB", method = RequestMethod.POST) 
@ResponseBody 
public String getTestB(@RequestBody long longValue, BindingResult result) { 
    if (longValue > 32) { 
    result.rejectValue("longValue", "error.longValue", "longValue max constrained failed"); 
    return "failed validation for test B"; 
    } else { 
    return "passed validation for test B"; 
    } 
} 


@RequestMapping(value = "testC", method = RequestMethod.POST) 
@ResponseBody 
public String getTestC(@RequestBody long longValue, BindingResult result) { 
    if (longValue > 32) { 
    result.rejectValue("longValue", "error.longValue", "longValue max constrained failed"); 
    return "failed validation for test C"; 
    } else { 
    return "passed validation for test C"; 
    } 
} 

prima cosa da notare, è withing 3 funzioni semplici, tutto il codice di convalida è duplicato.

In secondo luogo, se a un certo punto i requisiti di convalida cambiano, e ora tutti i valori lunghi devono essere maggiori di 35, è necessario modificare ogni singola funzione di convalida, e in questo esempio è davvero semplice, perché ci sono solo 3 funzioni con la stessa validazione, ma immaginate per un momento che siano 100 funzioni in cui eseguite la stessa validazione, ora è doloroso.

Quindi, semplicemente definendo una nuova classe, con il valore lungo e l'annotazione di convalida e utilizzando tale classe su ogni metodo, è stata rimossa la duplicazione del codice e anche quando i requisiti di convalida cambiano, applicando le modifiche in un unico punto, si ha mantenuto il codice.

Inoltre, non c'è nulla di sbagliato nel dover definire le classi per un compito specifico, infatti, questo è esattamente ciò che Single Responsability Principle ti dice di fare.

Modifica: aggiunto un collegamento a una descrizione SRP.

Problemi correlati