O que a anotação @Valid indica no Spring?


87

No exemplo a seguir, o ScriptFileparâmetro é marcado com uma @Validanotação.

O que a @Validanotação faz?

@RequestMapping(value = "/scriptfile", method = RequestMethod.POST)    
public String create(@Valid ScriptFile scriptFile, BindingResult result, ModelMap modelMap) {    
    if (scriptFile == null) throw new IllegalArgumentException("A scriptFile is required");        
    if (result.hasErrors()) {        
        modelMap.addAttribute("scriptFile", scriptFile);            
        modelMap.addAttribute("showcases", ShowCase.findAllShowCases());            
        return "scriptfile/create";            
    }        
    scriptFile.persist();        
    return "redirect:/scriptfile/" + scriptFile.getId();        
}    

Respostas:


63

É para fins de validação.

Validação É comum validar um modelo após vincular a entrada do usuário a ele. Spring 3 fornece suporte para validação declarativa com JSR-303. Este suporte é habilitado automaticamente se um provedor JSR-303, como o Hibernate Validator, estiver presente em seu classpath. Quando ativado, você pode acionar a validação simplesmente anotando um parâmetro do método do controlador com a anotação @Valid: Após vincular os parâmetros POST de entrada, o AppointmentForm será validado; neste caso, para verificar se o valor do campo de data não é nulo e ocorre no futuro.


Procure aqui mais informações:
http://blog.springsource.com/2009/11/17/spring-3-type-conversion-and-validation/


36

Somando as respostas acima, dê uma olhada no seguinte. AppointmentFormA datecoluna de é anotada com algumas anotações. Por ter uma @Validanotação que aciona validações no AppointmentForm(neste caso @NotNulle @Future). Essas anotações podem vir de diferentes provedores JSR-303 (por exemplo, Hibernate, Spring..etc).

    @RequestMapping(value = "/appointments", method = RequestMethod.POST)
    public String add(@Valid AppointmentForm form, BindingResult result) {
        ....
    }

    static class AppointmentForm {

        @NotNull @Future
        private Date date;
    }

1
Eu tenho um código semelhante. Eu tinha removido @Validem ApplicationFormparâmetro, mas, ainda validações foram disparados na date(Definir como null) campo. Por favor explique.
lupchiazoem

17

IIRC @Valid não é uma anotação Spring, mas uma anotação JSR-303 (que é o padrão Bean Validation). O que ele faz é basicamente verificar se os dados que você envia ao método são válidos ou não (isso validará o scriptFile para você).


2
O que significa "validará o scriptFile para você"? Verifique se não é nulo, tem alguma sintaxe ou algum conteúdo? Em outras palavras, o que ele valida e como? O usuário deve implementar algo? Onde posso obter informações sobre isso? Obrigado!
sobrinho

Por favor, responda à pergunta de @nephewtom, não é uma resposta suficiente para validar com o ponto principal ausente que é "contra o quê"?
monami

17

@Validem si não tem nada a ver com a primavera. Faz parte da especificação do Bean Validation (há vários deles, o último sendo JSR 380 no segundo semestre de 2017), mas @Validé muito antigo e deriva totalmente do JSR 303.

Como todos sabemos, Spring é muito bom em fornecer integração com todos os diferentes JSRs e bibliotecas java em geral (pense em JPA, JTA, Caching, etc.) e, claro, esses caras cuidaram da validação também. Um dos principais componentes que facilita isso é MethodValidationPostProcessor .

Tentar responder à sua pergunta - @Validé muito útil para a chamada validação em cascata, quando você deseja validar um gráfico complexo e não apenas os elementos de nível superior de um objeto. Cada vez que você quer ir mais fundo, você tem que usar @Valid. Isso é o que a JSR determina. O Spring obedecerá a isso com alguns pequenos desvios (por exemplo, tentei colocar em @Validatedvez de @Validno método RestController e a validação funciona, mas o mesmo não se aplicará a um bean de "serviço" regular).


Mas, o que valida?
sobrinho

Explique, @nephewtom. O que você quer esclarecer?
yuranos de

Eu li JSR 303: Bean Validation, beanvalidation.org/1.0/spec , mas ainda não entendi em que validação será realizada ScriptFile scriptFile.
sobrinho

ScriptFile dentro dele provavelmente tem vários campos e esses campos também têm anotações. É aqui que a validação começa. Com base na pergunta original, não está claro o que exatamente está dentro da classe ScriptFile.
yuranos

Ok, obrigado. Você poderia colocar um exemplo do que poderia validar se seus campos fossem String, Integer e Bean?
sobrinho

2
public String create(@Valid @NotNull ScriptFile scriptFile, BindingResult result, ModelMap modelMap) {    
    if (scriptFile == null) throw new IllegalArgumentException("A scriptFile is required");        

Eu acho que esta @NotNullanotação é válida, portanto, se a condição não for necessária.


1

Apenas adicionando à resposta acima, em um aplicativo da web @validé usado onde o bean a ser validado também é anotado com anotações de validação @NotNull, por exemplo , @Email(anotação de hibernação) para que ao obter a entrada do usuário os valores possam ser validados e o resultado da ligação terá a validação resultados. bindingResult.hasErrors()dirá se alguma validação falhou.


1

Outro aspecto útil do @Valid não mencionado acima é que (ou seja: usando o Postman para testar um endpoint) @Valid formatará a saída de uma chamada REST incorreta em JSON formatado ao invés de um blob de texto dificilmente legível. Isso é muito útil se você estiver criando uma API consumível comercialmente para seus usuários.


0

Acho que sei para onde vai sua pergunta. E como essa pergunta é a que aparece nos principais resultados de pesquisa do Google, posso dar uma resposta simples sobre o que a anotação @Valid faz.

Vou apresentar 3 cenários de como usei @Valid

Modelo:

public class Employee{
private String name;
@NotNull(message="cannot be null")
@Size(min=1, message="cannot be blank")
private String lastName;
 //Getters and Setters for both fields.
 //...
}

JSP:

...
<form:form action="processForm" modelAttribute="employee">
 <form:input type="text" path="name"/>
 <br>
 <form:input type="text" path="lastName"/>
<form:errors path="lastName"/>
<input type="submit" value="Submit"/>
</form:form>
...

Controlador para o cenário 1:

     @RequestMapping("processForm")
        public String processFormData(@Valid @ModelAttribute("employee") Employee employee){
        return "employee-confirmation-page";
    }

Neste cenário, depois de enviar seu formulário com um campo lastName vazio, você obterá uma página de erro, pois está aplicando regras de validação, mas não está lidando com isso de forma alguma.

Exemplo do referido erro: página de exceção

Controlador para o cenário 2:

 @RequestMapping("processForm")
    public String processFormData(@Valid @ModelAttribute("employee") Employee employee,
BindingResult bindingResult){
                return bindingResult.hasErrors() ? "employee-form" : "employee-confirmation-page";
            }

Nesse cenário, você está passando todos os resultados dessa validação para o bindingResult, então cabe a você decidir o que fazer com os resultados da validação desse formulário.

Controlador para o cenário 3:

@RequestMapping("processForm")
    public String processFormData(@Valid @ModelAttribute("employee") Employee employee){
                return "employee-confirmation-page";
            }
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public Map<String, String> invalidFormProcessor(MethodArgumentNotValidException ex){
  //Your mapping of the errors...etc
}

Nesse cenário, você ainda não está lidando com os erros como no primeiro cenário, mas passa isso para outro método que cuidará da exceção de que @Valid dispara ao processar o modelo de formulário. Verifique isso para ver o que fazer com o mapeamento e tudo mais.

Resumindo : @Valid por si só não faz mais nada que acione a validação dos campos anotados JSR 303 de validação ( @NotNull, @Email, @Size, etc ... ), você ainda precisa especificar uma estratégia do que fazer com os resultados dessa validação.

Espero ter conseguido esclarecer algo para as pessoas que podem tropeçar com isso.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.