Spring Web MVC – valide les parameters de demande individuels

J’utilise une application Web dans Spring Web MVC 3.0 et j’ai plusieurs méthodes de contrôleur dont les signatures sont approximativement les suivantes:

@RequestMapping(value = "/{level1}/{level2}/foo", method = RequestMethod.POST) public ModelAndView createFoo(@PathVariable long level1, @PathVariable long level2, @RequestParam("foo_name") Ssortingng fooname, @RequestParam(value = "description", required = false) Ssortingng description); 

Je voudrais append une validation – par exemple, la description devrait être limitée à une certaine longueur ou la fooname devrait contenir uniquement certains caractères. Si cette validation échoue, je veux renvoyer un message à l’utilisateur plutôt que de simplement lancer une exception non vérifiée (ce qui se produirait de toute façon si je laisse les données s’infiltrer dans la couche DAO). Je suis au courant de JSR303 mais je n’ai pas travaillé avec elle et je ne comprends pas très bien comment l’appliquer dans un contexte de spring.

D’après ce que j’ai compris, une autre option consisterait à lier le @RequestBody à un object de domaine entier et à y append des contraintes de validation, mais actuellement mon code est configuré pour accepter des parameters individuels comme indiqué ci-dessus.

Quelle est la manière la plus simple d’appliquer la validation aux parameters d’entrée en utilisant cette approche?

Il n’y a rien pour faire ça, pas encore . Avec les versions actuelles, vous devrez toujours utiliser WebDataBinder pour lier vos parameters à un object si vous souhaitez une validation automatique. Cela vaut la peine d’apprendre à faire si vous utilisez SpringMVC, même si ce n’est pas votre premier choix pour cette tâche.

Cela ressemble à ceci:

 public ModelAndView createFoo(@PathVariable long level1, @PathVariable long level2, @Valid @ModelAtsortingbute() FooWrapper fooWrapper, BindingResult errors) { if (errors.hasErrors() { //handle errors, can just return if using Spring form:error tags. } } public static class FooWrapper { @NotNull @Size(max=32) private Ssortingng fooName; private Ssortingng description; //getset } 

Si vous avez Hibernate Validator 4 ou version ultérieure sur votre classpath et utilisez la configuration par défaut du dissortingbuteur, il doit “Just work”.

Montage puisque les commentaires devenaient un peu gros:

Tout object qui se trouve dans la signature de votre méthode et qui ne ModelMap pas parmi ceux attendus par Spring sait comment injecter, comme HttpRequest , ModelMap , etc., les données seront liées. Ceci est accompli pour des cas simples, simplement en faisant correspondre les noms de parameters de la requête avec les noms de propriété du bean et les appelants. @ModelAtsortingbute il y a juste une chose de style personnel, dans ce cas, il ne fait rien. L’intégration de JSR-303 avec le paramètre @Valid sur une méthode se connecte via WebDataBinder . Si vous utilisez @RequestBody , vous utilisez un object marshaller basé sur le type de contenu que spring détermine pour le corps de la requête (généralement juste à partir de l’en-tête http). Le servlet du répartiteur ( AnnotationMethodHandlerAdapter ) commutateur de validation ‘pour un marshaller arbitraire. Il transmet simplement le contenu de la requête Web au convertisseur de messages et récupère un object. Aucun object BindingResult n’est généré, il n’y a donc aucun endroit pour définir les erreurs.

Vous pouvez toujours simplement injecter votre validateur dans le contrôleur et l’exécuter sur l’object que vous obtenez, il n’a tout simplement pas l’intégration magique avec le @Valid sur le paramètre de requête qui BindingResult le BindingResult pour vous.

Cela semble être possible maintenant (essayé avec Spring 4.1.2), voir https://raymondhlee.wordpress.com/2015/08/29/validating-spring-mvc-request-mapping-method-parameters/

Extrait de la page ci-dessus:

  1. Ajoutez MethodValidationPostProcessor à Spring @Configuration:

     @Bean public MethodValidationPostProcessor methodValidationPostProcessor() { return new MethodValidationPostProcessor(); } 
  2. Ajouter @Validated à la classe du contrôleur

  3. Utilisez @Size juste avant @RequestParam

     @RequestMapping("/hi") public Ssortingng sayHi(@Size(max = 10, message = "name should at most 10 characters long") @RequestParam("name") Ssortingng name) { return "Hi " + name; 

    }

  4. Gérer ConstraintViolationException dans une méthode @ExceptionHandler

Si vous avez plusieurs parameters de requête à valider (avec Http GET ou POST ). Vous pourriez aussi bien créer une classe de modèle personnalisée et utiliser @ Valid avec @ ModelAtsortingbute pour valider les parameters. De cette façon, vous pouvez utiliser Hibernate Validator ou javax.validator api pour valider les parameters. Ca fait plutot comme ca:

Méthode de demande:

 @RequestMapping(value="/doSomething", method=RequestMethod.GET) public Model dosomething(@Valid @ModelAtsortingbute ModelRequest modelRequest, BindingResult result, Model model) { if (result.hasErrors()) { throw new SomeException("invalid request params"); } //to access the request params modelRequest.getFirstParam(); modelRequest.getSecondParam(); ... } 

Classe ModelRequest :

 class ModelRequest { @NotNull private Ssortingng firstParam; @Size(min = 1, max = 10, message = "You messed up!") private Ssortingng secondParam; //Setters and getters public void setFirstParam (Ssortingng firstParam) { this.firstParam = firstParam; } public Ssortingng getFirstParam() { return firstParam; } ... } 

J’espère que cela pourra aider.