© Khalid HADDOUTI
SOMMAIRE
INTRODUCTION 3
CYCLE DE VIE D’UNE REQUETE HTTP 7
CONFIGURATION SPRING MVC 11
DEFINITION DES CONTROLLEURS 14
GESTION DES VUES 18
INTEGRATION DE TILES 23
GESTION DES FORMULAIRES 27
VALIDATION DES FORMULAIRES ET JSR-303 33
GESTION DES ERREURS 43
REST / AJAX 49
© Khalid HADDOUTI 2
3
© Khalid HADDOUTI
INTRODUCTION
Principe MVC
+ Spring MVC est un framework de présentation respectant
le principe Model View Controller
© Khalid HADDOUTI 4
INTRODUCTION
Présentation Spring MVC (1/2)
+ Depuis la version 2.5, Spring MVC se configure via les
annotations
Nom officiel Spring @MVC.
Utilisation XML possible : Spring <MVC/>.
+ La hiérarchie de contrôleurs est dépréciée depuis Spring
3.0
Utilisation de POJO pour les contrôleurs.
+ Cette formation ne traite que des annotations
© Khalid HADDOUTI 5
INTRODUCTION
Présentation Spring MVC (2/2)
+ Spring MVC repose un modèle simple Requête / Réponse
par rapport à un modèle évènementiel
JSF– cycle de vie des données très complexe.
+ Spring MVC intègre un grand nombre de technologies
pour la vue
JSP, FreeMarker, Velocity, Excel, PDF, etc…
+ Spring MVC fournit une librairie de tags pour faciliter le
développement des JSPs
© Khalid HADDOUTI 6
7
© Khalid HADDOUTI
CYCLE DE VIE D’UNE REQUETE HTTP
Présentation (1/3)
© Khalid HADDOUTI 8
CYCLE DE VIE D’UNE REQUETE HTTP
Présentation (2/3)
+ Spring MVC s’appui sur les URLs pour déterminer le
mapping à appliquer
Une URL permet l'appel d'une méthode via l'interface
HandlerMapping.
BeanNameUrlHandlerMapping est la classe par défaut.
+ Les intercepteurs agissent comme des filtres servlet
Configuration XML ou par annotations.
Sont gérés au sein du contexte Spring.
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**" />
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"/>
</mvc:interceptor>
<mvc:interceptors>
© Khalid HADDOUTI 9
CYCLE DE VIE D’UNE REQUETE HTTP
Présentation (3/3)
+ Spring MVC centralise la gestion des exceptions
Par annotation @ExceptionHandler
Par des beans implémentant l'interface HandlerExceptionResolver
Permet l’exécution d’actions spécifiques et la redirection vers les
vues
+ L’inteface ViewResolver détermine la vue à partir d’un
nom logique
InternalResourceViewResolver – redirection vers des JSPs et
Servlets.
+ L’interface View prépare les données du modèle et
effectue le rendue selon la technologie configurée
© Khalid HADDOUTI 10
11
© Khalid HADDOUTI
CONFIGURATION SPRING MVC
Dispatcher Servlet
+ Configuration de la servlet dans le fichier web.xml
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
Point d’entrée du framework Spring MVC
Dispatcher est le contexte web de l’application
© Khalid HADDOUTI 12
CONFIGURATION SPRING MVC
Le contexte servlet
+ La configuration MVC est contenue dans un fichier
spécifique
Par défaut, portant le nom de <servlet-name>-servlet.xml
Chargé depuis le répertoire WEB-INF
+ Le nom et le chemin vers le fichier est personnalisable
<servlet>
…
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/config/web-application-config.xml</param-value>
</init-param>
</servlet>
+ Contient les définitions de beans relatives à la couche
MVC
Intercepteurs, résolution de la Locale, les fichiers de ressources
des messages à afficher, etc…
© Khalid HADDOUTI 13
CONFIGURATION SPRING MVC
Le contexte applicatif
+ Le contexte applicatif Spring est chargé via un listener
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/config/web-application-config.xml</param-value>
</context-param>
Par défaut, Spring MVC charge le fichier WEB-
INF/applicationContext.xml
La balise context-param permet de spécifier le(s) fichier(s) de
contexte à charger
+ Contient les définitions de beans hors contexte MVC
Couche de service, beans métiers, datasources, etc…
© Khalid HADDOUTI 14
CONFIGURATION SPRING MVC
La hiérarchie des contextes (1/2)
+ Le contexte servlet et applicatif forment une hiérarchie de
contextes
© Khalid HADDOUTI 15
CONFIGURATION SPRING MVC
La hiérarchie des contextes (2/2)
+ La hiérarchie des contextes a des impacts sur la visibilité
des beans
Les beans définis au sein du contexte servlet voient ceux du
contexte racine.
L'inverse n'est pas applicable.
+ Un bean service peut être injecté au sein d'un bean
contrôlleur
Il est par contre impossible d'injecter un bean contrôlleur au sein
d'un bean service.
+ Le partage du contexte racine entre plusieurs
dispatcherServlet est envisageable
Un dispatcherServlet pour les services REST.
© Khalid HADDOUTI 16
CONFIGURATION SPRING MVC
Namespace « mvc » (1/3)
+ Simplifie la configuration de Spring MVC
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
Déclaration dans le fichier de contexte servlet
+ Configuration du modèle de programmation des contrôleurs
<mvc:annotation-driven/>
Définition par défaut des HandlerMapping et HandlerAdapter.
Configuration via @RequestMapping
Support de la validation avec @Valid (dépendance sur JSR-303).
Support pour la lecture et écriture XML/JSON
@RequestBody et @ResponseBody.
© Khalid HADDOUTI 17
CONFIGURATION SPRING MVC
Namespace « mvc » (2/3)
+ Mapping et mis en cache des ressources
Images, CSS, javascript, etc…
<mvc:resources location="classpath:/images/" mapping="/images/**" cache-period="31556926"/>
“location” indique l’emplacement physique des ressources.
"mapping" indique l'URL à associer.
"cache-period" définit la durée de mis en cache (client) des ressources.
Exemple d'URL:
http://localhost:8080/springmvc/images/internet.png
+ Redirection vers une vue sans passer par un contrôlleur
<mvc:view-controller path="/" view-name="index"/>
Affichage par défaut de la page d'index de l'application
© Khalid HADDOUTI 18
CONFIGURATION SPRING MVC
Namespace « mvc » (3/3)
+ Définition d'intercepteurs personnalisés
<mvc:interceptors>
<bean class="com.m2i.spring.mvc.view.interceptor.MyInterceptorImpl"/>
</mvc:interceptors>
Intercepteur appélée pour toutes les requêtes
<mvc:interceptors>
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" />
<mvc:interceptor>
<mvc:mapping path="/secure/*" />
<bean class="com.m2i.spring.mvc.view.interceptor.MyInterceptorImpl" />
</mvc:interceptor>
</mvc:interceptors>
Intercepteur "MyInterceptor" appelée pour les URLs contant
"/secure/".
© Khalid HADDOUTI 19
20
© Khalid HADDOUTI
DEFINITION DES CONTRÔLEURS
Les contrôleurs et la gestion du mapping (1/2)
+ Un contrôleur est une classe java (POJO) annotée par
@Controller
Point d’entrée pour les traitements
Effectue la redirection vers la vue en fonction du résultat.
+ Activation des annotations
<context:component-scan base-package="com.m2i.spring.mvc.view" />
<mvc:annotation-driven />
+ L’annotation RequestMapping effectue le mapping entre
l’URL et la méthode à exécuter
@Controller
public class UserController {
@RequestMapping("/listUsers")
public String list () {
// Exécutions des traitements
return "next";
}
}
Exemple d'URL : http://localhost:8080/mvcapp/listUsers
© Khalid HADDOUTI 21
DEFINITION DES CONTRÔLEURS
Les contrôleurs et la gestion du mapping (2/2)
+ @RequestMapping peut etre annotée sur la classe
En complément de l’annotation sur la méthode.
Permet une meilleur granularité du mapping.
@Controller
@RequestMapping(value="/users")
public class UtilisateurController {
@RequestMapping(value="/listUsers", method=RequestMethod.GET)
public String list() {
// Exécutions des traitements
return "next";
}
Exemple d’URL : http://localhost:8080/mvcapp/users/listUsers
L’emploi de jokers est possible : /users/*/**
+ L’attribut method restreint le verbe HTTP pris en compte
par le mapping
© Khalid HADDOUTI 22
DEFINITION DES CONTRÔLEURS
Paramètres des requêtes (1/3)
+ Les méthodes ont besoin de réceptionner les paramètres
de la requête
+ Spring MVC assigne les paramètres aux arguments de la
méthode via les annotations
Exemple d’URL :
http://localhost:8080/mvcapp/users/delete?id=234
@RequestMapping(value="/delete", method=RequestMethod.GET)
public String deleteUtilisateur( @RequestParam("id") int id) {
// Exécution des traitements
return "deleteConfirmed";
}
@RequestParam extrait le paramètre “id” de la requête.
Le transtypage est effectué automatiquement.
© Khalid HADDOUTI 23
DEFINITION DES CONTRÔLEURS
Paramètres des requêtes (2/3)
+ Spring MVC extrait également les paramètres suivant le
principe de l’UriTemplate
Concept partagé par beaucoup de frameworks
Non spécifique Spring MVC
+ Emploi du token {…} et de l’annotation @PathVariable
Exemple d’URL :
http://localhost:8080/mvcapp/users/delete/234
@RequestMapping(value="/delete/{userId}", method=RequestMethod.GET)
public String deleteUtilisateur( @PathVariable("userId") long id) {
// Exécution des traitements
return "deleteConfirmed";
}
Pas de nom de variable véhiculé dans la requête
© Khalid HADDOUTI 24
DEFINITION DES CONTRÔLEURS
Paramètres des requêtes (3/3)
+ La signature des méthodes n’est pas figée
Permet une grande souplesse dans la définition des arguments
@RequestMapping("/info")
public void info(@RequestHeader("Accept-Encoding") String encoding,
@RequestHeader("Keep-Alive") long keepAlive) {
...
}
Exemple appliqué sur les entêtes HTTP
+ Synthèse des annotations Spring MVC
Annotation Description
@PathVariable Récupère une partie de l’url et la place dans le paramètre annoté.
@RequestParam Récupère un paramètre de requête web (GET ou POST) .
@RequestHeader Récupère la valeur d’une entête HTTP.
@RequestBody Accède au corps de la requête.
@PathVariable Récupère un paramètre dans le cadre d’une URL de la forme UriTemplate
© Khalid HADDOUTI 25
26
© Khalid HADDOUTI
GESTION DES VUES
L’interface ViewResolver (1/2)
+ Les contrôleurs sont chargés de retourner le nom logique
d’une vue
En fonction du résultat du traitement.
La valeur est transmise au DispatcherServlet.
+ Les contrôleurs peuvent également retourner “void” ou
“null”
Définition d’un bean d’interface RequestToViewNameTranslator.
Spring fournit l’implémentation
DefaultRequestToViewNameTranslator.
Résolution des noms logiques à partir de l’URL.
+ Les contrôleurs sont capables de retourner une valeur
concrête
new JstlView("/WEB-INF/users/list.jsp");
Cas d’utilisation à proscrire car non flexible.
© Khalid HADDOUTI 27
GESTION DES VUES
L’interface ViewResolver (2/2)
+ Le DispatcherServlet délègue aux implémentations de
l’interface ViewResolver la résolutions des noms de vues
Un identifiant logique est transmis au gestionnaire de vue.
+ Par défaut, Spring MVC gère les noms logiques comme
des chemins relatifs à l'application Web
+ Définir un bean pour modifier le comportement par défaut
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
InternalResourceViewResolver est utilisé pour les JSPs.
Les préfixe et suffixe sont paramétrés.
La combinaison résultante forme un chemin vers la vue.
© Khalid HADDOUTI 28
GESTION DES VUES
Les types de retours (1/2)
+ Spring MVC fournit différents moyens de sélection de la
vue
Plusieurs type de retours de méthode depuis le contrôleur.
+ Renvoi uniquement du nom logique la vue
@RequestMapping("/helloWorld")
public String helloWorld() {
return "helloWorld";
}
Pas de données à afficher dans la vue.
+ Renvoi d'un objet encapsulant les données et le nom de la
vue
@RequestMapping("/helloWorld")
public ModelAndView helloWorld() {
ModelAndView mav = new ModelAndView();
mav.setViewName("helloWorld");
mav.addObject("message", "Hello World!");
return mav;
}
© Khalid HADDOUTI 29
GESTION DES VUES
Les types de retours (2/2)
+ Synthèse sur quelques types deretours
Classe/Interface Description
ModelAndView Encapsule le nom logique de la vue et sonmodèle.
Model Encapsule le modèle. Retour sur la vuecourante.
View (Interface) Retourne la vue préparée par l'application.
- Template Freemarker : FreeMarkerView
- Redirection vers une ressource externe (code HTTP 302) : RedirectView
String Fournit le nom logique.
© Khalid HADDOUTI 30
GESTION DES VUES
Les librairies de tag
+ Les taglibs permettent notamment de gérer les données
issues du modèle
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
Déclaration des taglib en début de la JSP.
+ Affichage d'une liste de personnes
@RequestMapping(method=RequestMethod.GET,value="list")
public ModelAndView listPeople() {
ModelAndView mav = new ModelAndView();
List<Person> people = personDao.getPeople();
mav.addObject("people",people);
mav.setViewName("list");
return mav;
}
Le contrôleur
<c:forEach items="${people}" var="person">
<a href="edit?id=${person.id}">${person.id} - ${person.firstName} ${person.lastName}</a>
<br/>
</c:forEach>
Extrait du contenu de la JSP
© Khalid HADDOUTI 31
GESTION DES VUES
Conclusion
+ Diagramme des flux
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
© Khalid HADDOUTI 32
33
© Khalid HADDOUTI
INTÉGRATION DE TILES
Présentation
+ Tiles est un moteur de template pour vues JSPs
Définition de fragments JSP (ou Tiles).
Assemblage de ces fragments pour obtenir une page complète.
+ Favorise la réutilisation des gabarits
+ Renforce le caractère homogène de l'identité visuelle
d'une application web
+ Framework Apache actuellement en version 3.0
Site officiel : http://tiles.apache.org/
Anciennement composant intégré à Strusts.
+ Ne pas utiliser la version 2.1.1 ou 2.1.0 à cause d’un bug
de sécurité
© Khalid HADDOUTI 34
INTÉGRATION DE TILES
Configuration dans Spring MVC (1/3)
+ Définitions des chemins vers les gabarits
<bean id="tilesConfigurer"
class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
<property name="definitions">
<list>
<value>/WEB-INF/defs/produit.xml</value>
<value>/WEB-INF/defs/login.xml</value>
<value>/WEB-INF/defs/administrateur.xml</value>
<value>/WEB-INF/defs/client.xml</value>
<value>/WEB-INF/defs/fournisseur.xml</value>
</list>
</property>
</bean>
Le bean tilesConfigurer définit un conteneur Tiles.
A configurer dans le fichier Spring de contexte servlet.
+ Un résolveur de vue spécifique Tiles doit être spécifié
<bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.tiles2.TilesView"/>
</bean>
Récupération d’un des fichiers de définitions en fonction du nom.
© Khalid HADDOUTI 35
INTÉGRATION DE TILES
Configuration dans Spring MVC (2/3)
+ Les gabarits sont définis dans les fichiers XML
<definition name="base.definition" template="/WEB-INF/jsp/layout.jsp">
<put-attribute name="title" value="" />
<put-attribute name="header" value="/WEB-INF/jsp/header.jsp" />
<put-attribute name="menu" value="/WEB-INF/jsp/menu.jsp" />
<put-attribute name="body" value="" />
<put-attribute name="footer" value="/WEB-INF/jsp/footer.jsp" />
</definition>
<definition name="clients" extends="base.definition">
<put-attribute name="title" value="Clients" />
<put-attribute name="body" value="/WEB-INF/jsp/clients.jsp" />
</definition>
Exemple de contenu pour /WEB-INF/defs/client.xml
© Khalid HADDOUTI 36
INTÉGRATION DE TILES
Configuration dans Spring MVC (3/3)
+ Exemple de redirection au sein d'un contrôlleur
@Controller
public class ClientController {
@RequestMapping("/clients")
public Récupération d’un des fichiers de définitions en fonction du nom
ModelAndView showContacts() {
return new ModelAndView("clients", "command", new Client());
}
Le nom de vue "clients" permet de sélectionner le gabarit Tiles.
Affichage du gabarit "clients" issu de fichier de définition " /WEB-
INF/defs/client.xml”
© Khalid HADDOUTI 37
SPRING MVC
Travaux pratiques
+ Exercice 1
A partir d’une application web existante
Effectuer la configuration de base Spring @MVC.
Définir les garabarits Tiles.
© Khalid HADDOUTI 38
39
© Khalid HADDOUTI
GESTION DES FORMULAIRES
Les taglibs « form »
+ Spring fournit un ensemble de taglibs pour la gestion de
formulaires
Chaque tag HTML possède son équivalent taglib.
Intègre les attributs pour la gestion des évènements
onclick, onchange, onmouseover, etc…
Facilite la liaison des données entre formulaire et contrôlleur.
Affiche les erreurs de validation des données de formulaires ou
métiers.
S'intègre avec Spring @MVC.
+ Déclaration du taglib
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
© Khalid HADDOUTI 40
CRÉATION DES FORMULAIRES
Définition d’un formulaire (1/2)
+ Soit la classe « Produit » comme modèle métier
public class Produit {
private String nom;
private String reference;
public String getNom() {
return nom;
}
public void setNom(String nom) {
this.nom = nom;
}
public String getReference() {
return reference;
}
public void setReference(String reference) {
this.reference = reference;
}
Classe pure Javabean
© Khalid HADDOUTI 41
CRÉATION DES FORMULAIRES
Définition d’un formulaire (2/2)
+ Formulaire d’édition d’un produit
<form:form method="post" modelAttribute="produit">
+
<table>
<tr>
<td>Référence</td>
<td><form:input path="reference"/></td>
</tr>
<tr>
<td>Nom</td>
<td><form:input path="nom"/></td>
</tr>
<tr>
<td colspan="2">
<form:button value="Créer">Créer</form:button>
</td>
</tr>
</table>
</form:form>
L’attribut modelAttribute permet de lier les données du formulaire
avec le modèle.
Le tag « form » positionne automatiquement l’attribut « action » en
fonction du controlleur.
Les attributs « form:input » font référence aux attributs du modèle.
© Khalid HADDOUTI 42
CRÉATION DES FORMULAIRES
Le contrôleur
+ Contrôleur gestionnaire de formulaire
@Controller
@RequestMapping("/produit")
public class ProduitController {
@RequestMapping(value = "/create", method = RequestMethod.POST)
public String create( @ModelAttribute("produit") Produit produit) {
// Appel de service de création du produit
return "createProduitSuccess";
}
@RequestMapping(value = "/create", method = RequestMethod.GET)
public ModelAndView create() {
ModelAndView view = new ModelAndView();
view.setViewName("createProduit");
view.addObject("produit", new Produit());
return view;
}
@ModelAttribute effectue le binding avec les données du
formulaire.
<form:form method="post" modelAttribute="produit"> […] </form:form>
© Khalid HADDOUTI 43
44
© Khalid HADDOUTI
VALIDATION DES FORMULAIRES
JSR-303 (1/3)
+ La JSR 303 fournit un ensemble d’annotations pour la
validation de données
+ La JSR-303 est extensible
Par la création de nouvelles annotations.
Par la composition d’annotations existantes :
@NotNull, @Max, @Size, @Pattern, etc …
+ Spring @MVC n’implémente pas la JSR-303
Hibernate fournit une implémentation utilisable avec Spring
@MVC
+ La JSR-303 n’est pas spécifique à la couche de
présentation
© Khalid HADDOUTI 45
VALIDATION DES FORMULAIRES
JSR-303 (2/3)
+ La classe représentant le modèle est annotée suivant les
contraintes souhaitées
public class Client {
@NotEmpty
private String nom;
@NotEmpty
private String prenom;
@Min(18)
private int age;
[…]
+ Les annotations peuvent s'appliquer sur les méthodes
@Pattern( regexp = ".*\\.jpg|.*\\.jpeg|.*\\.gif",
message=“Seules les images de type JPEG or GIF sont acceptés.")
public String getFileName() {
return fileName;
}
© Khalid HADDOUTI 46
VALIDATION DES FORMULAIRES
JSR-303 (3/3)
+ Validation dans le contrôleur
@RequestMapping(method = RequestMethod.POST)
public String submitForm(
@ModelAttribute("client") @Valid Client client, BindingResult result)) {
if (result.hasErrors()) {
return " clientForm ";
}
else {
clientService.make(client);
return "clientSuccess";
}
}
L’annotation @Valid portée sur l’objet du modèle active la
validation.
L’objet BindingResult encapsule les erreurs de validations
survenues.
© Khalid HADDOUTI 47
VALIDATION DES FORMULAIRES
Les messages d’erreurs (1/2)
+ Les messages d’erreurs sont externalisés via l’utilisation
de ResourceBundle
<bean class="org.springframework.context.support.ResourceBundleMessageSource"
id="messageSource">
<property name="basename" value="/resources/messages"/>
</bean>
Définition d’un bean pour charger un fichier messages.properties
situé dans le classpath.
+ La clé associé aux messages d'erreurs doit respecter une
convention de nomage
<Type d’Annotation>.<identifiant du modèle javaBean>.<champ du bean>=[…]
Exemple
NotEmpty.client.name = Le nom est requis.
Range.client.age = L’âge est compris entre 1 et 150 ans.
+ Utilisation des taglib "form" pour afficher les messages
dans la page
<td><form:input path="age" /></td>
<td><form:errors path="age" cssClass="error" /></td>
© Khalid HADDOUTI 48
VALIDATION DES FORMULAIRES
Validation par Spring (1/2)
+ Spring fournit l’interface « Validator » pour implémenter la
logique de validation spécifique
public class ClientValidator implements Validator{
public boolean supports(Class clazz) {
return Client.class.isAssignableFrom(clazz);
}
public void validate(Object target, Errors errors) {
ValidationUtils.rejectIfEmptyOrWhitespace(
errors, "nom", "required.nom", "Le nom est requis");
Client client = (Client)target;
if( ! regleTresComplexe(client){
errors.rejectValue("nom", "notmatch.nom");
}
}
La classe ValidationUtils est une classe de support pour de la
validation simple.
La méthode "supports" assure que le validateur est utilisable pour
le modèle courant.
© Khalid HADDOUTI 49
VALIDATION DES FORMULAIRES
Validation par Spring (2/2)
+ Le validateur est liée au contrôleur pour être
automatiquement utilisé par Spring
@Controller
public class ClientController {
ClientValidator clientValidator;
@Autowired
@Qualifier("produitValidator")
private Validator produitValidator;
@InitBinder
protected void initBinder(WebDataBinder binder) {
binder.setValidator(this.clientValidator);
}
@RequestMapping(method = RequestMethod.POST)
public String submitForm(
@ModelAttribute("client") @Valid Client client, BindingResult result)) {
if (result.hasErrors()) {
return " clientForm ";
} else {
clientService.make(client);
return "clientSuccess";
}
}
© Khalid HADDOUTI 50
51
© Khalid HADDOUTI
GESTION DES EXCEPTIONS
Présentation
+ Spring @MVC propose une gestion centralisée des
exceptions
Principe proche des déclarations dans "web.xml".
+ L'approche Spring @MVC offre une plus grande flexibilité
Exécution de méthodes lors de la levée d'exceptions.
Redirection vers une vue Spring
+ Spring @MVC permet la défintion des gestionnaires selon
deux modes
XML – déclaration d’un bean d’implémentation de l’interface
« HandlerExceptionResolver »
Par annotation – utilisation de @ExceptionHandler
© Khalid HADDOUTI 52
GESTION DES EXCEPTIONS
Approche XML - HandlerExceptionResolver
+ Spring @MVC fournit un certain nombre
d’implémentations
SimpleMappingExceptionResolver
DefaultHandlerExceptionResolver (implémentation par défaut),…
+ Exemple avec SimpleMappingExceptionResolver
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<prop key="com.monappli.exception.MonException">NomLogiquePageException</prop>
<prop key="java.lang.Exception">error</prop>
</props>
</property>
</bean>
Association d’une exception avec la vue à afficher.
La résolution de la vue est effectuée par le ViewResolver définit
dans le contexte Spring.
La vue JSP est enrichie d’un bean "exception" qui référence
l'exception levée <h2>${exception.message}</h2>
© Khalid HADDOUTI 53
GESTION DES EXCEPTIONS
Approche par annotation - @ExceptionHandler
+ L’exception est géré au sein d’un contrôleur
@Controller
public class ProduitController {
// Autres méthodes du contrôleur
@ExceptionHandler(IOException.class)
public String handleIOException(IOException ex, HttpServletRequest request) {
return ClassUtils.getShortName(ex.getClass());
}
}
L'annotation est posée sur une méthode spécifique qui gère
l'exception.
Les types d’exceptions sont déclarés en argument de l’annotation.
La méthode possède une signature variable selon les besoins du
développeur.
La méthode retourne une simple chaîne portant le nom de la vue
ou bien un objet de type "ModelAndView".
© Khalid HADDOUTI 54
GESTION DES EXCEPTIONS
Conclusion
+ Déclaration par XML pour une gestion globale des
exceptions au sein d’une application
Centralisation des traitements des exceptions.
Externaliser les traitements associés aux exceptions du code
applicatif.
Gestionnaire adapté pour les erreurs techniques.
+ Déclaration par annotation pour une gestion spécifique
des exceptions
Plus grande granularité dans les traitements.
Gestionnaire d'exception adapté pour les erreurs métiers.
© Khalid HADDOUTI 55
SPRING MVC
Travaux pratiques
+ Exercice 2
Élaborer une application simple de création de contrat.
Les points couverts :
Contrôleur.
Mapping de requête.
Validation.
Messages d’erreurs.
Formulaire web.
© Khalid HADDOUTI 56
57
© Khalid HADDOUTI
REST
Présentation
+ REST - Representational state transfer
+ Les applications web ne sont pas uniquement utilisées
par les navigateurs
+ Les systèmes automatisés sont aussi capables de se
connecter via HTTP
+ REST est un type d’architecture de web services défini
par Roy Fielding
HTTP est utilisé en tant que protocole d’application et non plus en
tant que couche de transport
© Khalid HADDOUTI 58
REST
Principes (1/2)
+ Les ressources sont identifiées par des URIs
Ensemble regroupant les URLs et URNs
+ Utilisation des verbes issue du protocole HTTP
GET, PUT, DELETE, POST.
+ Protocole de communication du web
XML, JSON, texte, etc…
+ Architecture stateless
HttpSession n’est pas utilisé
Les requêtes de type GET peuvent être mis en cache
Les clients conservent l’état de la session en cours
© Khalid HADDOUTI 59
REST
Principes (2/2)
+ Les clients REST peuvent demander une représentation
parmi plusieurs possibles
Les ressources peuvent êtres transmises sous plusieurs formes
HTML, XML, JSON, etc…
+ Les types MIME sont utilisés pour interagir avec les
ressources
+ Les entêtes et les codes d’état HTTP transportent les
résultats vers les clients
+ Couplage faible entre client et serveur
© Khalid HADDOUTI 60
REST
JAX-RS : Java API for RESTful Web Services
+ JAX-RS est l’implémentation standard Java EE 6 pour la
construction de web services REST
+ Concerne les clients automatisés (programmatique) plus
que les navigateurs Web
+ Plusieurs implémentations sont disponibles
Apache CXF
Jersey
RESTEeasy de Jboss
Reslet crée par Jérome Louvel (pionnier REST)
+ Pas de standard pour la construction de client
© Khalid HADDOUTI 61
REST
Spring MVC
+ Spring MVC apporte les outils pour la mise en place REST
Depuis la version 3.0
S’appui sur le modèle d’architecture Spring
Spring MVC n’offre pas de support pour JAX-RS
+ Support pour la partie client (web services sur HTTP) et
serveur (RESTful web applications)
+ Spring MVC fournit la classe RestTemplate pour
implémentation d’un client Java
© Khalid HADDOUTI 62
REST
Gestion des requêtes
+ Mapping des méthodes basés sur le verbe HTTP
Permet d’associer une même URL sur plusieurs méthodes
Utilisé pour la gestion des formulaires (GET et POST)
Important pour gérer les URLs des ressources REST
Incluant PUT et DELETE
@RequestMapping(value="/utilisateurs", method=RequestMethod.GET)
public void listUtilisateur(Model model) {
// Récupération des utilisateurs
// et les placer dans le modèle.
}
@RequestMapping(value="/utilisateurs", method=RequestMethod.POST)
public void createUtilisateur(HttpServletRequest request, Model model) {
// Création de l'utilisateur
}
© Khalid HADDOUTI 63
REST
Gestion des codes erreurs HTTP (1/3)
+ Les applications web utilisent les codes standards HTTP
200 OK, 404 Not Found, 302/303 pour les redirections et 500 pour
les erreurs internes.
+ L’annotation @ResponseStatus permet de positionner le
code HTTP paramétré au sein de l’instance
« HttpServletResponse »
+ @ResponseStatus permet d’associer un code spécifique
avec une exception
© Khalid HADDOUTI 64
REST
Gestion des codes erreurs HTTP (2/3)
+ Quelques codes HTTP
Code HTTP Description
200 Envoyé après une commande GET ayantaboutie
201 Création d’une nouvelle ressource depuis un POST ouPUT
204 La réponse est vide (après une commande POST ouPUT)
404 La ressource n’existepas
405 La méthode invoquée n’est pas supporté par la ressource
409 Un conflit apparait pendant la modification appliquée sur une ressource
500 Erreur interne grave
http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
© Khalid HADDOUTI 65
REST
Gestion des codes erreurs HTTP (3/3)
+ Exemple d’envoi d’un code HTTP de création d’une
ressource
@RequestMapping(method=RequestMethod.GET)
@ResponseStatus(HttpStatus.CREATED) // Code HTTP envoyé : 201
public void createUtilisateur(HttpServletRequest request, HttpServletResponse response) {
Utilisateur utilisateur = this.utilisateurService.createUtilisateur();
response.addHeader("Location", getLocationForChildResource(request, utilisateur.getId()));
}
La méthode ne renvoi pas vers une vue.
La réponse ne possède pas de contenu.
© Khalid HADDOUTI 66
REST / AJAX
Spring @MVC et JSON – Serveur (1/3)
+ Spring MVC permetde renvoyer du flux de type JSON
@ResponseBody spécifie le contenu retourné au consommateur.
Un convertisseur effectue la sérialisation/déssérialisation depuis
un javabean modèle.
Le convertisseur implémente l’interface HttpMessageConverter.
JSON – MappingJacksonHttpMessageConverter
+ Spring @MVC d’autres implémentations
XML – flux XML
Texte – Chaînes de caractères
+ Un type MIME est défini par défaut pour chaque
convertisseur
Il est possible de modifier le type MIME
© Khalid HADDOUTI 67
REST / AJAX
Spring @MVC et JSON – Serveur (2/3)
+ Les caractéristiques du service sont annotés sur le
contrôlleur
Controller
@RequestMapping(value = "/{clientId}", method = RequestMethod.GET)
Public @ResponseBody Client findClient(@PathVariable int clientId) {
return clientService.get(clientId);
}
+ Le modèle est encapsulé au sein d’un JavaBean
import org.codehaus.jackson.annotate.JsonAutoDetect;
@JsonAutoDetect
public class Client {
@NotEmpty
private String nom;
@NotEmpty
private String prenom;
@Min(18)
private int age;
….
}
@JsonAutodetect permet de sélectionner les champs/méthodes à
sérialiser.
© Khalid HADDOUTI 68
REST / AJAX
Spring @MVC et JSON – Serveur (3/3)
+ Les convertisseurs sont déclarés au sein du contexte
servlet
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="jsonConverter" />
</list>
</property>
</bean>
<bean id="jsonConverter"
class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="supportedMediaTypes" value="application/json" />
</bean>
+ Une librairie d’implémentation de JSON doit être ajouté au
projet.
Librairie Jackson : http://jackson.codehaus.org/
© Khalid HADDOUTI 69
REST / AJAX
Spring @MVC et JSON – Client (1/2)
+ Spring @MVC fournit la classe RestTemplate pour
interroger les services REST
Implémente le pattern Template
+ Le bean RestTemplate est déclaré dans le fichier de
contexte applicatif Spring
<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
<property name="messageConverters">
<list>
<ref bean="jacksonConverter"/>
</list>
</property>
</bean>
Les convertisseurs sont injectés dans le bean RestTemplate.
<bean id="jacksonConverter"
class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="supportedMediaTypes" value="application/json" />
</bean>
Par défaut, Spring @MVC positionne le type MIME
« application/json »
© Khalid HADDOUTI 70
REST / AJAX
Spring @MVC et JSON – Client (2/2)
+ Le bean RestTemplate est injecté et manipulé dans les
classes spécifique
@Component
public class Client {
@Autowired
private RestTemplate restTemplate;
public Contract getClient(int clientId) {
Client c = this.restTemplate.getForObject(
"http://localhost:8080/app/client/{clientId}", Client.class, clientId);
return c;
}
La classe RestTemplate possède de multiples méthodes pour
La création de ressources
La suppression de ressources
La lecture des entêtes HTTP
RestTemplate couvre l’ensemble des verbes HTTP.
© Khalid HADDOUTI 71
SPRING MVC
Travaux pratiques
+ Exercice 3
A partir d’une application web existante
Mettre en place un web service en s’appuyant sur Spring MVC.
Utiliser les différentes implémentations REST pour les web services.
A partir d’une application cliente existante :
Consommer le web service en s’appuyant sur la classe RestTemplate
et le protocole JSON.
© Khalid HADDOUTI 72
SPRING @MVC
73
© Khalid HADDOUTI