Validar os dados de entrada é uma tarefa muito importante para qualquer aplicação. É uma das principais formas de garantir a integridade dos dados e a segurança da aplicação.
A validação consiste na verificação das informações inseridas pelo usuário, para garantir que elas estão de acordo com o esperado. Por exemplo, se o usuário está inserindo um e-mail, é necessário verificar se o texto inserido possui o formato de um e-mail válido. Outro exemplo, é a validação de campo não vazio, ou seja, obrigar o usuário a inserir alguma informação naquele campo.
Faça um teste e acesse o formulário de adicionar um novo produto, deixe todos os campos vazios e clique em salvar. Perceba que a aplicação não faz nenhuma validação e salva o produto com todos os campos vazios. Isso não é uma abordagem correta, pois pode gerar diversos tipos de problemas na aplicação. Por isso a validação é uma etapa fundamental de qualquer sistema.
O Spring Boot possui uma biblioteca chamada spring-boot-starter-validation
que facilita bastante o trabalho de validação. Para utilizá-la, basta adicioná-la como dependência no arquivo pom.xml
:
1<dependency>2 <groupId>org.springframework.boot</groupId>3 <artifactId>spring-boot-starter-validation</artifactId>4</dependency>
Agora, vamos adicionar as anotações de validação nos campos do formulário. Para isso, vamos utilizar a anotação @NotBlank
que valida se o campo não está vazio. Essa anotação é do pacote jakarta.validation.constraints
, por isso é necessário importá-lo. A anotação possui uma mensagem que será exibida caso o campo esteja vazio definida através do atributo message
da anotação.
1import jakarta.validation.constraints.NotBlank;2
3public class Product {4 private String id;5 @NotBlank(message = "Nome é obrigatório")6 private String name;7 @NotBlank(message = "Descrição é obrigatória")8 private String description;9 private double price;10
11 ...12}
Apenas essa modificação não é suficiente para que a validação funcione. É necessário alterar o método store
do controller para que ele valide o objeto Product
, usando novamente uma anotação, desta vez a anotação @Valid
. A anotação vai verificar se os campos são validos.
Além da anotação @Valid
é necessário adicionar um parâmetro do tipo BindingResult
no método. Essa classe é responsável por armazenar o resultado da validação. Após as alterações o método deverá ficar da seguinte maneira:
1@PostMapping("/products/store")2public String store(@Valid Product product, BindingResult result) {3 if (result.hasErrors()) { return "create"; }4 products.add(product);5 return "redirect:/products";6}
O último detalhe é com relação ao objeto da classe BindingResult
que possui o método hasErrors()
que verifica se a validação foi executada com sucesso retornando true
caso tenha algum tipo de erro e false
caso contrário. Com isso é possível restringir a adição do novo produto caso a validação não tenha sido executada com sucesso e retornar para a página de criação do produto exibindo as mensagens de erro.
O Thymeleaf possui uma forma de exibir as mensagens de erro de validação. Basta usar o atributo th:errors
acompanhado do campo que está sendo validado. Por exemplo, para exibir as mensagens de erro do campo name
basta usar o atributo th:errors="${product.name}"
. O mesmo deve ser feito para os outros campos.
1<form method="post" th:action="@{/products/store}">2 <label for="name">Nome</label>3 <input type="text" th:field="${product.name}" id="name">4 <p th:errors="${product.name}"></p>5
6 <label for="description">Descrição</label>7 <input type="text" th:field="${product.description}" id="description">8 <p th:errors="${product.description}"></p>9
10 <label for="price">Preço</label>11 <input type="text" th:field="${product.price}" id="price">12 <p th:errors="${product.price}"></p>13
14 <button type="submit">Salvar</button>15</form>
Suba a aplicação e acesse a página de criação de um novo produto. Deixe todos os campos vazios e clique em salvar. Perceba que a aplicação não salva o produto e exibe as mensagens de erro. Caso a validação não funcione, tente parar o servidor e fazer um reinicio limpo (usando o comando mvn clean spring-boot:run
).
Além da anotação para valição de campo não vazio, o spring possui outras anotações para validação de outros tipos de dados. A seguir é mostrada uma tabela com algumas dessas anotações:
Anotação | Descrição |
---|---|
@NotBlank | Verifica se o campo não está vazio |
@NotNull | Verifica se o campo não é nulo |
@Size(min, max) | VEspecifica o tamanho ou intervalo de um campo (para coleções, strings, arrays, etc.) |
@Min | Verifica se o valor do campo é maior ou igual ao valor definido |
@Max | Verifica se o valor do campo é menor ou igual ao valor definido |
Verifica se o valor do campo possui o formato de um e-mail válido | |
@Pattern | Verifica se o valor do campo possui o formato definido através de uma expressão regular |
O campo de preço é um campo numérico com casas decimais. Logo é preciso verificar se esse campo possui no máximo 2 digitos decimais. Também é possível verificar um valor mínimo para o campo, visto que não faz sentido permitir a entrada de um valor menor do que zero.
Para isso vamos utilizar as anotações @DecimalMin
e @Digits
. A primeira anotação verifica se o valor do campo é maior ou igual ao valor definido. A segunda anotação verifica se o valor do campo possui o número de dígitos definido. A anotação @Digits
possui dois atributos, o atributo integer
que define o número de dígitos inteiros e o atributo fraction
que define o número de dígitos decimais.
1public class Product {2
3 @DecimalMin(value = "0.01", inclusive = true, message = "O preço deve ser maior que 0.00")4 @Digits(integer = 5, fraction = 2, message = "O preço deve ter no máximo 5 dígitos inteiros e 2 dígitos decimais")5 private double price;6 ...
Nesse exemplo estamos delimitando um valor máximo de preço que pode ser adicionado mas isso vai depender das regras de negócio da sua própria aplicação.