Guide des attributs Flash dans une application Web Spring

1. Vue d'ensemble

Les applications Web dépendent souvent des entrées de l'utilisateur pour répondre à plusieurs de leurs cas d'utilisation. En conséquence, la soumission de formulaires est un mécanisme très utilisé pour collecter et traiter les données de ces applications.

Dans ce didacticiel, nous allons apprendre comment les attributs flash de Spring peuvent nous aider avec le flux de travail de soumission de formulaires de manière sécurisée et fiable.

2. Principes de base des attributs Flash

Avant de pouvoir utiliser confortablement les attributs Flash, nous devons acquérir un niveau de compréhension décent du flux de travail de soumission de formulaire et de quelques concepts clés connexes.

2.1. Publier / Rediriger / Obtenir un modèle

Une manière naïve de concevoir un formulaire Web serait d'utiliser une seule requête HTTP POST qui s'occupe de la soumission et donne une confirmation via sa réponse. Cependant, une telle conception expose le risque de traitement en double des requêtes POST, au cas où l'utilisateur finirait par actualiser la page.

Pour atténuer le problème du traitement en double, nous pouvons créer le flux de travail sous la forme d'une séquence de demandes interconnectées dans un ordre spécifique, à savoir POST, REDIRECT et GET . En bref, nous appelons cela le modèle Post / Redirection / Get (PRG) pour la soumission de formulaire.

A la réception de la requête POST, le serveur la traite puis transfère le contrôle pour effectuer une requête GET. Par la suite, la page de confirmation s'affiche en fonction de la réponse à la demande GET. Idéalement, même si la dernière demande GET est tentée plus d'une fois, il ne devrait pas y avoir d'effets secondaires indésirables.

2.2. Cycle de vie des attributs Flash

Pour compléter la soumission du formulaire à l'aide du modèle PRG, nous devrons transférer les informations de la demande POST initiale à la demande GET finale après la redirection.

Malheureusement, nous ne pouvons utiliser ni RequestAttributes ni SessionAttributes. En effet, le premier ne survivra pas à une redirection entre différents contrôleurs, tandis que le second durera toute la session, même après la soumission du formulaire.

Mais nous n'avons pas à nous inquiéter car le cadre Web de Spring fournit des attributs flash qui peuvent résoudre ce problème exact.

Voyons les méthodes de l' interface RedirectAttributes qui peuvent nous aider à utiliser les attributs flash dans notre projet:

RedirectAttributes addFlashAttribute(String attributeName, @Nullable Object attributeValue); RedirectAttributes addFlashAttribute(Object attributeValue); Map getFlashAttributes();

Les attributs Flash sont de courte durée . En tant que tels, ceux-ci sont stockés temporairement dans un stockage sous-jacent, juste avant la redirection. Ils restent disponibles pour la demande suivante après la redirection, puis ils sont partis.

2.3. Structure des données FlashMap

Spring fournit une structure de données abstraite appelée FlashMap pour stocker les attributs flash sous forme de paires clé-valeur.

Jetons un œil à la définition de la classe FlashMap :

public final class FlashMap extends HashMap implements Comparable { @Nullable private String targetRequestPath; private final MultiValueMap targetRequestParams = new LinkedMultiValueMap(4); private long expirationTime = -1; }

On peut remarquer que la classe FlashMap hérite de son comportement de la classe HashMap . En tant que telle, une instance FlashMap peut stocker un mappage clé-valeur des attributs . De plus, nous pouvons lier une instance de FlashMap pour qu'elle ne soit utilisée que par une URL de redirection spécifique.

De plus, chaque requête a deux instances FlashMap , à savoir Input FlashMap et Output FlashMap, qui jouent un rôle important dans le modèle PRG:

  • Output FlashMap est utilisé dans la requête POST pour enregistrer temporairement les attributs flash et les envoyer à la prochaine requête GET après la redirection
  • Input FlashMap est utilisé dans la requête GET finale pour accéder aux attributs flash en lecture seule qui ont été envoyés par la requête POST précédente avant la redirection

2.4. FlashMapManager et RequestContextUtils

Comme son nom l'indique, nous pouvons utiliser FlashMapManager pour gérer les instances de FlashMap .

Jetons d'abord un coup d'œil à la définition de cette interface de stratégie:

public interface FlashMapManager { @Nullable FlashMap retrieveAndUpdate(HttpServletRequest request, HttpServletResponse response); void saveOutputFlashMap(FlashMap flashMap, HttpServletRequest request, HttpServletResponse response); }

En termes simples, nous pouvons dire que FlashMapManager nous permet de lire, mettre à jour et enregistrer des instances de FlashMap dans un stockage sous-jacent.

Ensuite, familiarisons-nous avec quelques méthodes statiques disponibles dans la classe d'utilitaire abstrait RequestContextUtils .

Pour rester concentré dans le cadre de ce didacticiel, nous limiterons notre couverture aux méthodes pertinentes pour les attributs flash:

public static Map getInputFlashMap(HttpServletRequest request); public static FlashMap getOutputFlashMap(HttpServletRequest request); public static FlashMapManager getFlashMapManager(HttpServletRequest request); public static void saveOutputFlashMap(String location, HttpServletRequest request, HttpServletResponse response);

Nous pouvons utiliser ces méthodes pour récupérer les instances FlashMap d' entrée / sortie , obtenir le FlashMapManager pour une requête et enregistrer une instance FlashMap .

3. Cas d'utilisation de la soumission de formulaire

À présent, nous avons établi une compréhension de base des différents concepts relatifs aux attributs Flash. Alors, allons plus loin et utilisons-les dans une application Web de concours de poésie.

Notre application de concours de poésie a un cas d'utilisation simple d'acceptation des entrées de poèmes de différents poètes via la soumission d'un formulaire. De plus, une inscription au concours contiendra les informations nécessaires relatives à un poème, comme un titre, un corps et le nom de l'auteur.

3.1. Configuration de Thymeleaf

Nous utiliserons Thymeleaf, qui est un moteur de modèle Java pour créer des pages Web dynamiques via de simples modèles HTML.

Tout d' abord, nous devons ajouter le printemps-boot-démarreur-thymeleaf dépendance à notre projet pom.xml :

 org.springframework.boot spring-boot-starter-thymeleaf 2.2.1.RELEASE 

Ensuite, nous pouvons définir certaines des propriétés spécifiques à Thymeleaf dans notre fichier pplication.properties situé dans le répertoire src / main / resources :

spring.thymeleaf.cache=false spring.thymeleaf.enabled=true spring.thymeleaf.prefix=classpath:/templates/ spring.thymeleaf.suffix=.html

Après avoir défini ces propriétés, nous pouvons maintenant créer toutes nos vues dans le répertoire / src / main / resources / templates . À son tour, Spring ajoutera le suffixe .html à toutes les vues nommées dans notre contrôleur.

3.2. Modèle de domaine

Up next, let's define our domain model in a Poem class:

public class Poem { private String title; private String author; private String body; }

Further, we can add the isValidPoem() static method in our Poem class to help us validate that the fields don't allow empty strings:

public static boolean isValidPoem(Poem poem) { return poem != null && Strings.isNotBlank(poem.getAuthor()) && Strings.isNotBlank(poem.getBody()) && Strings.isNotBlank(poem.getTitle()); }

3.3. Create Form

Now, we're ready to create our submission form. For that, we need an endpoint /poem/submit that will serve a GET request to show the form to the user:

@GetMapping("/poem/submit") public String submitGet(Model model) { model.addAttribute("poem", new Poem()); return "submit"; }

Here, we've used a model as a container to hold the poem-specific data provided by the user. Moreover, the submitGet method returns a view served by the submit view.

Additionally, we want to bind the POST form with the model attribute poem:

3.4. Post/Redirect/Get Submission Flow

Now, let's enable the POST action for the form. To do that, we'll create the /poem/submit endpoint in the PoemSubmission controller to serve the POST request:

@PostMapping("/poem/submit") public RedirectView submitPost( HttpServletRequest request, @ModelAttribute Poem poem, RedirectAttributes redirectAttributes) { if (Poem.isValidPoem(poem)) { redirectAttributes.addFlashAttribute("poem", poem); return new RedirectView("/poem/success", true); } else { return new RedirectView("/poem/submit", true); } }

We can notice that if the submission is successful, then control transfers to the /poem/success endpoint. Also, we added the poem data as a flash attribute before initiating the redirect.

Now, we need to show a confirmation page to the user, so let's implement the functionality for the /poem/success endpoint that'll serve the GET request:

@GetMapping("/poem/success") public String getSuccess(HttpServletRequest request) { Map inputFlashMap = RequestContextUtils.getInputFlashMap(request); if (inputFlashMap != null) { Poem poem = (Poem) inputFlashMap.get("poem"); return "success"; } else { return "redirect:/poem/submit"; } }

Il est important de noter ici que nous devons valider la FlashMap avant de décider de rediriger vers la page de réussite .

Enfin, utilisons le poème d' attribut flash dans notre page de réussite pour afficher le titre du poème soumis par l'utilisateur:

Click here to submit more.

4. Conclusion

Dans ce didacticiel, nous avons appris quelques concepts relatifs au modèle Post / Redirection / Get et aux attributs Flash. Et nous avons également vu les attributs flash en action avec une simple soumission de formulaire dans une application Web Spring Boot.

Comme toujours, le code source complet du didacticiel est disponible à l'adresse over sur GitHub.