Programmation Evoluée
Le Framework Spring
Chaker BEN MAHMOUD 2024
Références
• Livre « Spring par la pratique - Spring 2.5 et 3.0 », Arnaud
Cogoluègnes, Thierry Templier, Julien Dubois, EDITION Eyrolles,
2011,
• Livre « Spring par l'exemple », Gary Mak, EDITION PEARSON,
2009,
• Support de Cours « Spring MVC », Achref El Mouelhi, Ecole
d'ingénieurs d'Aix-Marseille Université, 2018
• Spring Documentation : [Link] (accès 03/09/2022)
Page 2
Plan
Chapitre 1 : Spring IoC
Chapitre 2 : Spring MVC
Chapitre 3 : Spring Data
Chapitre 4 : Spring Security
Chapitre 5 : Spring REST et Spring Boot
Page 3
Chapitre 1
Page 4
Introduction
Spring est un framework de développement Java
basé sur le concept de "conteneur léger"
Principes : cf article de Martin Fowler « Inversion of
Control Containers and the Dependency Injection pattern »
Spring en bref :
– début du projet en 2002
– créé par Rod Johnson (et Juergen Holler)
– projet Open Source
– Société : « SpringSource » => « VMware » => « Pivotal »
Page 5
Introduction
Les principales versions :
–Spring 1.0 (Mars 2004)
–Spring 2.0 (Oct 2006)
–Spring 2.5 (Nov 2007, annotations, …)
–Spring 3.0 (Dec 2009)
–Spring 3.1 (2011), Spring 3.2 (2012)
–Spring 4.0 (Dec 2013)
–Spring 5.0 (Dec 2017)
–Spring 6.0 (Novembre 2022)
=> actuellement version 6.1.4 (Février 2022)
Spring est composé de nombreuses "briques" qui peuvent
être utilisées indépendamment les unes des autres …
Page 6
Introduction
Page 7
Introduction
Notion de "conteneur léger" …
Se définit essentiellement par opposition aux
conteneurs dits "lourds", par exemple les conteneurs
d'EJB (en particulier avant les EJB 3) :
– Environnement souvent inadapté pour gérer des composants
simples
– Règles de développement et de déploiement contraignantes
Avantages d'un conteneur léger :
– Pas de "couplage" entre le conteneur et les composants qu'il gère
( non intrusif )
– N'importe quel objet peut être géré par le conteneur
– Rien à installer ( code Java + .jar : c'est tout ! )
Page 8
Introduction
Les concepts du "conteneur léger" de Spring
– Séparation des préoccupations
( SoC : Separation of Concerns )
– Inversion de contrôle
( IoC : Inversion of Control )
– Injection de dépendances
( DI : Dependency Injection )
– Gestion du cycle de vie des objets (Factory, Singleton,… )
– Programmation Orientée Aspect
( AOP : Aspect Oriented Programming )
Page 9
Séparation des préoccupations
En anglais "Separation Of Concerns" ( SoC )
Pris isolément, chaque problème est plus facile à traiter
=> séparation en couches, domaines, …
=> c’est un principe très ancien
Principe qui consiste à isoler les différentes problématiques à
traiter, par exemple :
– Présentation ( IHM, … )
– Services Métiers
– Persistance
– etc...
notion de composants spécialisés
Page 10
Inversion de contrôle
En anglais "Inversion Of Control" ( IoC )
Modèle de conception utilisé par de nombreux
Frameworks
Illustré par le "principe d'Hollywood"
"Don't call us, we'll call you"
Le code applicatif n'a plus l'initiative, il est "mis à
disposition"
Page 11
Injection de dépendance
Pour pouvoir fonctionner, un composant a généralement
besoin d'autres composants ...
L'injection de dépendance permet de "fabriquer" les
composants et de leur "injecter" automatiquement les
composants nécessaires
Page 12
Problématique
Fabrication directe des composants nécessaires
"A" a besoin de "B" et de "C"
=> il les fabrique lui-même !
Page 13
Solution "idéale"
Objectifs :
– "A" ne crée pas les composants dont il a besoin
– "A" ne récupère pas lui-même ces composants par un
tiers.
– "A" est totalement autonome
Comment ?
– Un objet externe va lui "injecter" les composants dont il a
besoin
– Le cycle vie de "A" est donc géré par cet objet "invisible" : le
conteneur de composants
Page 14
Le conteneur IoC de spring
Le conteneur IoC (container) de spring est le module
principal de ce framework,
Le conteneur va créer les objets, les associer ensemble, les
configurer et gérer leur cycle de vie complet,
Le conteneur utilise l’injection de dépendance (DI) pour
gérer les éléments qui composent une application.
Ces objets sont appelés Spring Beans.
Le conteneur reçoit des instructions sur ces objets par la
lecture des métadonnées de configuration.
Les métadonnées de configuration peuvent être représenté
soit par XML, annotations java ou code java.
Page 15
Le conteneur IoC de spring
Vue globale du schéma de fonctionnement de Spring
Page 16
Le conteneur IoC
Principaux éléments du "conteneur léger" :
– Les "beans" : objets gérés par le conteneur léger
– La "fabrique de bean" ("BeanFactory") : Mécanisme de
configuration qui permet de gérer des "beans" de différentes
natures (singleton/prototype)
– Le "contexte d'application" ("ApplicationContext") : extension
de la BeanFactory, concrètement un contexte est initialisé à partir
d'un fichier de configuration (XML)
Page 17
Le conteneur IoC : Les Beans
Les objets qui forment une application et qui sont gérer par le conteneur
IoC de Spring sont appelés Beans.
Un Bean est un objet qui instancié et géré par le conteneur IoC.
Ces Beans sont créés par des métadonnées de configuration fournis
par le conteneur via la balise <bean/>
Page 18
Le conteneur IoC : Les Beans
Spring prend en charge des types de scope pour les
beans:
– Singleton (une seule instance par conteneur IoC Spring
(par défaut))
– Prototype
– Request
– Session Web-aware scopes
– Global-session
Le scope dans une application Spring MVC
: combien de temps le Bean existe-t-il
Page 19
Création des Beans
Deux méthodes pour créer des beans :
– basée sur les constructeurs
• Le conteneur invoque un constructeur de la classe avec un
certain nombre d’arguments
<constructor-arg ... />
– Basée sur les modificateurs (Setters)
• Accompli par le conteneur en appelant les méthodes setters des
Beans désirés
<property ... />
Page 20
Création des Beans
considérons l’exemple suivant
public class Personne {
private int id;
private String nom;
public Personne() {}
public Personne(int id) {
[Link] = id;
}
public Personne(int id, String nom) {
[Link] = id;
[Link] = nom;
}
void afficher(){
[Link]([Link]+" "+[Link]);
}
}
Page 21
Création des Beans
Pour instancier la classe personne et afficher les détails de
l’objet créé :
Personne p = new Personne (1, ‘Ali’);
[Link]();
Ou bien :
Personne p = new Personne ();
[Link](1);
[Link](’Ali’);
[Link]();
Page 22
Création des Beans
Création d’un bean à base des constructeurs
<bean id="per" class="[Link]">
<constructor-arg value="1"></constructor-arg>
<constructor-arg value="Ali"></constructor-arg>
</bean>
Création d’un bean à base des modificateurs
<bean id="per" class="[Link] ">
<property name="id" value="1"></property>
<property name="nom" value="Ali"></property>
</bean>
Page 23
Injection de dépendance (DI) basée Constructeur
Et si on a une dépendance avec une autre classe ou une collection
public class Adresse {
private String rue;
private String codeP;
private String ville;
public Adresse() {}
public Adresse(String rue, String codeP, String ville){
[Link] = rue;
[Link] = codeP;
[Link] = ville;
}
}
Page 24
Injection de dépendance (DI) basée Constructeur
public class Personne {
private int id;
private String nom;
private Adresse adresse;
public Personne() {}
public Personne(int id) { public Personne(int id, String nom,
[Link] = id; Adresse adresse) {
} [Link] = id;
public Personne(int id, [Link] = nom;
[Link] = adresse;
String nom)
}
{
[Link] = id; void afficher(){
[Link] = nom; [Link]([Link]+" "+
} [Link]+" "+[Link]());
}
}
Page 25
Injection de dépendance (DI) basée Constructeur
<bean id="adresse1" class=“[Link]">
<constructor-arg value="Ibn Khattab"></constructor-arg>
<constructor-arg value="6072"></constructor-arg>
<constructor-arg value="Gabes"></constructor-arg>
</bean>
<bean id="per" class=“[Link]">
<constructor-arg value="1" type="int"></constructor-arg>
<constructor-arg value="Ali"></constructor-arg>
<constructor-arg>
<ref bean="adresse1"/>
</constructor-arg>
</bean>
Page 26
Injection de dépendance (DI) basée Setters
Et si on a un objet de type Adresse dans Personne
<bean id="adr" class=“[Link]">
<constructor-arg value="Ibn Khattab" />
<constructor-arg value="6072" />
<constructor-arg value="Gabes" />
</bean>
<bean id="per" class=“[Link]">
<property name="id" value="1" />
<property name="nom" value="Ali" />
<property name="adresse" ref="adr" />
</bean>
Page 27
Injection de dépendance (DI) basée Constructeur
Et les collections?
public class Personne {
private int id;
private String nom;
private List<String> sports;
……………………
}
<bean id="per" class=“[Link]">
<constructor-arg value="1" type="int"></constructor-arg>
<constructor-arg value="Ali"></constructor-arg>
<constructor-arg>
<list>
<value>foot</value>
<value>hand</value>
<value>basket</value>
</list>
</constructor-arg>
</bean>
Page 28
Le conteneur IoC
Les conteneurs IoC peuvent être :
Page 29
Le conteneur IoC : BeanFactory
Il s'agit du conteneur le plus simple fournissant le support de
base pour DI et défini par l'interface BeanFactory.
Il existe un certain nombre d'implémentations de l'interface
BeanFactory qui sont prêtes à l'emploi avec Spring.
L'implémentation de BeanFactory la plus couramment utilisée
est la classe XmlBeanFactory.
Ce conteneur lit les métadonnées de configuration à partir d'un
fichier XML et les utilise pour créer un système ou une
application entièrement configuré.
BeanFactory est généralement préférée lorsque les
ressources sont limitées, comme les appareils mobiles ou les
applications basées sur des applet.
Page 30
Le conteneur IoC : BeanFactory
Exemple d’utilisation
Resource r= new ClassPathResource("[Link]");
BeanFactory factory = new XmlBeanFactory(r);
Etudiant et= (Etudiant) [Link]("e1");
[Link]([Link]());
Page 31
Le conteneur IoC : ApplicationContext
Chaque Application utilise Spring à travers l'interface ApplicationContext
ApplicationContext dispose de plusieurs implémentations, dont :
– FileSystemXmlApplicationContext
(charge la configuration xml à partir du « file system » )
– ClassPathXmlApplicationContext
(charge la configuration xml à partir du « ClassPath » )
– AnnotationConfigApplicationContext
(char
Page 32
Métadonnées de
configuration à base d’un
fichier XML
Page 33
Le conteneur IoC et l’injection de dépendance
L’injection des dépendance, ou l’inversion de
contrôle est un concept qui intervient généralement
au début de l’exécution de l’application.
Spring IoC commence par lire un fichier XML qui
déclare quelles sont différentes classes à instancier
et d’assurer les dépendances entre les différentes
instances.
Quand on a besoin d’intégrer une nouvelle
implémentation à une application, il suffirait de la
déclarer dans le fichier xml de beans Spring.
Page 34
Injection de dépendance (DI) basée Constructeur
Première solution : avec un fichier .xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="[Link]
xmlns:xsi="[Link]
xsi:schemaLocation="[Link]
<bean id="per" class="[Link]">
<constructor-arg value="1" type="int"></constructor-arg>
<constructor-arg value="Ali"></constructor-arg>
</bean>
</beans>
RQ: Par défaut, le type d’un attribut est string (par exemple, nom)
Page 35
Injection de dépendance (DI) basée Constructeur
Et comment utiliser cet objet?
ApplicationContext context =
new ClassPathXmlApplicationContext("[Link]");
Personne p = [Link]("per",[Link]);
[Link]();
Page 36
Métadonnées de
configuration à base des
annotations
Page 37
Spring et les annotations
La configuration peut se faire directement dans le code en
utilisant des annotations
=> plus besoin de mettre à jour le fichier XML
En cas de double configuration (XML et annotation) c’est
la configuration XML qui prime
Page 38
Evolution : ajout d'une interface
L'application ne crée plus les objets elle-même, mais elle
reste liée à la classe qui fournit le service
=> il est préférable de passer par une interface
Page 39
Spring et les annotations
Considérons l’interface European et les deux classes French
et English qui l’implémente
public interface European {
void saluer();
}
public class French implements European {
public void saluer() {
[Link]("Bonjour");
}
}
public class English implements European {
public void saluer() {
[Link]("Hello");
}
}
Page 40
Spring et les annotations
Pour déclarer un Bean, il faut annoter la classe par @Component
European est une interface, donc on ne peut instancier.
@Component("french")
public class French implements European {
public void saluer() {
[Link]("Bonjour");
}
}
@Component("english")
public class English implements European {
public void saluer() {
[Link]("Hello");
}
}
Page 41
Spring et les annotations
Solution 1: dans le fichier [Link] on ajouter une balise qui
permet d’indiquer dans quel package se trouve les annotations:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="[Link]
xmlns:xsi="[Link]
xmlns:context="[Link]
xsi:schemaLocation="[Link]
[Link]
[Link]
[Link]
<context:component-scan base-package="[Link]" />
</beans>
Page 42
Spring et les annotations
Solution 2 : Ne pas utilisé le fichier [Link] (à supprimer)
Utiliser la classe AnnotationConfigApplicationContext
pour charger le contexte toute en spécifiant le package de
base pour la recherche des annotations
public class TestApp {
public static void main(String[] args) {
ApplicationContext context =
new AnnotationConfigApplicationContext("[Link]");
European e1 = (European) [Link]("french");
[Link]();
}
}
Page 43
Spring et les annotations
On peut utiliser des Component nommés :
@Component("c1")
public class French implements European {
public void saluer() {
[Link]("Bonjour");
}
}
European e1 = (European) [Link](“c1");
[Link]();
Page 44
Spring et les annotations
Exemple 2 :
@Component
public class Voiture {
public void demarer() {
[Link]("Voiture démarrée et prête à rouler");
}
}
@Component
public class Person {
Voiture v;
void drive() {
[Link]("Je suis prêt a conduire");
[Link]();
}
}
En exécutant ce code, une erreur sera affichée car on ne peut
appeler la méthode start() si la classe car n’a pas été instanciée.
Person p = (Person) [Link]("person");
[Link]();
Page 45
Spring et les annotations
Solution : utiliser une annotation pour créer l’objet v après instanciation de
la classe Person
@Autowired cherche les Beans selon le type.
Pour chercher un Bean selon le nom, il faut utiliser l’annotation @Qualifier
@Component
public class Person {
@Autowired
Voiture v;
void drive() {
[Link]("Je suis prêt a conduire");
[Link]();
}
}
Page 46
La configuration grâce aux annotations
• Avec Spring, il est possible de configurer le contexte en utilisant des
annotations au lieu du fichier de configuration XML.
• Spring propose plusieurs annotations issues du projet pour définir
certaines fonctionnalités de la configuration dans le code Java
notamment @Configuration et @Bean.
• Une classe annotée avec @Configuration permet de demander au
conteneur d'utiliser cette classe pour instancier des beans.
• L'annotation @Bean s'utilise sur une méthode d'une classe annotée
avec @Configuration qui crée une instance d'un bean.
• L'utilisation de ces annotations requiert que le tag
<context:component-scan> soit utilisé dans la configuration XML
du contexte de Spring.
Page 47
La configuration grâce aux annotations
@Configuration
public class AppConfiguration {
@Bean
public Etudiant getEtudiant() {
return new Etudiant(25, "aloulou");
}
}
public class TestApp {
public static void main(String[] args) {
ApplicationContext cxt=
new AnnotationConfigApplicationContext([Link]);
Etudiant e11=(Etudiant) [Link]("a1");
[Link]([Link]());
}
}
Page 48
La configuration grâce aux annotations
• La classe AnnotationConfigApplicationContext doit être utilisée
pour créer le contexte Spring à partir des classes de l'application
utilisant les annotations @Configuration et @Bean.
• La classe AnnotationConfigApplicationContext possède
plusieurs constructeurs.
• Il est possible de fournir en paramètre les instances de type Class
des classes à scanner (qui contient @configuration).
new AnnotationConfigApplicationContext([Link]);
• Il est aussi capable de scanner des répertoires pour trouver les
classes annotées avec @Configuration en les passant en
paramètres du constructeur.
new AnnotationConfigApplicationContext("[Link]");
Page 49
L'annotation @Configuration
• Les classes annotées avec @Configuration doivent respecter
certaines contraintes :
• ne doivent pas être final
• ne peuvent pas être déclarées dans une méthode d'une
autre classe
• doivent avoir un constructeur par défaut sans paramètre
• ne peuvent pas utiliser l'annotation @Autowired sur les
paramètres de leurs constructeurs
• L'annotation @Configuration est elle-même annotée avec
@Component : les classes annotées avec @Configuration
sont scannées et peuvent donc utiliser l'annotation
@Autowired sur des champs ou des méthodes.
Page 50
L'annotation @Bean
• Cette annotation est à utiliser sur une méthode qui se charge
de créer une instance d'un bean.
• L'annotation @Bean indique au conteneur que la méthode
pour être utilisée pour créer une instance d'un bean.
• L'identifiant est fourni en tant qu'attribut name de l'annotation
ou, à défaut, correspond au nom de la méthode avec la
première lettre en minuscule.
• L'attribut name est un tableau de chaînes de caractères ce qui
permet de préciser des alias.
• Cette annotation est similaire au tag <bean> du fichier de
configuration.
Page 51
Spring et les annotations
@Component("c1")
public class Voiture {
public void demarer() {
[Link]("Voiture démarrée et prête à rouler");
}
}
@Component
public class Person {
@Autowired
@Qualifier("c1")
Voiture v;
void drive() {
[Link]("Je suis prêt a conduire");
[Link]();
}
}
Page 52
« Common annotations » ( JSR-250 )
Page 53
Spring et les annotations
<dependency>
@Inject
<groupId>[Link]</groupId>
<artifactId>[Link]</artifactId>
<version>1</version>
</dependency>
<dependency> @Resource
<groupId>[Link]</groupId>
<artifactId>jsr250-api</artifactId>
<version>1.0</version>
</dependency>
Page 54
Spring et les annotations
A partir de Spring 2.5, il existe 4 types d’annotations pour
chercher les composants :
– @Component - Indique un composant simple
– @Repository - Indique le composant DAO dans la couche de
persistance.
– @Service - Indique un composant de service dans la couche de
gestion.
– @Controller - Indique un composant de contrôleur dans la
couche de présentation.
Alors, lequel utiliser?
Et dans quel contexte???
Page 55
Programmation Evoluée
Chapitre 2
Page 56
Introduction à Spring MVC
Spring MVC est un Framework Model-View-Controller
– Il permet de faire des applications Web
– Il est relativement simple à apprendre
– Il est performant et robuste
– Il est très configurable
Spring MVC est intégré à Spring Core (ce n’est pas un
sousprojet)
Page 57
Le modèle MVC
Le modèle MVC a été popularisé en Java par Struts
– Spring MVC est un concurrent direct de Struts
Page 58
Les composants de Spring MVC
Le Controller
– Un Bean Spring, annoté @Controller
– Supporte donc l’injection de dépendance : c’est ainsi qu’il accède à la
couche Service
– Il valide la requête, remplit le modèle, et redirige vers la bonne vue
La vue
– C’est typiquement une JSP qui va être chargée d’afficher le modèle
– Spring MVC n’est pas limité à la technologie JSP, mais c’est elle qui est le
plus couramment utilisée (on peut utiliser bien sur Angular)
Le modèle
– Un Java Bean ou un ensemble de Java Beans (Collection), provenant de la
couche service et étant affiché par la JSP
– Dans cette architecture, ce Java Bean est généralement une entité
Hibernate, ou un ensemble d’entités Hibernate
Page 59
Fonctionnement
Le Framework Spring Web MVC est conçu autour d’une
DispatcherServlet qui gère toutes les requêtes et
réponses HTTP.
Page 60
Fonctionnement
Après avoir reçu une requête HTTP, DispatchServlet
consulte le HandlerMapping pour appeler le Controller
approprié.
Le Controller analyse la requête et appelle les méthodes du
service appropriée, basé sur l’utilisation des méthodes POST
ou GET. La méthode du service initialisera les données du
model selon la logique métier puis retournera le nom de la
vue (view) à DispatcherServlet
DispatcherServlet se servit sur ViewResolver pour récupérer
la bonne vue.
Une fois que la vue est finalisée, DispatcherServlet passe les
données du model à la vue, et qui est finalement affichée sur
le navigateur.
Page 61
Fonctionnement
Tous les composants mentionnés (HandlerMapping,
Controller et ViewResolver) font partis du
WebApplicationContext.
WebApplicationContext est une extension du
ApplicationContext auquel on a ajouté quelques
caractéristiques supplémentaires pour les
applications web.
Page 62
Configuration du DispatcherServlet
Il faut orienter tous les requêtes vers le DispatcherServlet
pour les gérer, en utilisant un mappage d'URL dans le
fichier [Link]
<servlet-mapping>
<servlet-name>servlet-dispatcher</servlet-name>
<url-pattern> / </url-pattern>
</servlet-mapping>
Page 63
Configuration du DispatcherServlet : [Link]
<web-app . . . . version="2.5">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/[Link]</param-value>
</context-param>
<listener>
<listener-class>
[Link]
</listener-class>
</listener>
<servlet>
<servlet-name>servlet-dispatcher</servlet-name>
<servlet-class>
[Link]
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>servlet-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
Page 64
Fonctionnement
Lors de l'initialisation de l’application, le Framework
SpringMVC essaiera de charger le contexte d'application à
partir d'un fichier nommé [Link] situé dans le
répertoire WEB-INF de l'application.
Ensuite, la balise <servlet-mapping> indique quelles sont
les URL qui seront traités ( / ) par le DispatcherServlet.
Si on veut donner un nom et une destination par défaut pour
[Link], on peut personnaliser ce fichier par
l’ajout du listener ContextLoaderListener.
Page 65
Fichier de configuration de Spring MVC
Le fichier [Link]
<beans xmlns="" >
Beans pour les
<context:component-scan base-package="[Link]" /> package de base
et les annotations
<mvc:annotation-driven /> à utiliser
<bean class="[Link]">
<property name="prefix">
<value>/vues/</value>
</property>
<property name="suffix"> Bean pour indiquer le
<value>.jsp</value> dossier des views et
</property> l’extension à ajouter
</bean>
</beans>
Page 66
Fichier de configuration de Spring MVC
On commence par préciser les namespaces à utiliser
dans le projet.
La balise <context:component-scan> permet de
préciser le package de nos contrôleurs qui est ici [Link]
La balise <mvc:annotation-driven> permet d’utiliser
des annotations telles que
@Controller,@RequestMapping, ...
Le bean permet d’indiquer que nos vues seront dans le
répertoire vues (que nous devons créer) et qui auront
comme extension .jsp (donc pas besoin d’indiquer ces
informations qu’on fait appel à une vue)
Page 67
Configuration d’un Controller
Un Controller Spring MVC est un Bean Spring
– On peut lui injecter des Beans Spring de la couche
service, qui sont dans l’Application Context Spring
parent
Il se configure uniquement par annotations
– Historiquement en XML
– Généralement, il n’a pas d’interface et on lui laisse
son nom par défaut : il n’est pas destiné à être
injecté dans un autre Bean
Page 68
Configuration d’un Controller
Les contrôleurs donnent accès au comportement de
l'application que vous définissez généralement via une
interface de service.
Les contrôleurs interprètent les entrées des utilisateurs et les
transforment en un modèle représenté par l'utilisateur dans la
vue.
Spring implémente un contrôleur de manière très abstraite, ce
qui vous permet de créer une grande variété de contrôleurs.
Spring a introduit un modèle de programmation basé sur des
annotations pour les contrôleurs MVC qui utilise des
annotations telles que @RequestMapping, @RequestParam,
@ModelAttribute, etc.
Page 69
Configuration d’un Controller
@Controller
public class AppControlleur {
@RequestMapping("/home", method=[Link])
public String Message1(Model model) {
/* ensemble de traitement possible */
return "pageAcceuil";
}
}
DispatcherServlet délègue la requête de l’utilisateur aux contrôleurs
pour exécuter les fonctions spécifiques,
L’annotation @Controller indique qu’une classe particulaire joue le rôle
d’un contrôleur,
L’annotation est @RequestMapping est utilisé pour mapper une URL à
une méthode particulaire.
Page 70
Configuration d’un Controller
Comme vous pouvez le voir, les annotations @Controller et
@RequestMapping permettent des noms et des signatures
de méthodes flexibles.
Dans cet exemple particulier, la méthode accepte un modèle
et renvoie un nom de vue en tant que chaîne, mais divers
autres paramètres de méthode et valeurs de retour peuvent
être utilisés.
@Controller et @RequestMapping et plusieurs autres
annotations constituent la base de l'implémentation de Spring
MVC.
Page 71
Mapping des requêtes @RequestMapping
Les requêtes peuvent être mappées au niveau de la
classe ou des méthodes
Le mapping s’effectue sur un chemin, mais peut aussi
être fait sur d’autres critères comme en fonction du
verbe HTTP utilisé :
– GET pour lire une donnée
– POST pour la mettre à jour
@RequestMapping(value="/home", method=[Link])
public String Message1(Model model) {
[Link]("message", "Bienvenue à L'ENIG!");
return "pageAcceuil";
}
Page 72
Gestion des paramètres passés à la requête
L’annotation @PathVariable permet de binder un paramètre
de l’URL sur un paramètre de la méthode Java
– Le nom entre { } dans l’URL est par défaut celui du paramètre Java
@RequestMapping(value="/detail/{id}",method =[Link])
public String getDetail (Model model ,
@PathVariable(value="id") int cin) {
[Link]("idUser", cin);
return "detailUesr";
}
Page 73
Gestion des paramètres passés à la requête
La manière la plus simple : ajouter à la méthode un argument
annoté avec @RequestParam
Par défaut, ce paramètre est obligatoire et a le même nom que
le nom de la variable
@RequestMapping(value="/detail",method =[Link])
public String getDetail1(Model model,
@RequestParam(value="id", required=false) int cin) {
[Link]("idUser", cin);
return "detailUesr";
}
URL => [Link]
Page 74
@ModelAttribute sur un paramètre de méthode
Sur un paramètre d’une méthode annotée @RequestMapping,
l’annotation @ModelAttribute va permettre de «binder» les
paramètres de la requête HTTP sur cet objet
@RequestMapping(value="/detail",method =[Link])
public String getDetail(Model model,
@ModelAttribute("etd") Etudiant e1) {
return "detail";
}
ici, il va envoyer à détail un objet nommé etd de type Etudiant
construit avec un constructeur vide,
Page 75
@ModelAttribute sur une méthode
La première utilisation de @ModelAttribute est de mettre
dans le modèle un objet métier
– Cet objet peut être une entité JPA
– Il peut être également un objet spécifiquement développé pour la vue
Lorsqu’une méthode est annotée avec @ModelAttribute,
cette méthode est appelée avant chaque mapping (méthodes
annotées @RequestMapping)
– Ainsi, on est certain d’avoir les bonnes données dès le début
– Attention : cela peut avoir un impact de performances, surtout si cet
objet n’est pas utilisé dans toutes les méthodes annotées
@RequestMapping
Page 76
HttpSession et HttpServletRequest
Vous pouvez utiliser bien sur les HttpServletRequest et HttpSession
@RequestMapping(value="/acceuil",method =[Link])
public String Message1(Model model, HttpServletRequest request) {
String val= [Link]("nom");
. . . .
[Link]("message", "Bienvenue à L'ENIG!");
return "acceuil";
}
@RequestMapping(value="/acceuil",method =[Link])
public String Message1(Model model, HttpSession session) {
String login= (String) [Link]("login");
. . . .
[Link]("message", "Bienvenue à L'ENIG!");
return "acceuil";
}
Page 77
@ModelAttribute sur une méthode
Dans cet exemple, un objet de type Etudiant sera stocké
dans le modèle, avec la clef «etd» :
@ModelAttribute("etd")
public Etudiant getetd(){
Etudiant e1= new Etudiant(10, "ali", "BSS", "555");
return e1;
}
@RequestMapping(value="/detail",method =[Link])
public String getDetail(Model model,
@ModelAttribute("etd") Etudiant e1) {
return "detail";
}
Page 78
Les vues
Permettent d’afficher des données
Communiquent avec le contrôleur pour récupérer ces données
Doivent être créées dans le répertoire views dans WEB-INF,
SpringMVC support plusieurs types des vues pour différentes
technologies de présentation
– JSP,HTML,PDF,XML,JSON,….
– Mais, généralement on utilise les templates JSP écrit avec JSTL
<%@ page language="java" contentType="text/html" pageEncoding="ISO-8859-1" %>
<!DOCTYPE html>
<html>
<head></head>
<body>
${message }
</body>
</html>
Page 79
SpringMVC Tags
À partir de la version 2.0, Spring fournit un ensemble de
balises personnalisées à utiliser à la place des balises de
formulaire HTML standard,
ces balises de forme de Spring permettent de lier les champs
de formulaire aux Beans appelés objets de commande.
<%@ taglib prefix="form" uri="[Link] %>
<form:form action="saveEtudiant" method="post" modelAttribute="etudiant">
CIN <form:input path="cin" type="text" />
Prenom <form:input path="prenom" type="text" />
Nom <form:input path="nom" type="text" />
Groupe <form:input path="groupe" type="text"/>
<input type="submit" value="Enregistrer" />
</form:form>
Page 80
SpringMVC Tags
Page 81
SpringMVC Tags
Deux classes : Etudiant(id, nom, gpe) et Groupe(id, descgp)
<form:form action="saveEtudiant" method="POST"
modelAttribute="etd">
<form:input path="id" />
<form:input path="nom" />
<form:select path="[Link]" items="${listegpe}"
itemLabel="descgp" itemValue="id" />
<input type="submit" value="Enregistrer" />
</form:form>
itemLabel => ce que on afficher dans la liste déroulante
itemValue => ce que on va envoyer dans le modelAttribute
Page 82
Projet SpringMVC
Page 83
Architecture
Navigateur Utilisateur
(1) Request (8)
Reponse
[Link]
Redirection vers le dispatcher (2) (7) [Link]
[Link]
Récupération
Appel du contrôleur nom vue
(3) (4) de la vue (5) (6)
annoté + model
concerné
ViewResolver
Dossier vues
[Link]
Page 84
Projet SpringMVC
Les Dépendances <!-- Servlet Spec -->
<dependency>
<!-- Spring core & mvc --> <groupId>[Link]</groupId>
<dependency> <artifactId>servlet-api</artifactId>
<groupId>[Link]</groupId> <version>2.5</version>
<artifactId>spring-context</artifactId> <scope>compile</scope>
<version>[Link]</version> </dependency>
</dependency> <dependency>
<dependency> <groupId>[Link]</groupId>
<groupId>[Link]</groupId> <artifactId>[Link]-api</artifactId>
<artifactId>spring-webmvc</artifactId> <version>2.3.1</version>
<version>[Link]</version> <scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>[Link]</groupId> <groupId>jstl</groupId>
<artifactId>spring-orm</artifactId> <artifactId>jstl</artifactId>
<version>[Link]</version> <version>1.2</version>
<type>jar</type> </dependency>
<scope>compile</scope> <!-- accès base de données -->
</dependency> <dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.8</version>
</dependency>
Page 85
Projet SpringMVC
[Link]
<web-app xmlns:xsi="" version="2.5">
<display-name>ENIG Web Application</display-name>
Rediriger toutes les requêtes vers
<context-param>
<param-name>contextConfigLocation</param-name> le dispatcher du SpringMVC
<param-value>/WEB-INF/[Link]</param-value>
</context-param>
<listener>
<listener-class>[Link]</listener-class>
</listener>
<servlet>
<servlet-name>servlet-dispatcher</servlet-name>
<servlet-class>[Link]</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/[Link]</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>servlet-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
Page 86
Projet SpringMVC
Le fichier [Link]
<beans xmlns=" . . . . ">
<context:component-scan base-package="[Link]" />
<mvc:annotation-driven />
<bean class="[Link]">
<property name="prefix"> <value> /vues/ </value> </property>
<property name="suffix"> <value>.jsp </value> </property>
</bean>
<bean id="dataSource" class="[Link]">
<property name="driverClassName" value="[Link]" />
<property name="url" value="jdbc:mysql://localhost:3306/enigdb1" />
<property name="username" value="root" />
Bean de connexion à la
<property name="password" value="" /> base des données
</bean>
</beans>
Page 87
Projet SpringMVC
Structure du
projet dans
eclipse
Page 88
Le package de base : [Link]
Page 89
Projet SpringMVC
L’entité Etudiant
public class Etudiant {
private Long cin;
private String nom;
private String prenom;
public Etudiant() {
}
public Etudiant(Long cin, String nom, String prenom) {
[Link] = cin;
[Link] = nom;
[Link] = prenom;
}
/*
* Les Getters et Setters
*/
}
Page 90
Projet SpringMVC
L’interface du Dao
package [Link];
public interface IEtudiantDao {
public void saveEtudiant(Etudiant e);
public void updateEtudiant(Etudiant e);
public void deleteEtudiant(int id);
public Etudiant getEtudiant(int id);
public List<Etudiant> listEtudiant();
}
Page 91
Projet SpringMVC
@Repository
public class EtudiantDao implements IEtudiantDao{
@Autowired
@Qualifier(value="dataSource")
DataSource data;
public void setData(DataSource data) { [Link] = data;}
public List<Etudiant> listEtudiant() {
List<Etudiant> listEtudiants = new ArrayList<Etudiant>();
try{
listEtudiant = String sql = "SELECT * FROM etudiant";
Connection conn = [Link]();
PreparedStatement ps = [Link](sql);
ResultSet rs = [Link]();
while([Link]()) {
Etudiant e1 = new Etudiant();
[Link]([Link]("id"));[Link]([Link]("prenom"));
[Link]([Link]("nom"));
[Link](e1);
}
}
catch(Exception e){ }
return listEtudiants;
}
Page 92
}
Projet SpringMVC
Le contrôleur
@Controller
public class AppControlleur {
@Autowired
IEtudiantDao dao;
public void setDao(IEtudiantDao dao) {
[Link] = dao;
}
@RequestMapping(value="/liste",method =[Link])
public String ListeETD1(Model model) {
List<Etudiant> liste1= [Link]();
[Link]("message", "Bienvenue à L'ENIG!");
[Link]("listeE", liste1);
return "Afficheliste";
}
}
Page 93
Projet SpringMVC
Page [Link]
<%@ page language="java" contentType="text/html" %>
<%@ taglib uri="[Link] prefix="c" %>
<!DOCTYPE html >
<html>
<head></head>
<body>
<c:forEach var="etd" items="${listeE}">
<p> Nom : ${[Link] } et Prenom : ${[Link] } </p>
</c:forEach>
</body>
</html>
Page 94
Programmation Evoluée
Chapitre 3
Page 95
Spring Data JPA
Spring Data est un robuste Framework de Spring qui se
compose de nombreux modules offrant d’accéder des
solutions de données alternatives comme : GemFire,
MongoDB, Neo4J,…, et JPA
Spring Data JPA offre une couche d’abstraction
supplémentaire par rapport à JPA
Se charge de l'implémentation des fonctionnalités les plus
courantes des DAO (annotés @Repository en Spring)
On se concentre sur l’essentiel : l’écriture des requêtes
Page 96
Spring Data JPA
SpringData with JPA
Page 97
Spring Data JPA
manipule
JPA Spring Data
Se base sur
Hibernate EclipseLink
JDBC
BDD
Page 98
Spring Data JPA
Pour l'intégrer, il suffit d'ajouter une dépendance dans Maven :
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>[Link]</version>
</dependency>
Principe de base : Pour écrire le DAO pour un type d’entités, il
faut étendre certaines interfaces fournies par Spring Data :
public interface EtudiantDao extends CrudRepository<Etudiant, Long> {
Nom de l'entité qu'on manipule
Type de l'identifiant de l'entité
Page 99
Spring Data JPA
Les différentes interfaces :
– Repository : vous ne ferez pas grand-chose avec,
hormis les méthodes que vous ajouterez,
– CrudRepository : vous aurez des fonctionnalités
CRUD de base,
– PagingAndSortingRepository : vous aurez en plus
des méthodes pour la pagination et le tri,
– JpaRepository : vous aurez en plus des méthodes
propres à JPA
Page 100
Spring Data JPA
Page 101
Spring Data JPA
A partir de Spring 5
Page 102
Spring Data JPA
A partir de Spring 5
Page 103
Spring Data JPA
Page 104
Spring Data JPA
A partir de Spring 5
Page 105
Spring Data JPA
Page 106
Spring Data JPA
A partir de Spring 5
Page 107
Spring Data JPA
Page 108
Spring Data JPA
@Entity
public class Etudiant implements Serializable{
@Id @GeneratedValue
private Long cin;
private String nom;
private String prenom;
public Etudiant() {
}
public Etudiant(Long cin, String nom, String prenom) {
[Link] = cin;
[Link] = nom;
[Link] = prenom;
}
/*
* Les Getters et Setters
*/
}
Page 109
Spring Data JPA
Exemple
@Repository Dao
public interface EtudiantDao extends CrudRepository<Etudiant, Long> {
}
Page 110
Spring Data JPA
Créer vos propres requêtes ???
Solution :
– DSL : les requêtes dérivées,
– @Query : JPA+SQL => JPQL
Page 111
DSL Queries
DSL = Domain Specific Language
Spring Data JPA DSL sont des mappages de requêtes basés sur
les noms de méthode dans le Repository
Le DSL se compose de mots-clés associés aux noms d'attribut
de colonne du domaine.
Les requêtes deviennent plus «anglaises»
public interface UserRepository extends JpaRepository <User, Long>{
List<User> findByLastname(String lastname);
}
Page 112
DSL Queries
Mot clé Exemple JPQL snippet
And findByLastnameAndFirstname … where [Link] = ?1 and
[Link] = ?2
Or findByLastnameOrFirstname … where [Link] = ?1 or
[Link] = ?2
Is findByFirstname … where [Link] = ?1
findByFirstnameIs
Between findByStartDateBetween … where [Link] between ?1 and ?2
LessThan findByAgeLessThan … where [Link] < ?1
LessThanEqual findByAgeLessThanEqual … where [Link] <= ?1
GreaterThan findByAgeGreaterThan … where [Link] > ?1
GreaterThanEqual findByAgeGreaterThanEqual … where [Link] >= ?1
After findByStartDateAfter … where [Link] > ?1
Before findByStartDateBefore … where [Link] < ?1
IsNull findByAgeIsNull … where [Link] is null
Page 113
DSL Queries
Mot clé Exemple JPQL snippet
IsNotNull, NotNull findByAgeNotNull … where [Link] not null
Like findByFirstnameLike … where [Link] like ?1
NotLike findByFirstnameNotLike … where [Link] not like ?1
StartingWith findByFirstnameStartingWith … where [Link] like
?1(parameter bound with appended %)
EndingWith findByFirstnameEndingWith … where [Link] like
?1(parameter bound with prepended %)
Containing findByFirstnameContaining … where [Link] like
?1(parameter bound wrapped in %)
OrderBy findByAgeOrderByLastnameDesc … where [Link] = ?1 order by
[Link] desc
Not findByLastnameNot … where [Link] <> ?1
In findByAgeIn(Collection<Age> ages) … where [Link] in ?1
NotIn findByAgeNotIn(Collection<Age> ages) … where [Link] not in ?1
Page 114
@Query => JPQL
@Query - Utilisez votre propre requête
Vous n'aimez pas la requête dérivée ou souhaitez faire
quelque chose de plus sophistiqué?
Utilisez la notation @Query pour fournir la vôtre
Prise en charge à la fois de JPA ou de SQL natif => JPQL
Fournit toujours une implémentation automatique du proxy
Page 115
@Query => JPQL
Page 116
Projet SpringMVC
avec Spring Data
Page 117
Les dépendances maven
Ajouter les dépendances du Spring Data et Hibernate ( n’oublier pas les
autres dépendances )
<!-- Ajout de Hibernate -->
<dependency>
<groupId>[Link]</groupId>
<artifactId>hibernate-core</artifactId>
<version>[Link]</version>
</dependency>
<dependency>
<groupId>[Link]</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>[Link]</version>
</dependency>
<!-- Spring Data -->
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>[Link]</version>
</dependency>
Page 118
Le Dispatcher
Ajouter le namespace du JPA dans la définition du contexte.
Page 119
Le Dispatcher
Ajouter les beans du JPA et Hibernate ( n’oublier pas les autres beans )
<jpa:repositories base-package="[Link]" />
<bean id="transactionManager"
class="[Link]">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="entityManagerFactory"
class="[Link]">
<property name="dataSource" ref="data" />
<property name="packagesToScan" value="[Link]" />
<property name="jpaVendorAdapter">
<bean class="[Link]">
<property name="generateDdl" value="true" />
</bean>
</property>
</bean>
Page 120
Les packages de base : [Link]
Page 121
Les packages de base : [Link]
Page 122
Structure du projet
Page 123
L’entité JPA
package [Link];
@Entity
public class Client {
@Id
@GeneratedValue(strategy=[Link])
private Integer id;
private String nom;
private String adresse;
/*
* Les Getters et Setters
*/
Page 124
Les interfaces
L’interface IDao
package [Link];
@Repository
public interface IDao
extends CrudRepository <Client, Integer> {
Page 125
Le contrôleur
@Controller
public class AppTest {
@Autowired
IDao dao;
public void setDao(IDao dao) {[Link] = dao;}
@RequestMapping(value="/home",method=[Link] )
public String getVoituresdispo(Model m) {
List<Client> liste=[Link]();
[Link]("liste2", liste);
return "home";
}
@RequestMapping(value="/ajoutclient",method=[Link] )
public String formAddClient(Model m) {
[Link]("clt",new Client());
return "ajoutClient";
}
@RequestMapping(value="/saveClient",method=[Link] )
public String saveclient(@ModelAttribute("clt") Client clt, Model m) {
[Link](clt);
return "redirect:/home";
}
Page 126
}
Exercice
On désire développer une application Web de
gestion de stock d’un supermarché.
Cette application gère deux classes de base :
Produit et Magasin.
– Un produit est caractérisé par son numéro, son prix
d’achat, son prix de vente, le nombre d’exemplaires
en stock, sa description, et le magasin où il est
stocké.
– Un magasin est caractérisé par son nom, son lieu.
Page 127