2012-08-13 3 views
10

Ich verwende die Google Preconditions-Klasse, um die Eingabedaten des Benutzers zu überprüfen.
Aber ich bin besorgt, wo ist der beste Punkt der Benutzer Eingabedaten mit Preconditions Klasse zu überprüfen.
Zuerst schrieb ich Check-Code-Validierung in-Controller wie folgt:Überprüfen Sie die Vorbedingungen in der Controller- oder Serviceschicht

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

Aber ich dachte, dass register Verfahren in Service-Schicht wie unter einer anderen Controller-Methode wäre mit:

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

Auf der anderen Seite würde die Methode der Dienstschicht in nur einem Controller verwendet werden.
Ich war verwirrt. Was ist der beste Weg, die Voraussetzungen in Controller oder Service zu überprüfen?
Vielen Dank im Voraus.

Antwort

17

Idealerweise würden Sie es an beiden Orten tun. Aber Ihre verwirrend zwei verschiedene Dinge:

  • Validation (mit Fehlerbehandlung)
  • Defensivie Programming (aka Behauptungen, aka Design by Contract).

sollten Sie tun, absolut Validierung in der Steuerung und defensive Programmierung in Ihren Diensten. Und hier ist warum.

Sie müssen validieren für Formulare und REST-Anforderungen, damit Sie einen sinnvollen Fehler zurück an den Client senden können. Dies beinhaltet, welche Felder schlecht sind und dann die Lokalisierung der Fehlermeldungen ... etc ... (Ihr aktuelles Beispiel würde mir eine schreckliche 500 Fehlermeldung mit einem Stack-Trace senden, wenn die ProductInfo.name -Eigenschaft null war).

Feder hat eine solution for validating objects in der Steuerung.

Defensive Programmierung wird in der Dienstschicht gemacht, ABER NICHT Validierung, weil Sie haben keinen Zugriff auf locale richtige Fehlermeldungen zu erzeugen. Manche Leute tun, aber der Frühling hilft dir dort nicht wirklich.

Der andere Grund, warum die Validierung in der Service-Schicht nicht durchgeführt wird, ist, dass das ORM dies normalerweise durch die JSR-Bean-Validierungsspezifikation (Hibernate) tut, aber keine sinnvollen Fehlermeldungen generiert.

Eine Strategie, die Menschen tun, ist es eigene Voraussetzungen utils-Bibliothek zu erstellen, die benutzerdefinierten RuntimeException s anstelle von Guave des abgeleiteten Würfe (und commons lang) IllegalArgumentException und IllegalStateException und dann try ... catch die Ausnahmen in der Steuerung, sie zu Validierungsfehler bei dem Konvertieren Mitteilungen.

2

Es gibt keinen "besseren" Weg. Wenn Sie denken, dass der Dienst von mehreren Controllern (oder anderen Code-Stücken) verwendet wird, kann es sinnvoll sein, dort die Überprüfungen durchzuführen. Wenn es für Ihre Anwendung wichtig ist, ungültige Anfragen zu prüfen, während sie sich noch im Controller befinden, kann es sinnvoll sein, dort die Überprüfungen durchzuführen. Diese zwei, wie Sie bemerkt haben, schließen sich nicht gegenseitig aus. Sie müssen möglicherweise zweimal überprüfen, um beide Szenarien abzudecken.

Eine weitere mögliche Lösung: Verwenden Sie die Bean-Validierung (JSR-303), um die Prüfungen (Vorbedingungen) auf die ProductInfo-Bean selbst zu setzen. Auf diese Weise geben Sie die Überprüfungen nur einmal an, und alles, was erforderlich ist, kann die Bean schnell validieren.

+0

Ich stimme definitiv zu, dass Sie die Bean-Validierung verwenden sollten, insbesondere wenn Ihr DAO ORM verwendet. – hyness

0

Ich denke, in Ihrem speziellen Fall müssen Sie es auf Service-Layer überprüfen und Ausnahme an Controller im Falle von Datenintegritätsfehler zurückgeben.

@controller 
public class MyController{ 

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

} 

Es hängt auch davon ab, was Sie in Controller tun. ob Sie View zurückgeben oder einfach @ResponseBody Annotation verwenden. Spring MVC hat eine schöne "out of the box" -Lösung für die Eingabe/Datenüberprüfung Ich empfehle Ihnen, diese Bibliotheken zu überprüfen.

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

0

Voraussetzungen, Validierungen, ob einfach oder Unternehmen soll bei der Filterschicht oder durch Abfangjäger behandelt wird, noch bevor die Steuerung oder Dienstschicht zu erreichen.

Die Gefahr, wenn Sie es in Ihrer Controller-Schicht überprüfen, verletzen Sie das Prinzip der einheitlichen Verantwortung eines Controllers, dessen einziger Zweck ist, Anfrage und Antwort zu delegieren.

Durch die Einführung von Vorbedingungen in der Service-Schicht werden Querschnittsaufgaben in das Kerngeschäft eingeführt.

Filter oder Inzeptor ist für diesen Zweck gebaut. Durch das Vorgeben von Vorbedingungen auf der Filterschicht oder in Interzeptoren können Sie Regeln, die Sie für jede Servletanforderung im Stapel platzieren können, auswählen und anpassen, sodass eine bestimmte Regel nicht auf eine einzige Servletanforderung beschränkt bleibt oder Duplikate eingeführt werden.

Verwandte Themen