Introduction Spring MVC
Introduction Spring MVC
M G ib
Geib
Cedric Dumoulin
Documentation
[Link]
htt // t ti i / i /d / t/ i
ng‐framework‐reference/html/[Link]
Tutorial
[Link]
introduction spring mvc framework/
introduction‐spring‐mvc‐framework/
Download Spring‐framework
[Link]
htt // i / i
framework#download
Utiliser 3.1.3
313
Le cœur de l’environnement Spring est un « conteneur léger »
C’est le Design
g Pattern de l’Inversion du Contrôle : IoC
Exemple simplifié:
class Personne { String nom; Voiture car; }
Avec les classes:
class Voiture {String nom;}
et la description de contexte Spring:
<beans>
<bean id=
id=" user " class=
class=" Personne ">>
<property name=" nom " value=" jean "/>
<property name= " car " ref= "vehicule "/>
</bean>
<bean id=" vehicule " class=" Voiture ">
<property name=" nom " value=" megane "/>
</bean>
</beans>
Personne Voiture
user nom:jean
j vehicule
nom:megane
car:
SpringMVC est un framework de présentation,
pour application WEB, suivant le modèle MVC,
et fondé sur le conteneur léger de SPRING
U application
Une li ti 3ti3tier avec MVC
MVC:
La vision de SpringMVC
La [Link]
g p g p est le p
point d’entrée
générique qui délègue les requêtes à des Controller
Un [Link] prend en charge une requête,
et utilise la couche métier pour y répondre
répondre.
Un Controller fabrique un modèle sous la forme d’une [Link] contenant les
éléments de la réponse.
Un Controller
C choisit une [Link]
f qui sera
paramétrée par la Map pour donner la page qui sera affichée.
Spring 3.x
Controller Spring 3
Spring 3 simplifie la création des contrôleurs:
annotations @Controller
ll et @RequestMapping
Pas d’interface à implémenter
Le contrôleur le pplus simple:
p
une classe annoté @Controller
plus une méthode annoté @RequestMapping
Cette méthode reçoit la requête, doit la traiter (c
(c’est
est à dire fabriquer les
données de réponse grâce à la couche métier) et retourner un objet
ModelAndView
L’URL associée est spécifié dans le paramètre
@Controller
public class HelloWorldController {
@RequestMapping("/helloWorld")
q pp g( )
public ModelAndView helloWorld() {
ModelAndView mav = new ModelAndView();
[Link]("helloWorld");
[Link]("date",
j , new Date());
())
return mav;
}
}
URL DispatcherServlet
HandlerMapping Metier
Choix d’un contrôleur
en fonction de l’URL
MonControleur
HttpServletRequest
handleRequest ModelAndView =
N
Nom d
de vue + Model
M d l
Choix d
d’une
une vue
ViewResolver
Page
HTML Vue Model
Contrôleur Spring 3
@Controller @Controller
public class Affichage
p g { Pas d’interface
à implémenter
// un groupe de personnes fourni par le contexte de l'application
private Groupe groupe;
// gestion de la requête
@RequestMapping("/afficher")
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception {
Nom de la vue à utiliser
ModelAndView mav = new ModelAndView(); pour générer la page
[Link]("vuemembres");
[Link]("groupe", groupe);
return mav; Ajoutt d
Aj du groupe
} au modèle
Exemple: 3 – une page JSP-JSTL pour afficher les membres
<html>
<head>
<title>Affichage</title>
On retrouve
</head>
<body> le modèle
<h2>Groupe</h2>
<table border="1">
<tr>
<th colspan
colspan="3"
3 align
align="center">Membres
center >Membres du groupe</th>
</tr>
<tr>
<c:forEach var="personne" items="${[Link]}">
<td>${personne}</td>
</c:forEach>
</tr>
</table>
<a href="<c:url value="/[Link]"/>">Ajout</a>
</body>
</html> Fi hi //views/[Link]
Fichier i / b j
Exemple: 4: définir l’application WEB:
Injection de dépendance
Pierre
groupe:
g p Paul
au
Jacques
Nom de la DispatcherServlet
Spring 3.x
Exemple
p : 5 - le fichier WEB-INF/[Link]
<beans>
<!-- le controleur -->
<bean id="AffichageController" class="[Link]">
<
<property
t name="groupe"
" " ref="groupe"/>
f " "/>
</bean> La dépendance
pour injecter le groupe
<!– l’instance du metier
<b
<bean id
id="groupe"
" " class="[Link]"
l " ti G "
<property name="membres">
<list>
<value>Paul</value>
< al e>Mélanie</ al e>
<value>Mélanie</value>
<value>Jacques</value>
</list>
</property>
</bean>
Exemple: 6 – les mappings
Il faut
f t utiliser
tili un ViewResolver
Vi R l
<property name="viewClass"
value="[Link]"
g p gf />
/
<property name="prefix" value="/WEB‐INF/vues/" />
<property name="suffix" value=".jsp" /> Le nom de la vue
</bean>
est utilisé pour former
le nom de la jsp
membres
WEB-INF
[Link]
[Link]
e b es se e
vues
[Link]
j p
src
metier
L’appli Web avec Spring: [Link]
web
[Link]
lib
[Link]
[Link]
[Link]
[Link]
ll ti j
classes
Lancement: [Link]
On peut sortir le mapping des vues du fichier de configuration
Fichier /WEB-INF/vues/[Link]
<?xml version=
version="1
1.0
0" encoding=
encoding="ISO-8859-1"?>
ISO 8859 1 ?>
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"[Link]
<web-app>
<!-- le chargeur du contexte de l'application -->
<listener>
<listener-class>
[Link]
</listener-class>
</listener>
...
</web-app>
membres
[Link]
WEB-INF
[Link]
[Link]
[Link]
vues
[Link]
L’appli Web avec Spring: [Link]
src
metier
[Link]
web
[Link]
lib
[Link]
spring jar
[Link]
[Link]
commons-collections
commons [Link]
jar
classes
Spring 3.x
Formulaire
Met en œuvre:
une page web b (ex:
( jsp)
j )
un contrôleur avec jusque deux méthodes pour traiter
les requêtes get et post
un objet command pour passer les données entre le
formulaire et le contrôleur
Une méthode pour initialiser l’objet command
Spring 3.x
GET Request
Utilise
@RequestMapping(method = [Link])
protected String processPost(…)
Page Metier
Objet
HTML ModelAndView
Initialiser l’objet
j de Command
Par une méthode annoté @ModelAttribute
@ModelAttribute("commandAjout")
public userInfoData initFormObject( HttpServletRequest
HttpSer letRequest request) {
CommandAjout command = new CommandAjout();
return command ;
}
@Controller @RequestMapping("ajouter")
public class AjoutController {
private Groupe groupe;
@RequestMapping(method
q pp g = [Link])
q
protected Object processGet(ModelMap model) {
récupère le modèle implicite
// Create the command used to fill the jsp form
CommandAjout cmd = new CommandAjout(); crée l’objet command
[Link]("Entrez un nom");
// Add it to the implicit model
[Link]("commandAjout", cmd); la vue affichant le formulaire
// return the logical name of the view used to render the form.
return "formulaire";
} récupère
é è l’l’objet
bj t command
d
à partir du modèle implicite
@RequestMapping(method = [Link])
protected String processPost( @ModelAttribute("commandAjout") CommandAjout commandAjout,
BindingResult result, SessionStatus status ) throws Exception
p {
if( [Link]()) {
return "formulaire";} le résultat du bind
// Add new membre
[Link]([Link]());
status setComplete();
[Link](); indique la fin de la session
return "confirmation"; nettoie les attributs du modèle
}
}
Spring 3.x
[Link]
<body><h3>Formulaire Ajouter un membre </h3> nom de l’objet dans le modèle
<form:form commandName="commandAjout">
<table>
<tr> nom de propriete dans l’objet
<td>Nouveau Membre</td>
<td><form:input path="nouveauMembre" /></td>
<%-- Show errors for name field --%>
<td><form:errors path="nouveauMembre" /></td>
</tr>
<tr>
<td colspan="3"><input type="submit" value="Envoyer" /></td>
</tr>
</table>
</form:form>
confirmation jsp
[Link]
<body>
<h3>Confirmation de l'ajout</h3> valeur de la propriété
<table border="1">
<tr>
<td>Nouveau Membre </td>
<td>${[Link]}</td>
</tr>
</table>
< href="<c:url
<a h f "< l value="/[Link]"/>">Retour</a>
l "/ ffi h ht l"/>">R t </ >
</body>
Spring 3.x
Il ne faut plus déclarer les contrôleurs. Ils seront découvert grâce aux annotations
</beans>
Spécifie le package à scanner
membres
[Link]
WEB-INF
[Link]
[Link]
applicationContext xml
[Link]
vues
[Link]
[Link]
[Link]
L’appli Web avec Spring: [Link]
src
metier
[Link]
web
[Link]
[Link]
[Link]
lib
[Link]
[Link]
[Link]
[Link]
classes
On peut terminer par mettre un « welcome file » dans le [Link]
<welcome-file-list>
<welcome-file>[Link]</welcome-file>
</welcome-file-list>
fichier [Link]:
<%@ page language="java" pageEncoding="ISO-8859-1"
contentType text/html;charset ISO 8859 1 %>
contentType="text/html;charset=ISO-8859-1"%>
<%@ taglib uri="/WEB-INF/[Link]" prefix="c" %>
<c:redirect url="/[Link]"/>
- Dans
D [Link],
fi ti j pour retourner
t à lla liliste
t
<a href="<c:url value="/[Link]"/>">Retour</a>
membres
[Link]
[Link]
WEB-INF
[Link]
[Link]
b l t l
L’appli est terminée [Link]
et se lance par:
vues
[Link] [Link]
[Link]
[Link]
[Link]
fi ti j
src
metier
[Link]
p j
web
[Link]
[Link]
C
[Link]
dAj t j
lib
[Link]
[Link]
j
[Link]
[Link]
classes
Spring 3
Spring 3.x
Erreur de conversion
@RequestMapping(method = [Link])
protected String onSubmit(
@ModelAttribute("commandAjout") CommandAjout commandAjout,
BindingResult result,
result SessionStatus status ) throws Exception {
if( [Link]()) {
return "formulaire"; retourne au formulaire en cas d’erreurs
}
[Link]([Link]());
[Link]();
return "confirmation";
confirmation ; efface la session si ok
}
Validation
Doit se faire explicitement
@Controller @RequestMapping("ajouter")
@RequestMapping( ajouter )
public class AjoutController {
@RequestMapping(method = [Link])
protected String onSubmit(
@ModelAttribute("commandAjout")
@ModelAttribute( commandAjout ) CommandAjout commandAjout,
commandAjout
BindingResult result, SessionStatus status ) throws Exception {
// validation
validator validate(commandAjout result);
[Link](commandAjout,
if( [Link]()) {
return "formulaire";
appel la validation. Utilise le BindResult
}
…
Un validator pour détecter les saisies vide du nouveau membre
package web;
import [Link];
}
[Link]
void reject(String errorCode)
Register a global error for the entire target object, using the given error description.
Validation
Peut aussi utiliser le standard
’JSR‐303
’JSR V lid t ’
Validator’
Utilise le tag @Valid et des validators
Nécessite
Né i une implémentation
i lé i d du standard
d d
ex: Hibernate Validate
<html>
<head>
<title>formulaire Ajout</title>
</head>
<body>
<h3>Formulaire Ajouter un membre</h3>
<form:form commandName="commandAjout" acceptCharset="UTF-8">
<body>
<form:form commandName="commandAjout" acceptCharset="UTF-8">
Le fichier [Link]
messages properties :
Il p
peut y avoir un fichier de messages
g p pour chaque
q langue.
g
Suffixer le nom par le local et le country :
•fr_FR
•en_US
•de_DE
Le framework choisit le fichier en fonction des préférences utilisateur
<!-- le fichier des messages -->
<b
<bean id "
id="messageSource"
S "
class="[Link]">
<property name="basename">
<value>messages</value>
</property>
</bean>
messages_fr_FR.properties
messages
g _en_US.properties
p p
[Link]=Name is mandatory
[Link]=Duplicate name
membres
[Link]
[Link]
WEB-INF
[Link]
[Link]
[Link]
vues
[Link]
[Link]
L’appli Web avec Spring: [Link]
[Link]
src
metier
[Link]
web
[Link]
g j
[Link]
[Link]
[Link]
lib
[Link]
[Link]
[Link]
[Link]
j
classes
[Link]
Accéder à un objet JNDI ou EJB
L’objet doit exister dans un autre container
On injecte le bean
ex: injecter
j p g
un bean dans Spring
[Link]
<beans xmlns=
xmlns="[Link]
[Link]
springframework org/schema/beans"
xmlns:xsi="[Link]
xmlns:jee="[Link]
xsi:schemaLocation="[Link]
[Link] springframework org/schema/beans/spring-beans-2 5 xsd
[Link]
[Link]
[Link]
<bean id=
id="catalogController"
catalogController class=
class="ipint
[Link]
mysite CatalogController">
>
<property name="catalog" ref="catalogId"/>
</bean> injection
<jee:local-slsb id=
id="myComponent"
myComponent jndi-name=
jndi-name="ejb/myBean"
ejb/myBean
business-interface="[Link]"/>
<bean id="myController" class="[Link]">
<property name
name="myComponent"
myComponent ref
ref="myComponent"/>
myComponent />
</bean>
Documentation
Spring
[Link]
tutoriall
[Link]
[Link]
tutorial; a adapter pour la dernière version
article
[Link]
synthese
y de Spring
p g
documentation
[Link]
la reference
pdf : ([Link]
Exemples
Exemples fournies avec Spring
\spring‐framework‐2.5.x\samples
\ i f k \ l
Utiliser Spring 3
Nécessite les jars
((situés dans spring3.x/dist)
p g3 / )
[Link]
[Link]
[Link]
[Link]
[Link]
org springframework core
[Link]
[Link]
Download:
[Link]
Partie 2
La navigation dans une application MVC
[Link]
public class SaisieNom extends SimpleFormController {
…
Saisie protected ModelAndView onSubmit() {
Nom
Nom return new ModelAndView("redirectionSaisiePrenom" );
}
Submit Controller }
[Link]
<bean id="redirectionSaisiePrenom"
[Link]=[Link]
Redirection class="[Link]">
[Link]=/[Link]
<property name="url"><value>/[Link]</value></property>
</bean>
/b
Action1
Affi h
Afficher
Methode
Action2 Action 1
Saisir
Methode
Action 2
suite
MultiActionControleur (Spring3)
( p g )
Classe annoté
@Controller et @RequestMapping(
@RequestMapping("/url")
/url )
@Controller
@RequestMapping("/appointments")
q pp g / pp
public class AppointmentsController {
<bean id="MonController"
class="[Link]">
<property name="methodNameResolver">
<ref local="MaMethodNameResolver"/>
</property>
</bean>
<bean id="MaMethodNameResolver
MaMethodNameResolver"
class="[Link]">
<property name="defaultMethodName"><value>action1</value></property>
<property name="methodParamNames">
<list>
<value>action2</value>
<value>action3</value>
</list>
</property>
</bean>
Spring 2
package web;
import [Link];
import [Link];
Get
Liste à sélection
des noms des
personnes
Methode
Voir Détails affichageListe
Ajout Methode
afficherDétails
MultiActionController
Détails
d’une Methode
Personne ajoutPersonne
retour
Redirection
Formulaire de
saisie des infos
d’une personne Saisie
SimpleFormController
Redirection Retour Personne
Un exemple complet: Gestion des réservations de vol par des personnes
Personne Vol
nom id
prenom * * depart - Consulter la liste des personnes et
arrivee avoir la possibilité de saisir une
nouvelle personne
* * - Consulter la liste des vols et avoir la
possibilité de saisir un nouveau vol
FabPersonne FabVol - Réserver un vol pour une personne
getNoms() getIds()
addPersonne() addVol()
getPersonne() getVol()
On décide du modèle MVC de l’application:
Retour R t
Retour
Réservation
Liste à sélection Liste à sélection
des noms des des ids des
personnes vols
Confirmer Annuler
Le fichier [Link] va configurer toute l’application.
<bean id=
id="ReservationController"
ReservationController
class="[Link]">
<property name="methodNameResolver">
<ref local="ReservationMethodNameResolver"/>
</property> 3- Trois contrôleurs sont des
<property name="fabVol"> MultiActionController. On leur
<ref bean="fabriqueVol"/> injecte le métier nécessaire.
</property>
<property name=
name="fabPersonne">
fabPersonne >
<ref bean="fabriquePersonne"/>
</property>
</bean>
4- On définit les actions reconnues par les MultiActionController
<bean id="ListeMethodNameResolver"
class="[Link]">
<property name="defaultMethodName"><value>list</value></property>
<property name="methodParamNames">
<list>
<value>ajout</value>
l j / l
<value>voir</value>
</list>
</property>
</bean>
/b
<bean id="ReservationMethodNameResolver"
class="[Link]">
<property name="defaultMethodName"><value>list</value></property>
<propertyt name="methodParamNames">
" th dP N "
<list>
<value>choixVol</value>
<value>choixPersonne</value>
<value>voirVol</value>
l iV l / l
<value>voirPersonne</value>
<value>confirmer</value>
<value>annuler</value>
</list>
/li t
</property>
</bean>
<bean id="SaisiePersonneController" <bean id="SaisieVolController"
class="[Link]">
l " bS i i P C t ll " class="[Link]">
l " b S i i V lC t ll "
<property name="sessionForm"> <property name="sessionForm">
<value>true</value> <value>true</value>
</property> </property>
<property t name="formView">
"f Vi " <propertyt name="formView">
"f Vi "
<value>saisirPersonne</value> <value>saisirVol</value>
</property> </property>
<property name="validator"> <property name="validator">
<reff bean="ValidatePersonne"/>
b "V lid t P "/ <reff bean="ValidateVol"/>
b "V lid t V l"/
</property> </property>
<property name="commandName"> <property name="commandName">
<value>personne</value> <value>vol</value>
</property>
/ t </property>
/ t
<property name="fabPersonne"> <property name="fabVol">
<ref bean="fabriquePersonne"/> <ref bean="fabriqueVol"/>
</property> </property>
</bean>
/b </bean>
/b
<bean id=
id="fabriquePersonne"
fabriquePersonne <bean id=
id="fabriqueVol"
fabriqueVol
class="[Link]"> class="[Link]">
<property name="personnes"> <property name="vols">
<map> <map>
<entry> <entry>
<key> <value>Geib</value></key> <key> <value>AF322</value></key>
<ref local="PersonneGeib" /> <ref local="volAF322" />
</entry> </entry>
<entry> <key> <value>Tison</value></key> <entry> <key> <value>AF645</value></key>
<ref local="PersonneTison" /> <ref local="volAF645" />
</entry> </entry>
</map> </map>
</property> </property>
</bean> </bean>
<bean id="PersonneGeib" class="[Link]">
7- Pour finir on définit les <property name="nom" value="Geib" />
p p y name="prenom"
<property p value="Jean-Marc" />
objets qui sont placés </bean>
dans les fabriques
<bean id="PersonneTison" class="[Link]">
<property
p p y name="nom" value="Tison" />
<property name="prenom" value="Sophie" />
</bean>
</h3></body>
</html>
Plugin Eclipse pour Spring
[Link] org/project/wiki/SpringideInstall
[Link]
Bibliography
Spring 3.x tutorials
[Link]
htt // i di t/ i / i /i d ht l
[Link]
[Link]
h // h id / i l/S i
Tutorial‐Setting‐Up‐Configuring‐The‐Environment
Download
[Link]
h // i /d l d/ i
Required
q Jar files
For a typical web application you need the following
module jars:
[Link]
[Link]
org springframework asm
[Link]
[Link]
[Link]
[Link]
[Link]
Since most web applications use logging and basic AOP
features, you need the following required third‐party
offerings:
commons‐logging‐1.1.1
l i
Notes sur les annotations
Un bean ne peut pas etre declare a la fois par @annotated
et par <bean></bean>. Si on utilise les 2, il est declare 2
f
fois, et le
l conteneur renvoie une erreur ‘already
‘ l d mapped d’
Si on utilise SimpleUrlHandlerMapping (dans le fichier de
config), il capte tous les mapping, et les mapping fait dans
les controlleurs sont ignorés.
@Inject – vient de JSR 330; permet de faire de l’injection;
fonctionne avec Spring 3; Inject le bean de type
correspondant; Ne permet pas de specifier le nom du bean
;
@Autowire
A i – identique
id i a @Inject,
I j mais
i vient
i d
de Spring.
S i
Validation – La validation peut‐être effectue avec ’JSR‐303
Validator’;; Utilise le tag @Valid
Validator
Installation
Spring comprend un ensemble de jars de base, necessaire a
l’execution.
Il est aussi possible de télécharger un environement de
dévelopement basé sur Eclipse