Manuel de formation sur l’utilisation du Framework Thymeleaf et Spring MVC
Manuel de formation sur l’utilisation du Framework Thymeleaf et Spring MVC
…
1.4 La place de Spring MVC dans une application Web
Situons Spring MVC dans le développement d'une application Web. Le plus souvent, celle-ci sera bâtie sur une architecture multicouche telle que la suivante :
- la couche [Web] est la couche en contact avec l'utilisateur de l'application Web. Celui-ci interagit avec l'application Web au travers de pages Web visualisées par un navigateur. C'est dans cette couche que se situe Spring MVC et uniquement dans cette couche ;
- la couche [métier] implémente les règles de gestion de l'application, tels que le calcul d'un salaire ou d'une facture. Cette couche utilise des données provenant de l'utilisateur via la couche [Web] et du SGBD via la couche [DAO] ;
- la couche [DAO] (Data Access Objects), la couche [ORM] (Object Relational Mapper) et le pilote JDBC gèrent l'accès aux données du SGBD. La couche [ORM] fait un pont entre les objets manipulés par la couche [DAO] et les lignes et les colonnes des tables d'une base de données relationnelle. Nous utiliserons ici l'ORM Hibernate. Une spécification appelée JPA (Java Persistence API) permet de s'abstraire de l'ORM utilisé si celui-ci implémente ces spécifications. C'est le cas d'Hibernate et des autres ORM Java. On appellera donc désormais la couche ORM, la couche JPA ;
- l'intégration des couches est faite par le framework Spring ;
La plupart des exemples donnés dans la suite, n'utiliseront qu'une seule couche, la couche [Web] :
..
Ce document se terminera cependant par la construction d'une application Web multitier :
Le navigateur se connectera à une application [Web1] implémentée par Spring MVC / Thymeleaf qui ira chercher ses données auprès d'un service web [Web2] lui aussi implémenté avec Spring MVC. Cette seconde application web accédera à une base de données.
1.5 Le modèle de développement de Spring MVC
Spring MVC implémente le modèle d'architecture dit MVC (Modèle – Vue – Contrôleur) de la façon suivante :
Le traitement d'une demande d'un client se déroule de la façon suivante :
- demande - les URL demandées sont de la forme /contexte/Action/param1/param2/....?p1=v1&p2=v2&... Le
[Front Controller] utilise un fichier de configuration ou des annotations Java pour " router " la demande vers le bon contrôleur et la bonne action au sein de ce contrôleur. Pour cela, il utilise le champ [Action] de l'URL. Le reste de l'URL
[/param1/param2/...] est formé de paramètres facultatifs qui seront transmis à l'action. Le C de MVC est ici la chaîne [Front
Controller, Contrôleur, Action]. Si aucun contrôleur ne peut traiter l'action demandée, le serveur Web répondra que l'URL demandée n'a pas été trouvée.
- traitement
- l'action choisie peut exploiter les paramètres parami que le [Front Controller] lui a transmis. Ceux-ci peuvent provenir de plusieurs sources :
- du chemin [/param1/param2/...] de l'URL,
- des paramètres [p1=v1&p2=v2] de l'URL,
- de paramètres postés par le navigateur avec sa demande ;
- dans le traitement de la demande de l'utilisateur, l'action peut avoir besoin de la couche [métier] [2b]. Une fois la demande du client traitée, celle-ci peut appeler diverses réponses. Un exemple classique est :
- une page d'erreur si la demande n'a pu être traitée correctement
- une page de confirmation sinon
- l'action demande à une certaine vue de s'afficher [3]. Cette vue va afficher des données qu'on appelle le modèle de la vue. C'est le M de MVC. L'action va créer ce modèle M [2c] et demander à une vue V de s'afficher [3] ;
- réponse - la vue V choisie utilise le modèle M construit par l'action pour initialiser les parties dynamiques de la réponse HTML qu'elle doit envoyer au client puis envoie cette réponse.
Maintenant, précisons le lien entre architecture web MVC et architecture en couches. Selon la définition qu'on donne au modèle, ces deux concepts sont liés ou non. Prenons une application web Spring MVC à une couche :
…
Si nous implémentons la couche [Web] avec Spring MVC, nous aurons bien une architecture web MVC mais pas une architecture multicouche. Ici, la couche [web] s'occupera de tout : présentation, métier, accès aux données. Ce sont les actions qui feront ce travail.
La couche [Web] peut être implémentée sans framework et sans suivre le modèle MVC. On a bien alors une architecture multicouche mais la couche Web n'implémente pas le modèle MVC. Par exemple, dans le monde .NET la couche [Web] ci-dessus peut être implémentée avec ASP.NET MVC et on a alors une architecture en couches avec une couche [Web] de type MVC. Ceci fait, on peut remplacer cette couche ASP.NET MVC par une couche ASP.NET classique (WebForms) tout en gardant le reste (métier, DAO, ORM) à l'identique. On a alors une architecture en couches avec une couche [Web] qui n'est plus de type MVC.
Dans MVC, nous avons dit que le modèle M était celui de la vue V, c.a.d. l'ensemble des données affichées par la vue V. Une autre définition du modèle M de MVC est donnée :
…
Beaucoup d'auteurs considèrent que ce qui est à droite de la couche [Web] forme le modèle M du MVC. Pour éviter les ambigüités on peut parler :
- du modèle du domaine lorsqu'on désigne tout ce qui est à droite de la couche [Web]
- du modèle de la vue lorsqu'on désigne les données affichées par une vue V
Dans la suite, le terme " modèle M " désignera exclusivement le modèle d'une vue V.
1.6 Un premier projet Spring MVC
… …
Examinons le projet, d'abord sa configuration Maven.
1.6.2 Configuration Maven
Le fichier [pom.xml] est le suivant :
- <?xml version="1.0" encoding="UTF-8"?>
- <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 ">
- <modelVersion>4.0.0</modelVersion>
5.
- <groupId>org.springframework</groupId>
- <artifactId>gs-serving-web-content</artifactId>
- <version>0.1.0</version>
9.
- <parent>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-parent</artifactId>
- <version>1.1.9.RELEASE</version>
- </parent>
15.
- <dependencies>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-thymeleaf</artifactId>
- </dependency>
- </dependencies>
- <properties>
- <start-class>hello.Application</start-class>
- </properties>
26.
- <build>
- <plugins>
- <plugin>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-maven-plugin</artifactId>
- </plugin>
- </plugins>
- </build>
35.
- <repositories>
- <repository>
- <id>spring-milestone</id>
- <url></url>
- </repository>
- </repositories>
42.
- <pluginRepositories>
- <pluginRepository>
- <id>spring-milestone</id>
- <url></url>
- </pluginRepository>
- </pluginRepositories>
49.
- </project>
- lignes 6-8 : les propriétés du projet Maven. Manque une balise [] indiquant le type du fichier produit par la compilation Maven. En l'absence de celle-ci, c'est le type [jar] qui est utilisé. L'application est donc une application exécutable de type console, et non une application web où le packaging serait alors [war] ;
- lignes 10-14 : le projet Maven a un projet parent [spring-boot-starter-parent] C'est lui qui définit l'essentiel des dépendances du projet. Elles peuvent être suffisantes, auquel cas on n'en rajoute pas, ou pas, auquel cas on rajoute les dépendances manquantes ;
- lignes 17-20 : l'artifact [spring-boot-starter-thymeleaf] amène avec lui les bibliothèques nécessaires à un projet spring MVC utilisé conjointement avec un moteur de vues appelé [Thymeleaf]. Cet artifact amène avec lui un très grand de bibliothèques dont celles d'un serveur Tomcat embarqué. C'est sur ce serveur que l'application sera exécutée ;
… …
1.6.3 L'architecture d'une application Spring MVC
Spring MVC implémente le modèle d'architecture dit MVC (Modèle – Vue – Contrôleur) :
Le traitement d'une demande d'un client se déroule de la façon suivante :
- demande - les URL demandées sont de la forme /Action/param1/param2/....?p1=v1&p2=v2&... La
[Dispatcher Servlet] est la classe de Spring qui traite les URL entrantes. Elle "route" l'URL vers l'action qui doit la traiter. Ces actions sont des méthodes de classes particulières appelées [Contrôleurs]. Le C de MVC est ici la chaîne [Dispatcher Servlet,
Contrôleur, Action]. Si aucune action n'a été configurée pour traiter l'URL entrante, la servlet [Dispatcher Servlet] répondra que l'URL demandée n'a pas été trouvée (erreur 404 NOT FOUND) ;
- traitement
- l'action choisie peut exploiter les paramètres parami que la servlet [Dispatcher Servlet] lui a transmis. Ceux-ci peuvent provenir de plusieurs sources :
- du chemin [/param1/param2/...] de l'URL,
- des paramètres [p1=v1&p2=v2] de l'URL,
- de paramètres postés par le navigateur avec sa demande ;
- dans le traitement de la demande de l'utilisateur, l'action peut avoir besoin de la couche [metier] [2b]. Une fois la demande du client traitée, celle-ci peut appeler diverses réponses. Un exemple classique est :
- une page d'erreur si la demande n'a pu être traitée correctement
- une page de confirmation sinon
- l'action demande à une certaine vue de s'afficher [3]. Cette vue va afficher des données qu'on appelle le modèle de la vue. C'est le M de MVC. L'action va créer ce modèle M [2c] et demander à une vue V de s'afficher [3] ;
- réponse - la vue V choisie utilise le modèle M construit par l'action pour initialiser les parties dynamiques de la réponse HTML qu'elle doit envoyer au client puis envoie cette réponse.
Nous allons regarder ces différents éléments dans le projet étudié.
1.6.4 Le contrôleur C
L'application importée a le contrôleur suivant :
- package hello;
2.
- import org.springframework.stereotype.Controller;
- import org.springframework.ui.Model;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RequestParam;
7.
- @Controller
- public class GreetingController {
10.
- @RequestMapping("/greeting")
- public String greeting(@RequestParam(value="name", required=false, defaultValue="World") String name,
Model model) {
- model.addAttribute("name", name);
- return "greeting";
- }
16.
- }
- ligne 8 : l'annotation [@Controller] fait de la classe [GreetingController] un contrôleur Spring, ç-à-d que ses méthodes sont enregistrées pour traiter des URL ;
- ligne 11 : l'annotation [@RequestMapping] indique l'URL que traite la méthode, ici l'URL [/greeting]. Nous verrons ultérieurement que cette URL peut être paramétrée et qu'il est possible de récupérer ces paramètres ;
- ligne 12 : la méthode admet deux paramètres :
◦ [String name] : ce paramètre est initialisé par un paramètre de nom [name] dans la requête traitée, par exemple [/greeting?name=alfonse]. Ce paramètre est facultatif [required=false] et lorsqu'il n'est pas là, le paramètre [name] prendra la valeur 'World' [defaultValue="World"],
◦ [Model model] est un modèle de vue. Il arrive vide et c'est le rôle de l'action (la méthode greeting) de le remplir. C'est ce modèle qui sera transmis à la vue que va faire afficher l'action. C'est donc un modèle de vue ;
- ligne 13 : la valeur de [name] est mis dans le modèle de la vue. La classe [Model] se comporte comme un dictionnaire ;
- ligne 14 : la méthode rend le nom de la vue qui doit afficher le modèle construit. Le nom exact de la vue dépend de la configuration de [Thymeleaf]. En l'absence de celle-ci, la vue affichée ici sera la vue [/templates/greeting.html] ou le dossier [templates] doit être à la racine du Classpath du projet ;