MVC @Valid Validation with custom HandlerMethodArgumentResolver

je veux enregistrer une coutume HandlerMethodArgumentResolver qui pourrait gérer le suivant @Controller définition de la méthode handler

@RequestMapping(method = RequestMethod.POST)
public String createDomain(@Valid Domain domain, BindingResult errors, @RequestParam("countryId") Long countryId) {

je peux enregistrer mon résolveur, ce qui crée un Domain objet à travers les paramètres de la demande, en remplaçant addArgumentResolver()WebMvcConfigurerAdapter. Quand le printemps tente de résoudre le Domain paramètre, il passe en revue sa liste de HandlerMethodArgumentResolver (il y en a beaucoup) et prend la première qui supports().

Dans l'exemple ci-dessus, bien que mon résolveur obtiendrez appelé et mon Domain l'argument sera initialisé, le @Valid annotation de ne pas avoir été traitée et le résolveur pour BindingResult, un ErrorsMethodArgumentResolver échouera parce qu'il nécessite un @ModelAttribute,@RequestBody ou @RequestPart argument dans la méthode handler, que je n'ai pas.

Si j'essaie de le corriger en ajoutant @ModelAttribute

@RequestMapping(method = RequestMethod.POST)
public String createDomain(@Valid @ModelAttribute Domain domain, BindingResult errors, @RequestParam("countryId") Long countryId) {

HandlerMethodArgumentResolver mise en œuvre, ModelAttributeMethodProcessor, sera cochée en premier avec supports() et résolvez l'argument (avec @ModelAttribute et @Valid) avant mon résolveur personnalisé. BindingResult ne pas échouer, mais je n'aurai pas ma création personnalisée comportement sur le Domain instance.

je pourrais simplement copier-coller le code pour la validation et l'ajout au modèle qui est dans ModelAttributeMethodProcessor, mais j'espérais qu'il y aurait un moyen plus simple de résoudre mes paramètres et d'effectuer la validation sans ajouter d'objet au modèle. Est-il une telle façon?

21
demandé sur Sotirios Delimanolis 2013-08-07 02:58:27

2 réponses

Sympa la description du problème que vous rencontrez.

j'ai vérifié le code que vous avez décrit et en suis arrivé à la même conclusion que vous avez - il n'y a pas de façon intégrée d'avoir à la fois une coutume HandlerMethodArgumentResolver ainsi que @Valid validation appliqués au même moment, le seul choix est de faire ce que l' ModelAttributeMethodProcessor fait qui est de vérifier si le paramètre a un @Valid annoter et appeler le code lié à la logique de validation.

vous pouvez probablement dériver votre HandlerMethodResolverArgumentResolverModelAttributeMethodProcessor et appeler super.validateIfApplicable(..) au moins de cette façon, le code existant est mis à profit.

9
répondu Biju Kunjummen 2013-08-07 00:25:01

C'est peut-être trop tard, mais votre HandlerMethodArgumentResolver devient WebDataBinderFactory objet comme dernier argument, alors, pour le raccordement de la validation, il suffit de l'ajouter à votre programme de résolution de mise en œuvre:

Object resolvedObject = // your logic 
if(parameter.hasParameterAnnotation(Valid.class){
            binderFactory.createBinder(webRequest,resolvedObject,"resolvedObjectLogicalName").validate ();
}
5
répondu Alexander.Furer 2015-03-18 13:30:34