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.
- Definição da Interface: ```
public interface GrupoValidacaoA {}
- Aplicação no POJO: ```
@NotBlank(message = "Campo obrigatório", groups = {GrupoValidacaoA.class})
private String codigoRastreio;
- 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.