Diferencia entre @Valid y @Validated en Spring

106

Spring admite dos métodos de validación diferentes: la validación de Spring y la validación del bean JSR-303. Ambos se pueden usar definiendo un validador Spring que delegue a otros delegadores, incluido el validador de frijoles. Hasta aquí todo bien.

Pero cuando se anotan métodos para solicitar la validación, es otra historia. Puedo anotar así

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

o así

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

Aquí, @Valid es javax.validation.Valid y @Validated es org.springframework.validation.annotation.Validated . Los documentos de este último dicen

Variante de JSR-303's Valid, que soporta la especificación de grupos de validación. Diseñado para un uso conveniente con el soporte JSR-303 de Spring, pero no específico para JSR-303.

lo cual no ayuda mucho porque no dice exactamente en qué se diferencia. Como mucho. Ambos parecen funcionar bastante bien para mí.

Sergei Tachenov
fuente
2
Podría ser interesante: stackoverflow.com/questions/18911154/…
Wim Deblauwe
4
"apoyar la especificación de grupos de validación" es una declaración muy explícita.
un mejor oliver
Debería pensar que Valid está estrechamente relacionado con las validaciones JSR 303 (NotNull, etc.). Mientras que puede crear otras validaciones / grupos y hacer que se verifiquen en Validado.
Atul
@zeroflagL, cierto, pero como nunca lo he usado, me perdí el punto y me obsesioné con la parte "no específica de JSR-303". Ahora está claro.
Sergei Tachenov

Respuestas:

83

Como citó de la documentación, @Validatedse agregó para admitir "grupos de validación", es decir, grupo de campos en el bean validado. Esto se puede utilizar en formularios de varios pasos en los que puede validar el nombre, el correo electrónico, etc. en el primer paso y luego en otros campos en los pasos siguientes.

La razón por la que esto no se agregó a la @Validanotación es porque está estandarizado usando el proceso de la comunidad java (JSR-303), lo que lleva tiempo y los desarrolladores de Spring querían permitir que las personas usaran esta funcionalidad antes.

Vaya a este boleto de jira para ver cómo surgió la anotación.

František Hartman
fuente
112

Una respuesta más directa. Para aquellos que todavía no saben qué diablos es "grupo de validación" .

Uso para @Validvalidación

Controlador:

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

Objeto de formulario:

public class Account {

    @NotBlank
    private String username;

    @Email
    @NotBlank
    private String email;

}

Uso para el @Validatedgrupo de validación
Fuente: http://blog.codeleak.pl/2014/08/validation-groups-in-spring-mvc.html

Controlador:

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

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

Objeto de formulario:

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
fuente
gracias @ Zhuhang.jasper por explicar en detalle con gran sencillez.
Gautam Tyagi
Esto es exactamente lo que he estado buscando durante las últimas 2 horas, gracias @ Zhuhang.jasper
Shady Hussein
gracias @zhuhang. he estado buscando esto.
Vishnu Dahatonde
4

En los fragmentos de código de ejemplo de la pregunta, @Validy @Validatedno hay diferencia. Pero si @RequestBodyestá anotado con un Listobjeto, o es un valor de cadena anotado por @RequestParam, la validación no tendrá efecto.

Podemos usar la @Validatedcapacidad de validación a nivel de método de para que funcione. Para lograrlo, el punto clave es colocarlo @Validateden la clase. Esta puede ser otra diferencia importante entre @Validy @Validateden el marco de primavera.

Referencia

Lebecca
fuente
¿Podría explicar por qué la anotación no tiene ningún efecto sobre los Listobjetos? Supongo que esto tampoco funcionará para otras colecciones como Map? Tal vez podría darme una explicación más detallada en mi pregunta: stackoverflow.com/questions/60167961/…
Theiaz
1
@Theiaz Como quieras
Lebecca
1

además de lo anterior, solo puede solicitar @Validen un dominio / campo para la validación anidada, no con un @validated.

Zelin Zhu
fuente