Diferença entre @Valid e @Validated na primavera

106

Spring suporta dois métodos de validação diferentes: validação Spring e validação de bean JSR-303. Ambos podem ser usados ​​definindo um validador Spring que delega a outros delegadores, incluindo o validador de bean. Por enquanto, tudo bem.

Mas ao anotar métodos para realmente solicitar validação, é outra história. Eu posso anotar assim

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

ou assim

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

Aqui, @Valid é javax.validation.Valid e @Validated é org.springframework.validation.annotation.Validated . Os documentos deste último dizem

Variante do Valid JSR-303, suportando a especificação de grupos de validação. Projetado para uso conveniente com o suporte JSR-303 do Spring, mas não específico para JSR-303.

o que não ajuda muito porque não diz exatamente como é diferente. Se for assim. Ambos parecem estar funcionando muito bem para mim.

Sergei Tachenov
fonte
2
Pode ser interessante: stackoverflow.com/questions/18911154/…
Wim Deblauwe
4
"apoiar a especificação de grupos de validação" é uma declaração muito explícita.
um melhor oliver
Devo pensar que Valid é fortemente acoplado com validações JSR 303 (NotNull, etc). Considerando que você pode criar outras validações / grupos e tê-los verificados em Validado.
Atul
@zeroflagL, é verdade, mas como nunca o usei, perdi o ponto e me fixei na parte “não específica do JSR-303”. Agora está claro.
Sergei Tachenov

Respostas:

83

Como você citou na documentação, @Validatedfoi adicionado para oferecer suporte a "grupos de validação", ou seja, grupo de campos no bean validado. Isso pode ser usado em formulários de várias etapas, onde você pode validar nome, e-mail, etc. na primeira etapa e, em seguida, outros campos nas etapas seguintes.

O motivo pelo qual isso não foi adicionado à @Validanotação é porque ele é padronizado usando o processo da comunidade java (JSR-303), que leva tempo e os desenvolvedores do Spring queriam permitir que as pessoas usassem essa funcionalidade mais cedo.

Acesse este tíquete jira para ver como a anotação surgiu.

František Hartman
fonte
112

Uma resposta mais direta. Para quem ainda não sabe o que é "grupo de validação" .

Uso para @Validvalidação

Controlador:

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

Objeto de formulário:

public class Account {

    @NotBlank
    private String username;

    @Email
    @NotBlank
    private String email;

}

@Validated
Fonte de uso para grupo de validação : 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 formulário:

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
fonte
obrigado @ Zhuhang.jasper por explicar em detalhes com grande simplicidade.
Gautam Tyagi
Isso é exatamente o que eu tenho pesquisado nas últimas 2 horas, obrigado @ Zhuhang.jasper
Shady Hussein
obrigado @zhuhang. tem procurado por isso.
Vishnu Dahatonde
4

Nos trechos de código de exemplo da pergunta, @Valide @Validatednão faz diferença. Mas se o @RequestBodyfor anotado com um Listobjeto, ou for um valor de string anotado por @RequestParam, a validação não terá efeito.

Podemos usar a @Validatedcapacidade de validação em nível de método de para fazê-lo funcionar. Para isso, o ponto-chave é colocar @Validatedna classe. Esta pode ser outra diferença importante entre @Valide @Validatedna estrutura da mola.

Refrence

Lebecca
fonte
Você poderia explicar por que a anotação não tem efeito para Listobjetos? Presumo que isso também não funcionará para outras coleções como Map? Talvez você pudesse me dar uma explicação mais detalhada na minha pergunta: stackoverflow.com/questions/60167961/…
Theiaz
1
@Theiaz Como desejar
Lebecca
1

além do acima, você só pode aplicar @Validem um domínio / campo para validação aninhada, não com um @validated.

Zelin Zhu
fonte