Enviando dados para o Servidor

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.

Exibindo o 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.

Submetendo o formulário

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 Producte 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.