Printemps DTO de validation dans le Service ou le Contrôleur?
Je suis en train de construire un simple AJAX /JSON web service avec le Printemps. La commune de flux de données est:
some DTO from browser
v
Spring @Controller method
v
Spring @Service method
Je suis à la recherche de la plus simple façon de gérer la validation des données.
- Je sais que le
@Valid
annotation qui fonctionne plutôt bien à l'intérieur de@Controller
méthodes. - Pourquoi ne
@Valid
pas de travail au sein de@Service
méthodes?
Je veux dire: Une méthode de service peut être utilisé par un autre service et de contrôleur. Donc ne serait-il pas beaucoup plus de sens à valider au @Service
niveau?
Prenons cet exemple simple:
MyDTO.java:
public class MyDTO {
@NotNull
public String required
@Min(18)
public int age;
}
MyServiceImpl.java:
public MyDomainObject foo(MyDTO myDTO) {
//persist myDTO
//and return created domain object
}
MyController.java:
@Autowired
MyService myService;
@Autowired //some simple bean mapper like Dozer or Orika
Mapper mapper; //for converting domain objects to DTO
@RequestMapping(...)
public MyDomainObjectDTO doSomething(@RequestBody MyDTO myDTO) {
mapper.map(myService.foo(myDTO), MyDomainObjectDTO.class);
}
Il est de pratique courante que la méthode de service reçoit les DTO?
- Si
yes
: Quelle est la meilleure pratique pour valider que les DTO à l'intérieur de la méthode de service? - Si
no
: peut-être Devrais-le contrôleur de manipuler l'objet du Domaine et de laisser le service de sauver cet objet? (cela semble assez inutile pour moi)
À mon avis, le service ne devrait être responsable que de la cohérence des données.
Comment voulez-vous résoudre ce problème?
double possible de Vérifiez les conditions préalables au Contrôleur ou de la couche de Service
OriginalL'auteur Benjamin M | 2013-09-30
Vous devez vous connecter pour publier un commentaire.
Ma réponse? Les deux.
Le service doit vérifier son propre contrat de validité.
Le contrôleur est partie de l'INTERFACE utilisateur. Il doit le valider et de le lier pour une meilleure expérience utilisateur, mais le service ne doit pas compter sur elle.
Le service ne peut pas savoir comment on l'appelle. Que faire si vous l'envelopper comme un service REST?
Le service sait aussi sur la logique des affaires de violations de la manière qu'aucune INTERFACE utilisateur. Il doit valider pour vous assurer que le cas d'utilisation est remplie adéquatement.
Sac Double; de faire les deux.
@Valid
annotations? ... J'ai reçu votre point, le service et le contrôleur peut utiliser (par exemple) les différents champs dans leurs classes. Dans mon application, c'est toujours la même. De ce fait, je viens de passer à travers la DTO dans le service.Car il y a une différence entre la validation et la défensive de programmation/gestion des erreurs. Cela étant dit, je ne l'utilisation de validation pour une programmation défensive. Je vais poster une réponse bientôt.
OriginalL'auteur duffymo
Voir mon autre réponse: Vérifiez les conditions préalables au Contrôleur ou de la couche de Service
Si vous voulez vraiment faire de la validation, comme la gestion des erreurs dans votre couche de Service similaire à Spring MVC, vous pouvez utiliser
javax.validation
et AspectJ (les conseils, les méthodes pour valider) qui est ce que je fais parce que j'aime faire de réflexion, de travail et de programmation déclarative (annotations).Spring MVC n'a pas besoin de faire AspectJ/AOP faire l'erreur de manipulation, car les méthodes sont appelés par le biais de la réflexion (le routage d'url/expédition).
Enfin pour vous MVC code, vous devez savoir que
@Valid
est une sorte de non-officiellement obsolète. Au lieu de considérer@Validé
qui aura un effet de levier plus de lajavax.validation
fonctionnalités.@Validated
à la couche de Service, ce qui est assez impressionnant. Il suffit de s'inscrire PrintempsMethodValidationPostProcessor
, puis mettre@Validated
annotation sur l'interface du Service lui-même et le dernier mais non moins mettre quelques@Valid
ou@NotNull
annotations sur les signatures de méthode définie dans l'Interface de Service. Le ServiceImpl reste propre. Cela fonctionne très bien! Le seul "problème" est que lapropertyPath
au sein de l'jetésConstraintViolationException
obtenir le préfixe avec l'ensemble de la hiérarchie d'appel, c'est à direcontrollerMethod.serviceMethod.dtoProperty
. Je dois en quelque sorte de se débarrasser de ce.Qu'entendez-vous par "sorte de non-officiellement obsolète'?
OriginalL'auteur Adam Gent