Différence entre @Valid et @Validated au printemps

108

Spring prend en charge deux méthodes de validation différentes: la validation Spring et la validation du bean JSR-303. Les deux peuvent être utilisés en définissant un validateur Spring qui délègue à d'autres délégués, y compris le validateur de bean. Jusqu'ici tout va bien.

Mais lorsque vous annotez des méthodes pour demander une validation, c'est une autre histoire. Je peux annoter comme ça

@RequestMapping(value = "/object", method = RequestMethod.POST)
public @ResponseBody TestObject create(@Valid @RequestBody TestObject obj, BindingResult result) {

ou comme ça

@RequestMapping(value = "/object", method = RequestMethod.POST)
public @ResponseBody TestObject create(@Validated @RequestBody TestObject obj, BindingResult result) {

Ici, @Valid est javax.validation.Valid et @Validated est org.springframework.validation.annotation.Validated . Les documents pour ce dernier disent

Variante du Valid de JSR-303, prenant en charge la spécification des groupes de validation. Conçu pour une utilisation pratique avec le support JSR-303 de Spring mais pas spécifique au JSR-303.

ce qui n'aide pas beaucoup car cela ne dit pas exactement en quoi c'est différent. Si pas du tout. Les deux semblent fonctionner assez bien pour moi.

Sergueï Tachenov
la source
2
Peut-être intéressant: stackoverflow.com/questions/18911154/…
Wim Deblauwe
4
"soutenir la spécification des groupes de validation" est une déclaration très explicite.
un meilleur oliver
Je devrais penser que Valid est étroitement associé aux validations JSR 303 (NotNull, etc.). Alors que vous pouvez créer d'autres groupes / validation et les faire valider.
Atul
@zeroflagL, c'est vrai, mais comme je ne l'ai jamais utilisé, j'ai raté le point et je me suis plutôt fixé sur la partie «pas spécifique au JSR-303». Maintenant c'est clair.
Sergei Tachenov

Réponses:

83

Comme vous l'avez cité dans la documentation, a @Validatedété ajouté pour prendre en charge les «groupes de validation», c'est-à-dire le groupe de champs dans le bean validé. Cela peut être utilisé dans des formulaires en plusieurs étapes où vous pouvez valider le nom, l'email, etc. dans la première étape, puis d'autres champs dans la ou les étapes suivantes.

La raison pour laquelle cela n'a pas été ajouté à l' @Validannotation est qu'il est normalisé à l'aide du processus de la communauté java (JSR-303), ce qui prend du temps et les développeurs de Spring voulaient permettre aux gens d'utiliser cette fonctionnalité plus tôt.

Accédez à ce ticket jira pour voir comment l'annotation est née.

František Hartman
la source
115

Une réponse plus simple. Pour ceux qui ne savent toujours pas ce qu'est un "groupe de validation" .

Utilisation pour la @Validvalidation

Manette:

@RequestMapping(value = "createAccount")
public String stepOne(@Valid Account account) {...}

Objet de formulaire:

public class Account {

    @NotBlank
    private String username;

    @Email
    @NotBlank
    private String email;

}

Utilisation pour la@Validated
source du groupe de validation : http://blog.codeleak.pl/2014/08/validation-groups-in-spring-mvc.html

Manette:

@RequestMapping(value = "stepOne")
public String stepOne(@Validated(Account.ValidationStepOne.class) Account account) {...}

@RequestMapping(value = "stepTwo")
public String stepTwo(@Validated(Account.ValidationStepTwo.class) Account account) {...}

Objet de formulaire:

public class Account {

    @NotBlank(groups = {ValidationStepOne.class})
    private String username;

    @Email(groups = {ValidationStepOne.class})
    @NotBlank(groups = {ValidationStepOne.class})
    private String email;

    @NotBlank(groups = {ValidationStepTwo.class})
    @StrongPassword(groups = {ValidationStepTwo.class})
    private String password;

    @NotBlank(groups = {ValidationStepTwo.class})
    private String confirmedPassword;

}
zhuhang.jasper
la source
merci @ Zhuhang.jasper pour avoir expliqué en détail avec une grande simplicité.
Gautam Tyagi le
C'est exactement ce que je cherchais depuis 2 heures, merci @ Zhuhang.jasper
Shady Hussein
merci @zhuhang. ont été à la recherche de cela.
Vishnu Dahatonde le
4

Dans l'exemple d'extraits de code de la question, @Validet @Validatedne faites aucune différence. Mais si le @RequestBodyest annoté avec un Listobjet, ou est une valeur de chaîne annotée par@RequestParam , la validation ne prendra pas effet.

Nous pouvons utiliser le @Validated capacité de validation au niveau de la méthode pour le faire fonctionner. Pour y parvenir, le point clé est de se placer @Validatedsur la classe. Cela peut être une autre différence importante entre @Validet @Validateddans le cadre à ressort.

Réfrence

Lebecca
la source
Pouvez-vous expliquer pourquoi l'annotation n'a aucun effet sur les Listobjets? Je suppose que cela ne fonctionnera pas non plus pour d'autres collections comme Map? Peut-être pourriez-vous me donner une explication plus détaillée dans ma question: stackoverflow.com/questions/60167961/…
Theiaz
1
@Theiaz Comme vous le souhaitez
Lebecca
1

outre ci-dessus, vous ne pouvez postuler que @Validsur un domaine / champ pour une validation imbriquée, pas avec un @validated.

Zelin Zhu
la source