Até então conseguimos apenas mostrar os dados para o usuário que está acessando nossa aplicação, mas não conseguimos receber dados do usuário. Para isso, precisamos criar um formulário.
O formulário segue as mesmas instruções do HTML, porém para que ele funcione corretamente dentro do Spring precisamos fazer algumas alterações.
Primeiro, precisamos criar uma nova rota para o formulário. Vamos criar a uma nova rota chamada /products/create
que irá renderizar o formulário para o usuário. Além de criar a rota, precisamos associar um objeto Product
ao formulário, para que o Spring consiga receber os dados enviados pelo formulário e criar um novo objeto Product
com os dados enviados pelo usuário. Para isso precisamos novamente utilizar a classe Model
para enviar dados para a visão.
1 @GetMapping("/products/create")2 public String create(Model model) {3 model.addAttribute("product", new Product());4 return "create";5 }
Agora, precisamos criar o formulário dentro da visão create.html
que será renderizada quando o usuário acessar a rota /products/create
. O formulário criado será semelhante ao formulário criado no HTML, porém precisamos utilizar o atributo th:field
para associar os campos do formulário com os atributos do objeto Product
que foi enviado para a visão. Outro detalhe importante é que precisamos definir o método do formulário como post
para que o Spring consiga receber os dados enviados pelo formulário.
Até então tinhamos trabalho apenas com o método GET do protocolo HTTP, que é utilizado para receber dados do servidor. Agora, precisamos utilizar o método POST, que é utilizado para enviar dados para o servidor. Existem outros métodos HTTP que iremos discutir mais para frente.
1 <form method="post">2 <label for="name">Nome</label>3 <input type="text" th:field="${product.name}" id="name">4
5 <label for="description">Descrição</label>6 <input type="text" th:field="${product.description}" id="description">7
8 <label for="price">Preço</label>9 <input type="text" th:field="${product.price}" id="price">10
11 <button type="submit">Salvar</button>12 </form>
Agora, se acessarmos a rota /products/new
veremos o formulário sendo exibido. Porém, se tentarmos enviar o formulário, veremos que nada acontece. Isso acontece porque o Spring não sabe o que fazer com os dados enviados pelo formulário.
Antes de consertarmos o formulário para enviar os dados faça uma alteração no método `create. Em vez de passar um objeto vazio, crie um objeto com dados pré-definidos. Por exemplo:
1 @GetMapping("/products/create")2 public String create(Model model) {3 Product product = new Product("Notebook", "Notebook Dell", 3500.00);4 model.addAttribute("product", product);5 return "create";6 }
Agora, se acessarmos a rota /products/create
veremos que o formulário já está preenchido com os dados do objeto Product
que foi criado no método create
. Isso acontece porque o Spring consegue associar os atributos do objeto Product
com os campos do formulário. Depois de ver a alteração volte novamente o método create
para que ele fique como estava antes.
Até esse ponto temos o formulário sendo exibido e conseguimos associar os campos do formulário com os atributos do objeto Product
. Porém se você tentar enviar o formulário, verá que nada acontece. Isso acontece porque o HTML não sabe para qual lugar enviar os dados do formulário. Para isso, precisamos definir o atributo action
, que define para qual rota os dados do serão enviados.
Primeira alteração que devemos fazer é criar um atributo action
para uma nova rota que irá receber os dados do formulário. Para isso o Thymeleaf define o atributo th:action
e faz o uso novamente das expressões de links @{}
.
1 <form method="post" th:action="@{/products/store}">
Agora o HTML conhece a rota para onde deve enviar os dados do formulário porém essa rota ainda não existe no projeto. Vamos criar uma nova rota chamada /products/store
que irá receber os dados do formulário. Para isso, precisamos criar um novo método no nosso controller que irá receber os dados do formulário.
1 @PostMapping("/products/store")2 public String store(Product product) {3 products.add(product);4 return "redirect:/products";5 }
Aqui temos algumas diferenças importantes. Primeiro, o método agora é anotado com @PostMapping
em vez de @GetMapping
. Isso indica que esse método irá receber dados enviados pelo método POST do HTTP. Segundo, o método recebe um objeto Product
como parâmetro. Isso acontece porque o Spring consegue associar os campos do formulário com os atributos do objeto Product
e criar um novo objeto Product
com os dados enviados pelo formulário. Por fim, o método retorna uma string redirect:/products
. Isso indica que o Spring deve redirecionar o usuário para a rota /products
em vez de chamarmos a visão diretamente.
Além disso, estamos adicionando o objeto Product
na lista de produtos. Porém, caso você tenha usado o método Arrays.asList()
para fazer a criação da lista de produtos, você não vai conseguir adicionar novos produtos na lista. Isso acontece porque o método Arrays.asList()
cria uma lista de tamanho fixo e não é possível adicionar novos elementos nessa lista. Para resolver esse problema, altere a criação da lista para uma lista vazia.
1 public List<Product> products = new ArrayList<>();
Agora, se você acessar a rota /products/create
você receberá a página com o formulário em braco. Ao preencher os dados do e enviar o formulário, você será redirecionado para a rota /products/store
que associará os dados do formulário com um novo objeto Product
e adicionará esse produto na lista de produtos. Por fim, você será redirecionado para a rota /products
que por sua vez irá renderizar a visão list
com a lista de produtos atualizada.
Uma estratégia comum no desenvolvimento Web é o padrão conhecido como Post/Redirect/Get (PRG). O padrão PRG é uma estratégia para evitar que os usuários enviem novamente os dados de um formulário quando atualizam a página. O padrão PRG é implementado da seguinte forma: 1. O usuário envia um formulário para o servidor usando o método POST. 2. O servidor processa o formulário e, em seguida, redireciona o usuário para uma nova página usando o método GET.