Mensagens de feedback com RedirectAttributes
O processo de dar feedback ao usuário após uma ação é uma tarefa muito comum em aplicações web. Por exemplo, ao cadastrar um novo produto em um e-commerce ou salvar os dados de um formulário, é comum que a aplicação exiba uma mensagem como “Produto salvo com sucesso!” na página seguinte.
Apesar de ser uma funcionalidade muito comum, isso não significa dizer que seja fácil implementar corretamente. A primeira parte importante é entender o desafio técnico que o padrão Post-Redirect-Get (PRG) nos impõe. Quando um usuário envia um formulário (POST), a boa prática é redirecioná-lo (Redirect) para uma nova página (GET), como a listagem de produtos.
O problema é: como passar a mensagem de “sucesso” da requisição POST para a nova requisição GET?
Entendendo o Problema: O “Apagão” do Redirect
Primeiramente, é importante entender o processo que ocorre no Spring MVC. Quando seu método do controlador (o POST que salva o produto) retorna a string return "redirect:/products", ele está, na verdade, enviando uma resposta HTTP 302 ao navegador.
O navegador, ao receber essa resposta, faz uma requisição GET completamente nova para a URL /products. Como essa é uma requisição nova, qualquer dado que você tenha colocado no Model da requisição POST original é totalmente perdido. Ele se foi, “apagou”.
Então, como podemos enviar uma mensagem do método store (POST) para o método index (GET) que renderiza a lista de produtos?
A Solução: RedirectAttributes
Para resolver exatamente esse problema, o Spring nos oferece a interface RedirectAttributes. Pense nela como um “porta-recados” especial, projetado para sobreviver a um redirecionamento.
Ele permite que você adicione atributos que não serão perdidos. A forma mais comum de usá-lo para mensagens é com o método addFlashAttribute().
1. Enviando a Mensagem de Sucesso (no Controller)
Como o intuito é entender o processo, vamos alterar nosso ProductController para que ele envie uma mensagem de sucesso após salvar um produto.
O próximo passo é alterar o controlador para que ele receba a interface RedirectAttributes como parâmetro. O Spring irá injetá-la automaticamente para nós.
@PostMapping("/products/store")
public String store(@RequestParam String title, @RequestParam String description, @RequestParam long price, RedirectAttributes redirectAttributes) {
Product product = new Product();
product.setTitle(title);
product.setDescription(description);
product.setPrice(price);
productRepository.save(product);
// Este é o passo mais importante!
// Adicionamos um "Flash Attribute" para o redirect
redirectAttributes.addFlashAttribute("mensagemSucesso", "Produto salvo com sucesso!");
return "redirect:/products";
}
Analisando o método store, podemos perceber que o passo crucial é redirectAttributes.addFlashAttribute(...). Mas por que “Flash”?
O nome “Flash” (como um flash de câmera) é usado porque esse atributo tem vida curta:
- O Spring armazena
mensagemSucessotemporariamente na Sessão HTTP do usuário. - Logo após o redirect, o Spring lê esse atributo da sessão e o adiciona ao
Modelda requisiçãoGET. - Imediatamente após a leitura, o Spring remove o atributo da sessão.
Isso é perfeito! Garante que a mensagem seja exibida apenas uma vez. Se o usuário atualizar a página (F5), a mensagem não estará mais lá.
2. Exibindo a Mensagem de Sucesso (no HTML)
Agora que o controlador está enviando a mensagem, precisamos exibi-la na página de destino (ex: products/index.html).
Como o Spring magicamente moveu o “Flash Attribute” da Sessão para o Model da página de listagem, a variável mensagemSucesso estará disponível para nós no Thymeleaf.
O segundo e último passo é alterar o arquivo products/index.html (ou onde quer que você esteja redirecionando) para que ele seja capaz de exibir a mensagem.
<div th:if="${mensagemSucesso}" class="alert alert-success">
<span th-text="${mensagemSucesso}"></span>
</div>
Veja que usamos a expressão th:if="${mensagemSucesso}". Isso é fundamental.
- Se viemos de um redirecionamento que enviou a mensagem, a variável
mensagemSucessoexiste, e odivde alerta é renderizado. - Se o usuário apenas acessou a página
/productsdiretamente (digitando no navegador), a variável não existe, e odivfica oculto.
Faça essas alterações e teste o cadastro de um novo produto. Você deve perceber que, após salvar, você é redirecionado para a listagem e a mensagem de sucesso aparece no topo. Se você atualizar a página, ela desaparece.
Como mencionado anteriormente, usar o padrão Post-Redirect-Get é uma boa prática, e o RedirectAttributes é a ferramenta padrão do Spring para fazer a “ponte” entre essas duas requisições, permitindo um feedback claro e profissional para o usuário.