Implementação de Validação de Dados com Spring MVC e Hibernate Validator

A validação de dados é um pilar fundamental na segurança de aplicações web. Realizar essa verificação no lado do servidor garante a integridade dos dados independentemente da origem da requisição (seja um navegador, um aplicativo móvel ou uma chamada via API).

Níveis de Validação

  • Camada de Controle (Controller): Verifica a legalidade dos parâmetros enviados na requisição HTTP.
  • Camada de Serviço (Service): Foca na validação de regras de negócio e parâmetros essenciais para o processamento lógico.
  • Camada de Persistência (DAO): Geralmente não executa validações complexas, confiando nas camadas superiores.

Configuração do Ambeinte

O Spring MVC integra-se ao framework Hibernate Validator (implementação de referência da especificação Bean Validation). Para começar, é necessário incluir as dependências do JSR-303/JSR-349 no projeto, como o hibernate-validator e a validation-api.

Configurando o Validator no Spring

No arquivo de configuração do Spring (contexto da aplicação), devemos definir o LocalValidatorFactoryBean e o recurso de mensagens personalizadas:

<!-- Habilita a validação no mvc:annotation-driven -->
<mvc:annotation-driven validator="validador" />

<!-- Definição do Bean do Validador -->
<bean id="validador" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
    <property name="providerClass" value="org.hibernate.validator.HibernateValidator" />
    <property name="validationMessageSource" ref="messageSource" />
</bean>

<!-- Configuração do arquivo de mensagens -->
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
    <property name="basenames">
        <list>
            <value>classpath:mensagensValidacao</value>
        </list>
    </property>
    <property name="fileEncodings" value="utf-8" />
    <property name="cacheSeconds" value="120" />
</bean>

Definindo Regras no POJO

Utilizamos anotações diretamente nos atributos da classe de modelo para definir as restrições:

public class ProdutoDTO {
    private Integer id;

    @Size(min = 2, max = 50, message = "{produto.nome.tamanho}")
    private String nome;

    @NotNull(message = "{produto.data.nulo}")
    private Date dataCadastro;

    // Getters e Setters
}

No arquivo mensagensValidacao.properties, definimos os textos correspondentes:

produto.nome.tamanho=O nome do produto deve ter entre 2 e 50 caracteres.
produto.data.nulo=A data de cadastro é obrigatória.

Processando Erros no Controller

No método do Controller, utilizamos a anotação @Validated para disparar a verificação e o objeto BindingResult para capturar os possíveis erros. Importante: O BindingResult deve aparecer imediatamente após o objeto validado.

@RequestMapping("/salvarProduto")
public String salvarProduto(Model model, 
                            @Validated ProdutoDTO produto, 
                            BindingResult resultado) {
    
    if (resultado.hasErrors()) {
        List<ObjectError> erros = resultado.getAllErrors();
        for (ObjectError erro : erros) {
            System.out.println(erro.getDefaultMessage());
        }
        
        model.addAttribute("listaErros", erros);
        return "produto/formulario";
    }

    servicoProduto.salvar(produto);
    return "sucesso";
}

Exibição de Erros na View (JSP)

Para exibir as mensagens de erro ao usuário final, podemos iterar sobre a lista enviada pelo Controller:

<c:if test="${listaErros != null}">
    <div style="color: red;">
        <c:forEach items="${listaErros}" var="erro">
            ${erro.defaultMessage}<br/>
        </c:forEach>
    </div>
</c:if>

Validação por Grupos

Em cenários onde o mesmo POJO é usado em fluxos diferentes (ex: criação vs. edição) com regras distintas, utilizamos Groups. Grupos são interfaces Java simples utilizadas apenas para marcação.

  1. Definição da Interface: ``` public interface GrupoValidacaoA {}
  2. Aplicação no POJO: ``` @NotBlank(message = "Campo obrigatório", groups = {GrupoValidacaoA.class}) private String codigoRastreio;
  3. Uso no Controller: ``` public String processar(@Validated(value = GrupoValidacaoA.class) ProdutoDTO produto, BindingResult result) { // Lógica aqui }
    
    

Dessa forma, o Spring validará apenas os campos que pertencem ao grupo especificado na assinatura do método.

Tags: Spring MVC hibernate validator bean validation java JSR-303

Publicado em 6-26 04:47