2012-08-13 11 views
10

Utilizzo la classe Preconditions di Google per convalidare i dati di input dell'utente.
Ma sono preoccupato di dove sia il punto migliore per verificare i dati di input dell'utente utilizzando la classe Preconditions.
In primo luogo, ho scritto validazione del codice del check-in di controllo come di seguito:Verificare le precondizioni nel livello Controller o Service

@Controller 
... 
public void register(ProductInfo data) { 
    Preconditions.checkArgument(StringUtils.hasText(data.getName()), 
     "Empty name parameter."); 
    productService.register(data); 
} 

@Service 
... 
public void register(ProductInfo data) { 
    productDao.register(data); 
} 

ma ho pensato che register metodo livello di servizio sarebbe utilizzando un altro metodo di controllo come di seguito:

@Controller 
... 
public void register(ProductInfo data) { 
    productService.register(data); 
} 
public void anotherRegister(ProductInfo data) { 
    productService.register(data); 
} 

@Service 
... 
public void register(ProductInfo data) { 
    Preconditions.checkArgument(StringUtils.hasText(data.getName()), 
     "Empty name parameter."); 
    productDao.register(data); 
} 

D'altra parte , il metodo del livello di servizio verrebbe utilizzato in un solo controller.
Ero confuso. Qual è il modo migliore per controllare le precondizioni nel controller o nel servizio?
Grazie in anticipo.

risposta

17

Idealmente lo faresti in entrambi i posti. Ma i tuoi confondere due cose diverse:

  • convalida (con la gestione degli errori)
  • Defensivie Programmazione (aka affermazioni, alias di progettazione per contratto).

È assolutamente dovrebbe fare convalida nel controller e programmazione difensiva nel vostro servizio. Ed ecco perché.

È necessario convalidare per le richieste di moduli e REST in modo che sia possibile inviare un errore sensibile al client. Questo include quali campi sono cattivi e quindi si effettua la localizzazione dei messaggi di errore ... ecc ... (il tuo esempio attuale mi manderebbe un orribile messaggio di errore 500 con una traccia stack se la proprietà ProductInfo.name era null).

La molla ha un solution for validating objects nel controller.

difensiva programmazione è fatto nel livello di servizio ma non convalida perché non hanno accesso a locale da generare messaggi di errore corretto. Alcuni lo fanno, ma Spring non ti aiuta davvero.

L'altro motivo per cui la convalida non viene eseguita nel livello di servizio è che l'ORM esegue già questo tramite la specifica di convalida del bean JSR (sospensione), ma non genera messaggi di errore sensibili.

Una strategia le persone fanno è quello di creare una propria libreria ci precondizioni utils che lancia personalizzata derivata RuntimeException s invece di guava (e di beni comuni Lang) IllegalArgumentException e IllegalStateException e poi try ... catch le eccezioni di cui il controller di convertirli in errore di convalida messaggi.

2

Non esiste un modo "migliore". Se pensate che il servizio verrà utilizzato da più controller (o altri pezzi di codice), allora potrebbe essere logico eseguire i controlli lì. Se è importante che l'applicazione controlli le richieste non valide mentre sono ancora nel controller, potrebbe essere logico eseguire i controlli lì. Questi due, come hai notato, non si escludono a vicenda. Potrebbe essere necessario controllare due volte per coprire entrambi gli scenari.

Un'altra possibile soluzione: utilizzare Bean Validation (JSR-303) per inserire i controlli (precondizioni) sul bean ProductInfo stesso. In questo modo si specificano solo i controlli una volta e tutto ciò che è necessario può convalidare rapidamente il bean.

+0

Definitivamente d'accordo che si dovrebbe usare la convalida del bean, specialmente se il DAO sta usando ORM. – hyness

0

Penso che nel caso particolare sia necessario controllarlo sul livello di servizio e restituire l'eccezione al controller in caso di errore di integrità dei dati.

@controller 
public class MyController{ 

@ExceptionHandler(MyDataIntegrityExcpetion.class) 
public String handleException(MyDataIntegrityExcpetion ex, HttpServletRequest request) { 
    //do someting on exception or return some view. 
} 

} 

Dipende anche da ciò che si sta facendo nel controller. se si restituisce Visualizza o si utilizza semplicemente l'annotazione @ResponseBody. Spring MVC ha una soluzione "pronta all'uso" per la validazione di input/dat. Ti consiglio di controllare queste librerie.

http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/validation.html

0

Presupposti, convalide, semplici o struttura devono essere manipolati secondo strato filtro o da intercettori, anche prima di raggiungere lo strato controller o servizio.

Il pericolo se lo si controlla nel livello controller, si sta violando il principio di responsabilità singola di un controller, il cui unico scopo è delegare richiesta e risposta.

Porre le precondizioni nel livello di servizio introduce problemi trasversali al core business.

Il filtro o l'intercettatore è costruito per questo scopo. Mettendo le precondizioni allo strato filtro o agli intercettatori, è possibile anche "selezionare e abbinare" le regole che si possono inserire nello stack per ogni richiesta servlet, quindi non confinare una regola particolare con una sola richiesta servlet o introdurre la duplicazione.

Problemi correlati