2012-08-13 5 views
10

J'utilise la classe Préconditions de Google pour valider les données d'entrée de l'utilisateur.
Mais je suis inquiet de savoir où est le meilleur point de vérifier les données d'entrée de l'utilisateur en utilisant la classe Preconditions.
D'abord, j'écrit le code de vérification de validation dans le contrôleur comme ci-dessous:Vérifier les conditions préalables dans la couche Contrôleur ou 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); 
} 

Mais je pense que la méthode register dans la couche de service serait d'utiliser une autre méthode de contrôleur comme ci-dessous:

@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'autre part , la méthode de couche de service serait utilisée dans un seul contrôleur.
J'étais confus. Quelle est la meilleure façon de vérifier les conditions préalables du contrôleur ou du service?
Merci d'avance.

Répondre

17

Idéalement, vous le feriez aux deux endroits. Mais votre confusion entre deux choses différentes:

  • Validation (avec gestion des erreurs)
  • Defensivie programmation (aka affirmations, alias conception par contrat).

Vous devez absolument faire la validation dans le contrôleur et programmation défensive dans votre service. Et voici pourquoi.

Vous devez valider pour les formulaires et les demandes REST afin de pouvoir renvoyer une erreur sensible au client. Cela inclut les champs qui sont mauvais et ensuite la localisation des messages d'erreur ... etc ... (votre exemple actuel m'enverrait un horrible message d'erreur 500 avec une trace de pile si la propriété ProductInfo.name était nulle).

Le ressort a un solution for validating objects dans le contrôleur.

programmation défensive est fait dans la couche de service, mais pas validation parce que vous n'avez pas accès aux locaux, pour générer des messages d'erreur appropriés. Certaines personnes le font mais le printemps ne vous aide pas vraiment là-bas.

L'autre raison pour laquelle la validation n'est pas effectuée dans la couche de service est que l'ORM le fait déjà typiquement via la spécification JSR Bean Validation (hibernate) mais ne génère pas de messages d'erreur sensibles.

Un peuple de stratégie faire est de créer il y a bibliothèque propre utils préconditions qui lancers francs dérivé coutume RuntimeException s au lieu de de goyave (et communes lang) IllegalArgumentException et IllegalStateException puis try ... catch les exceptions dans le contrôleur pour les convertir à une erreur de validation messages.

2

Il n'y a pas de "meilleur" moyen. Si vous pensez que le service va être utilisé par plusieurs contrôleurs (ou d'autres morceaux de code), il peut être judicieux de faire les vérifications ici. S'il est important pour votre application de vérifier les demandes non valides pendant qu'elles sont encore dans le contrôleur, il peut être judicieux d'effectuer les vérifications à cet endroit. Ces deux, comme vous l'avez remarqué, ne s'excluent pas mutuellement. Vous devrez peut-être vérifier deux fois pour couvrir les deux scénarios.

Une autre solution possible: utilisez Bean Validation (JSR-303) pour mettre les vérifications (conditions préalables) sur le haricot ProductInfo lui-même. De cette façon, vous ne spécifiez les contrôles qu'une seule fois, et tout ce qui est nécessaire peut rapidement valider le bean.

+0

Décidément d'accord que vous devriez utiliser la validation du bean, surtout si votre DAO utilise ORM. – hyness

0

Je pense que dans votre cas particulier, vous devez le vérifier sur la couche Service et renvoyer l'exception au contrôleur en cas d'erreur d'intégrité des données.

@controller 
public class MyController{ 

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

} 

Cela dépend aussi de ce que vous faites dans le contrôleur. que vous retourniez View ou que vous utilisiez simplement @ResponseBody Annotation. Spring MVC a une belle solution "prête à l'emploi" pour la validation des entrées/datées Je vous recommande de vérifier ces bibliothèques.

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

0

Préalables, validation, simple ou entreprise doit être manipulé à la couche filtrante ou par des intercepteurs, avant même d'atteindre la couche de contrôleur ou d'un service.

Le danger si vous le vérifiez dans votre couche de contrôleur, vous violez le principe de la responsabilité unique d'un contrôleur, dont le seul but est de déléguer la demande et la réponse.

La mise en place de conditions préalables dans la couche de service introduit des problèmes transversaux au cœur de métier.

Le filtre ou l'incepteur est construit à cette fin. Mettre des conditions préalables sur la couche de filtre ou dans les intercepteurs vous permet également de "choisir et de faire correspondre" les règles que vous pouvez placer dans la pile pour chaque requête de servlet, ne limitant ainsi pas une règle particulière à une seule demande.

Questions connexes