You are on page 1of 48

7

Spring MVC
La mise en pratique du patron de conception MVC (Model View Controller) offre une meilleure structuration du tiers de prsentation des applications Java EE en dissociant les proccupations de dclenchement des traitements de la construction de la prsentation proprement dite. Les principaux frameworks MVC implmentent le type 2 de ce patron, qui instaure un point dentre unique ayant pour mission daiguiller les requtes vers la bonne entit de traitement. Le framework Spring offre une implmentation innovante du patron MVC par le biais dun framework nomm Spring MVC, qui prote des avantages de linjection de dpendances (voir chapitres 2 et 3) et qui, depuis la version 2.5, offre une intressante exibilit grce aux annotations Java 5. Ce module permet ds lors de sabstraire de lAPI Servlet de Java EE, les informations souhaites tant automatiquement mises disposition en tant que paramtres des mthodes des contrleurs. De plus, partir de la version 3.0, Spring MVC intgre un support permettant de grer la technologie REST, les URL possdant la structure dcrite par cette dernire tant exploitable en natif. Le prsent chapitre passe en revue les fonctionnalits et apports de ce module, qui met en uvre les principes gnraux du framework Spring, lesquels consistent masquer lAPI Servlet et simplier les dveloppements dapplications Java EE tout en favorisant leur structuration et leur exibilit.

Implmentation du pattern MVC de type 2 dans Spring


Cette section dcrit brivement limplmentation du patron de conception MVC de type 2 dans le framework Spring.

184

Les frameworks de prsentation PARTIE II

Nous prsenterons rapidement les concepts de base du type 2 de ce patron puis nous concentrerons sur les principes de fonctionnement et constituants de Spring MVC, limplmentation du patron MVC par Spring.

Fonctionnement du patron MVC 2


Le patron MVC est communment utilis dans les applications Java/Java EE pour raliser la couche de prsentation des donnes aussi bien dans les applications Web que pour les clients lourds. Lorsquil est utilis dans le cadre de Java EE, il sappuie gnralement sur lAPI servlet ainsi que sur des technologies telles que JSP/JSTL. Il existe deux types de patrons MVC, celui dit de type 1, qui possde un contrleur par action, et celui dit de type 2, plus rcent et plus exible, qui possde un contrleur unique. Nous nous concentrerons sur ce dernier, puisquil est implment dans les frameworks MVC. La gure 7-1 illustre les diffrentes entits du type 2 du patron MVC ainsi que leurs interactions lors du traitement dune requte.

Contrleur

Contrleur frontal Aiguillage des requtes vers la bonne entit de traitement

Entit de traitement

Ralise les traitements de la requte Modle

Objet Objet Objet Contient les donnes prsenter Vue Fichier Construite la vue avec un pseudo template afin dafficher les donnes prsenter Classe

Construit la vue en Java afin dafficher les donnes prsenter

Figure 7-1

Entits mises en uvre dans le patron MVC de type 2

Spring MVC CHAPITRE 7

185

Les caractristiques des composants mis en uvre dans ce patron sont les suivantes : Modle. Permet de mettre disposition les informations utilises par la suite lors des traitements de prsentation. Cette entit est indpendante des API techniques et est constitue uniquement de Beans Java. Vue. Permet la prsentation des donnes du modle. Il existe plusieurs technologies de prsentation, parmi lesquelles JSP/JSTL, XML, les moteurs de templates Velocity et FreeMarker ou de simples classes Java pouvant gnrer diffrents types de formats. Contrleur. Gre les interactions avec le client tout en dclenchant les traitements appropris. Cette entit interagit directement avec les composants de la couche service mtier et a pour responsabilit la rcupration des donnes mises disposition dans le modle. Lors de la mise en uvre du type 2 de ce patron, cette partie se compose dun point dentre unique pour toute lapplication et de plusieurs entits de traitement. Ce point dentre unique traite la requte et dirige les traitements vers lentit approprie. Pour cette raison, lentit de traitement est habituellement appele contrleur. Le contrleur frontal, ou contrleur faade , est intgr au framework MVC, et seuls les entits de traitement sont spciques lapplication. Un framework MVC implmente le contrleur faade, les mcanismes de gestion du modle, ainsi que ceux de slection et de construction de la vue. Lutilisateur dun tel framework a en charge le dveloppement et la conguration des entits de traitements et des vues choisies.

Principes et composants de Spring MVC


Le framework Spring fournit des intgrations avec les principaux frameworks MVC ainsi que sa propre implmentation. Forts de leur exprience dans le dveloppement dapplications Java EE, ses concepteurs considrent que linjection de dpendances offre un apport de taille pour concevoir et structurer des applications fondes sur le patron MVC. Prcisons que Spring MVC ne constitue quune partie du support relatif aux applications Web. Le framework Spring offre dautres fonctionnalits permettant notamment le chargement des contextes applicatifs de manire transparente ainsi que des intgrations avec dautres frameworks MVC, tels JSF, WebWork ou Tapestry. Parmi les principes fondateurs de Spring MVC, remarquons notamment les suivants : Utilisation du conteneur lger an de congurer les diffrentes entits du patron MVC et de bncier de toutes les fonctionnalits du framework Spring, notamment au niveau de la rsolution des dpendances. Favorisation de la exibilit et du dcouplage des diffrentes entits mises en uvre grce la programmation par interface. Utilisation dune hirarchie de contextes applicatifs an de raliser une sparation logique des diffrents composants de lapplication. Par exemple, les composants des services mtier et des couches infrieures nont pas accs ceux du MVC.

186

Les frameworks de prsentation PARTIE II

Les composants du MVC ont pour leur part les principales caractristiques suivantes : partir de la version 2.5 de Spring, la gestion de laiguillage et la conguration des contrleurs MVC se ralisent par lintermdiaire dannotations. Par ce biais, Spring MVC permet de masquer lutilisation de lAPI servlet et favorise la mise en uvre des tests unitaires ce niveau. Lapproche fonde sur les classes dimplmentation de contrleurs est dsormais dprcie. Gestion des formulaires en se fondant sur les annotations relatives aux contrleurs an non seulement de charger et dafcher les donnes du formulaire, mais galement de grer leur soumission. Ces donnes sont utilises pour remplir directement un Bean sans lien avec Spring MVC, qui peut tre valid si ncessaire. Des mcanismes de mappage et de conversion des donnes sont intgrs et extensibles selon les besoins. Abstraction de limplmentation des vues par rapport aux contrleurs permettant de changer de technologie de prsentation sans impacter le contrleur. Pour mettre en uvre ces principes et composants, Spring MVC sappuie sur les entits illustres la gure 7-2. Le traitement dune requte passe successivement par les diffrentes entits en commenant par la servlet DispatcherServlet et en nissant par la vue choisie.

DispatcherServlet

HandlerMapping

Controller

ViewResolver

View

Contrleur faade

Aiguillage des requtes vers le bon contrleur

Entits ralisant les traitements de la requte

Mcanisme de slection de la vue souhaite

Entit construisant la vue

ModelAndView
Contexte de Spring MVC

Contexte de l'application Web

Contexte partag (facultatif)

Figure 7-2

Entits de traitement des requtes de Spring MVC

Les principaux composants de Spring MVC peuvent tre rpartis en trois groupes, selon leur fonction : Gestion du contrleur faade et des contextes applicatifs. Permet de spcier les chiers des diffrents contextes ainsi que leurs chargements. Le contrleur faade doit tre congur de faon spcier laccs lapplication.

Spring MVC CHAPITRE 7

187

Gestion des contrleurs. Consiste congurer la stratgie daccs aux contrleurs, ainsi que leurs diffrentes classes dimplmentation et leurs proprits. Laiguillage se congure dsormais directement dans les classes mettant en uvre des contrleurs en se fondant sur des annotations. Ces dernires permettent galement de mettre facilement disposition les donnes prsentes dans la requte, la session et le modle. Gestion des vues. Consiste congurer la ou les stratgies de rsolution des vues ainsi que les frameworks ou technologies de vue mis en uvre.

Initialisation du framework Spring MVC


Linitialisation du framework Spring MVC seffectue en deux parties, essentiellement au sein du chier web.xml puisquelle utilise des mcanismes de la spcication Java EE servlet.

Gestion des contextes


Le framework Spring permet de charger automatiquement les contextes applicatifs en utilisant les mcanismes des conteneurs de servlets. Dans le cadre dapplications Java EE, une hirarchie de contextes est mise en uvre an de regrouper et disoler de manire logique les diffrents composants. De la sorte, un composant dune couche ne peut accder celui dune couche suprieure.

Contexte applicatif Spring Rappelons quun contexte applicatif correspond au conteneur lger en lui-mme, dont la fonction est de grer des Beans. Le framework offre galement un mcanisme permettant de dnir une hirarchie de contextes an de raliser une sparation logique entre des groupes de Beans. Dans le cas du MVC, il sagit dempcher lutilisation de composants du MVC par des composants service mtier ou daccs aux donnes.

Le framework Spring offre une hirarchie pour les trois contextes suivants : Contexte racine. Ce contexte est trs utile pour partager des objets dune mme bibliothque entre plusieurs modules dune mme application Java EE pour un mme chargeur de classes. Contexte de lapplication Web. Stock dans le ServletContext, ce contexte doit contenir la logique mtier ainsi que celle de laccs aux donnes. Contexte du framework MVC. Gr par le contrleur faade du framework, ce contexte doit contenir tous les composants relatifs au framework MVC utilis.

188

Les frameworks de prsentation PARTIE II

La gure 7-3 illustre cette hirarchie ainsi que la porte des diffrents contextes.
Figure 7-3

Hirarchie des contextes de Spring pour une application Web

Contexte racine Singleton

Contexte WebApp ServletContext

Contexte WebApp

Contexte MVC Servlet

Contexte MVC

La mise en uvre du contexte de lapplication Web est obligatoire, tandis que celle du contexte racine est optionnelle et nest donc pas dtaille ici. Si ce dernier est omis, Spring positionne de manire transparente celui de lapplication Web en tant que contexte racine. Linitialisation du contexte de lapplication Web, que nous dtaillons dans ce chapitre, est indpendante du framework MVC choisi et utilise les mcanismes du conteneur de servlets. Sa conguration est identique dans le cadre du support dautres frameworks MVC.
Chargement du contexte de lapplication Web

Le framework Spring fournit une implmentation de la classe ServletContextListener de la spcication servlet permettant de congurer et dinitialiser ce contexte au dmarrage et de le naliser larrt de lapplication Web. Cette fonctionnalit est utilisable avec un conteneur de servlets supportant au moins la version 2.3 de la spcication. Cet observateur paramtre les chiers de conguration XML du contexte en ajoutant les lignes suivantes dans le chier web.xml de lapplication :
<context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext*.xml</param-value> </context-param> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener>

Spring MVC CHAPITRE 7

189

Chargement du contexte de Spring MVC

La conguration tout comme le chargement de ce contexte sont lis ceux de la servlet du contrleur faade de Spring MVC. Prcisons que, par dfaut, cette dernire initialise un contexte applicatif fond sur un chier <nom-servlet>-servlet.xml, lequel utilise le nom de la servlet prcdente pour <nom-servlet>. Ce chier se situe par dfaut dans le rpertoire WEBINF ; la valeur de <nom-servlet> est spcie grce la balise servlet-name. Dans notre tude de cas, la servlet de Spring MVC sappelle tudu. Le chier tudu-servlet.xml contient les diffrents composants utiliss par ce framework, comme les contrleurs, les vues et les entits de rsolution des requtes et des vues. Nous pouvons personnaliser le nom de ce chier laide du paramtre dinitialisation contextConfigLocation de la servlet. Le code suivant montre comment spcier un chier mvc-context.xml pour le contexte de Spring MVC par lintermdiaire du paramtre prcdemment cit ( ) :
<web-app> (...) <servlet> <servlet-name>tudu</servlet-name> (...) <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/mvc-context.xml</param-value> </init-param> </servlet> </web-app>

Initialisation du contrleur faade


Le fait que le framework Spring MVC implmente le patron MVC de type 2 entrane quil met en uvre un contrleur faade pour diriger les traitements vers des classes dsignes par le terme Controller dans Spring MVC.
Le contrleur faade Cette entit correspond lunique point daccs de lapplication Web. Son rle est de rediriger les traitements vers le bon contrleur en se fondant sur ladresse daccs pour traiter la requte. Dans le cas dapplications Web, ce contrleur est implment par le biais dune servlet, qui est gnralement fournie par le framework MVC utilis.

Ce contrleur faade est implment par le biais de la servlet DispatcherServlet du package org.springframework.web.servlet, cette dernire devant tre congure dans le chier WEBINF/web.xml. Le mappage de la ressource ( ) est dni au niveau du conteneur de servlets dans le chier web.xml localis dans le rpertoire WEB-INF. Spring ne pose aucune restriction ce niveau, comme lillustre le code suivant :

190

Les frameworks de prsentation PARTIE II

<web-app> ... <servlet> <servlet-name>tudu</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>tudu</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> </web-app>

Support des annotations pour les contrleurs


Comme indiqu prcdemment, partir de la version 2.5 de Spring, la conguration des contrleurs se ralise par lintermdiaire dannotations. Bien que cette approche soit celle utiliser, il reste nanmoins ncessaire de lactiver dans la conguration de Spring. Cet aspect peut tre mis en uvre de deux manires linstar de la conguration des composants par lintermdiaire des annotations dans Spring. La premire approche consiste spcier une implmentation de linterface HandlerMapping fonde sur les annotations. Spring MVC propose la classe DefaultAnnotationHandlerMapping cet effet. Cette dernire peut tre utilise conjointement avec la classe AnnotationMethodHandlerAdapter an de congurer les mthodes de traitements des requtes dans les contrleurs avec des annotations. Avec cette approche, les Beans des contrleurs doivent tre congurs en tant que Beans dans le contexte de Spring MVC. Le code suivant dcrit lutilisation de ces deux classes dans le chier de conguration Spring associ la servlet DispatcherServlet de Spring MVC :
<beans (...)> <bean class="org.springframework.web.servlet .mvc.annotation.DefaultAnnotationHandlerMapping"/> <bean class="org.springframework.web.servlet .mvc.annotation.AnnotationMethodHandlerAdapter"/> </beans>

La seconde consiste en lutilisation de la balise component-scan de lespace de nommage context an de dtecter tous les composants prsents et notamment les contrleurs Spring MVC. Ces derniers nont plus tre dnis en tant que Beans dans la conguration de Spring. Dans ce contexte, lannotation Autowired doit tre utilise pour linjection de dpendances. Pour plus de prcision, reportez-vous au chapitre 2.

Spring MVC CHAPITRE 7

191

La conguration de cet aspect se ralise dans le chier de conguration Spring associ la servlet DispatcherServlet de Spring MVC :
<beans (...)> <context:component-scan base-package="tudu.web" /> </beans>

Il est recommand de nutiliser la premire approche que si une personnalisation de la stratgie de mappage des requtes est envisage. La seconde approche reste donc celle utiliser par dfaut.

En rsum
Cette section a dtaill les mcanismes gnraux de fonctionnement du patron MVC de type 2 ainsi que la structuration utilise dans le framework Spring MVC an de le mettre en uvre. Nous avons pu constater que les entits utilises permettent de bien modulariser les traitements et disoler le contrleur de la vue. Les mcanismes de chargement des contextes, de conguration du contrleur faade et de lapproche dirige par les annotations du framework Spring MVC ont galement t dcrits. Nous allons maintenant dtailler la faon dont Spring MVC gre les requtes et les vues.

Traitement des requtes


Comme nous lavons voqu prcdemment, lapproche de Spring MVC an de traiter les requtes est dsormais compltement dirige par des annotations. Ces dernires permettent de congurer aussi bien laiguillage des requtes que les contrleurs eux-mmes. Il est noter dans ce contexte que lannotation Controller permet de prciser quune classe correspond un contrleur MVC et quelle contient les traitements correspondants. Une fois cette annotation positionne, le mappage des URI doit tre dni an de slectionner le contrleur de traitement pour une requte Web donne. Cela se congure galement par le biais des annotations, ainsi que nous le dtaillons dans la prochaine section.

Slection du contrleur
Comme pour tout framework implmentant le patron MVC de type 2, un mcanisme de correspondance entre la classe de traitement approprie et lURI de la requte est intgr. Le framework congure cette correspondance en se fondant sur les informations prsentes dans les annotations RequestMapping des contrleurs. An de congurer ce mcanisme, il est indispensable de bien comprendre la structure de lURL dune requte, qui apparat toujours sous la forme suivante dans les applications Java EE :
http://<machine>:<port>/<alias-webapp>/<alias-ressource-web>

192

Les frameworks de prsentation PARTIE II

LURI correspond la n de lURL :


/<alias-webapp>/<alias-ressource-web>

Lalias de lapplication Web, <alias-webapp>, est congur au niveau du serveur dapplications, contrairement celui de la ressource Web, <alias-ressource-web>, qui se ralise au sein de lapplication. Dans un premier temps, laccs la servlet DispatcherServlet de Spring MVC est paramtr dans le chier web.xml du rpertoire WEB-INF an de prendre en compte un ensemble dURI avec des mappages de la forme *, /quelquechose/* ou *.quelquechose. Nous avons dtaill la conguration de cet aspect la section Initialisation du contrleur faade prcdemment dans ce chapitre. Avec les annotations, limplmentation DefaultAnnotationHandlerMapping de linterface HandlerMapping est utilise implicitement ou explicitement suivant la conguration. Elle se fonde sur les informations prsentes dans les annotations de type RequestMapping. Cette dernire peut tre prsente aussi bien au niveau de la classe du contrleur que des mthodes de ce dernier. Les informations spcies par ce biais au niveau de la classe lui sont globales, avec la possibilit de les surcharger au niveau des mthodes. Cet aspect offre dintressantes perspectives an de congurer diffrents types de contrleurs, tels que ceux entres multiples ou ddis la gestion des formulaires. Nous dtaillons cet aspect plus loin dans ce chapitre. Le tableau 7-1 rcapitule les diffrentes proprits utilisables de lannotation RequestMapping.
Tableau 7-1. Proprits de lannotation RequestMapping
Proprit Type Description
Spcie la ou les mthodes HTTP supportes par le mappage. La spcication dune mthode se ralise par lintermdiaire des valeurs de lnumration RequestMethod. Permet de raliser un mappage plus n en se fondant sur les paramtres de la requte. La prsence ou la non-prsence (avec loprateur !) dun paramtre peut tre utilise. Correspond la valeur de lannotation. Cette proprit permet de dnir la ou les valeurs dnissant le mappage de llment. Ces valeurs peuvent ventuellement correspondre des expressions rgulires au format Ant.

method params value

String[] String[] String[]

Lexemple suivant illustre lutilisation de lannotation au niveau de la classe du contrleur ( ) an de spcier la valeur du mappage ainsi quau niveau de la mthode ddie au traitement de la requte ( ) :
@Controller @RequestMapping("/welcome.do") public class WelcomeController { @RequestMapping public void welcome() { (...) } }

Spring MVC CHAPITRE 7

193

Dans lexemple ci-dessus, lannotation au niveau de la mthode reprend les valeurs des proprits de lannotation positionne au niveau de la classe. Il est galement possible de ne spcier le mappage quau niveau de la mthode de traitement ( ) :
@Controller public class WelcomeController { @RequestMapping("/welcome.do") public void welcome() { (...) } }

Pour nir, il est galement possible de spcier plusieurs mappages ( ) pour une mme annotation avec la mthode HTTP daccs souhaite ( ) ainsi quun ltrage se fondant sur les valeurs des paramtres de la requte ( ), comme lillustre le code suivant :
@Controller public class WelcomeController { @RequestMapping( value={"/welcome.do", "/index.do"), method=RequestMethod.GET params={"auth=true", "refresh", "!authenticate"} public void welcome() { (...) } }

Dans lexemple ci-dessus, la mthode welcome du contrleur est appele pour les URI / <alias-webapp>/welcome.do ou /<alias-webapp>/index.do seulement par la mthode HTTP GET si les conditions sur les paramtres sont vris. Dans notre cas, le paramtre auth doit possder la valeur true, le paramtre refresh doit tre prsent, et le paramtre authenticate ne doit pas ltre.

Les types de contrleurs


Comme indiqu prcdemment, Spring MVC fournit lannotation Controller an de dnir une classe en tant que contrleur. Cette approche est particulirement exible mettre en uvre, car elle permet de sabstraire de lAPI Servlet et de dnir le contenu des contrleurs et les signatures des mthodes en fonction des besoins. Les sections qui suivent dtaillent les diffrents mcanismes et dclinaisons utilisables an de mettre en uvre des contrleurs dans Spring MVC.

194

Les frameworks de prsentation PARTIE II

Contrleurs de base

Pour mettre en uvre les contrleurs de ce type, lutilisation de lannotation RequestMapping prcdemment dcrite est sufsante. Les mthodes sur lesquelles est applique cette annotation prennent en paramtres des objets de type HttpServletRequest et HttpServletResponse et retournent un objet de type ModelAndView. Ces contrleurs peuvent tre entres multiples puisquil est possible en standard de positionner une annotation RequestMapping sur plusieurs de leurs mthodes.
Point dentre Dans le contexte du pattern MVC, un point dentre correspond une mthode dun composant qui peut tre utilise par le conteneur ou le framework qui le gre an de traiter une requte. La signature de cette mthode suit habituellement des conventions spciques an de pouvoir tre appele.

Le code suivant illustre la mise en uvre dun contrleur simple en se fondant sur lannotation RequestMapping ( ) :
@Controller public class ShowTodosController { (...) @RequestMapping("/showTodos.do") public ModelAndView showTodos(HttpServletRequest request, HttpServletResponse response) throws Exception { Collection<TodoList> todoLists = new TreeSet<TodoList>( userManager.getCurrentUser().getTodoLists()); String listId = null; if (!todoLists.isEmpty()) { listId = request.getParameter("listId"); if (listId != null) { listId = todoLists.iterator().next().getListId()); } } Map<String, Object> model = new HashMap<String, Object>(); model.put("defaultList", listId); return new ModelAndView("todos", model); } }

Aucune autre conguration, si ce nest linjection des dpendances avec lannotation Autowired, nest ncessaire. Spring MVC offre nanmoins une approche intressante et exible an de supporter diffrentes signatures de mthodes de traitements des contrleurs et de spcier des mthodes de remplissage du modle. Nous dcrivons cette approche, dont lutilisation est recommande, aux sections suivantes.

Spring MVC CHAPITRE 7

195

Support des paramtres et retours des mthodes

En parallle de la signature type pour les mthodes de traitement des contrleurs, signature hrite des prcdentes versions de Spring MVC, le framework permet si ncessaire de sabstraire des API Servlet et de Spring MVC. Il est en ce cas possible de spcier une signature de mthodes en fonction de ses besoins. La dtermination des points dentre dun contrleur est dtermine par la prsence de lannotation RequestMapping. Il est noter que cette approche est galement valable pour les mthodes annotes par ModelAttribute et InitBinder. Spring MVC permet de passer directement des paramtres prcis soit par type, soit en se fondant sur des annotations supplmentaires. Le framework permet en outre de retourner diffrents types en fonction de ses besoins. Ces deux possibilits peuvent se combiner pour une plus grande exibilit. Le tableau 7-2 rcapitule les diffrents paramtres supports par Spring MVC pour les mthodes de gestion des requtes Web, et le tableau 7-3 les types de retours possibles.
Tableau 7-2. Types de paramtres possibles pour une mthode dun contrleur
Type de paramtre Description
Requte par lintermdiaire de lAPI Servlet. Rponse de la requte par lintermdiaire de lAPI Servlet. Session de linitiateur de la requte par linter mdiaire de lAPI Servlet. Accs dune manire gnrique aux paramtres de la requte sans utiliser lAPI Servlet. Couple pays et langue associ la requte. Flux dentre associ la requte an davoir accs au contenu de la requte. Flux de sortie associ la rponse de la requte an de gnrer le contenu de la rponse. Paramtre de la requte dont lidentiant est celui spci dans lannotation. Spring a la responsabilit de le rcuprer dans la requte et de le convertir dans le type attendu. Modle utilis pour les donnes prsentes dans la vue. Celuici offre la possibilit davoir accs aux donnes contenues dans le modle et de les manipuler. Objet de formulaire rcupr dans le modle en se fondant sur lidentiant spci dans lannotation. Rsultat du mappage et validation dobjets de formulaire. Une validation personnalise peut se fonder sur ce paramtre an denregistrer les erreurs. Dans le cas dun formulaire mis en uvre sur plusieurs pages, cet objet offre la possibilit de relcher les ressources mises en uvre cet effet.

ServletRequest ou HttpServletRequest ServletResponse ou HttpServletResponse HttpSession WebRequest ou NativeWebRequest Locale InputStream ou Reader OutputStream ou Writer
Paramtre annot par RequestParam

Map, Model ou ModelMap

Type correspondant un objet de formulaire et annot par ModelAttribute

Errors ou BindingResult

SessionStatus

196

Les frameworks de prsentation PARTIE II Tableau 7-3. Types de retours possibles pour une mthode dun contrleur
Type de retour Description
Objet contenant les donnes du modle utiliser dans la vue. Lidentiant de la vue est implicitement dduit par Spring MVC (voir le cas void, o aucun objet nest retourn). Identique au prcdent. Objet regroupant lidentiant de la vue utiliser suite aux traitements du contrleur et le contenu du modle pour cette dernire. Identiant de la vue utiliser suite aux traitements du contrleur. Vue utiliser suite aux traitements du contrleur. Dans le cas o aucun objet nest retourn, Spring MVC dduit implicitement lidentiant de la vue utiliser. Ce mcanisme se fonde sur une implmentation de linterface RequestToViewNameTranslator. Limplmentation par dfaut extrait cet identiant en enlevant les prxe et sufxe de lURI. Par exemple, pour un URI /showTodos.do, lidentiant de la vue est showTodos. Objet ajouter aux donnes du modle aprs lexcution de la mthode et avant celle de la vue. Lidentiant utilis dans lajout correspond celui de lannotation.

Map Model ModelAndView String View void

Nimporte quel type annot par ModelAttri-

bute

Comme le montrent ces tableaux, deux annotations sont proposes pour le traitement des requtes, RequestParam et ModelMap. Nous dcrivons dans cette section lutilisation de la premire et dtaillerons la seconde la section Contrleur de gestion de formulaire . Lannotation RequestParam offre la possibilit de rfrencer un paramtre de la requte par son nom. Lobjet correspondant est alors pass en tant que paramtre. ce niveau, une conversion de type est ralise si ncessaire an de coller avec le type attendu pour le paramtre. Le code suivant illustre lutilisation de lannotation RequestParam an davoir accs au paramtre de la requte didentiant listId par lintermdiaire dun paramtre dune mthode de traitement du contrleur :
@Controller public class ShowTodosController { (...) @RequestMapping("/showTodos.do") public ModelAndView showTodos( @RequestParam String listId) throws Exception { Collection<TodoList> todoLists = new TreeSet<TodoList>( userManager.getCurrentUser().getTodoLists()); if (!todoLists.isEmpty()) { if (listId != null) { listId = todoLists.iterator().next().getListId(); } }

Spring MVC CHAPITRE 7

197

Map<String, Object> model = new HashMap<String, Object>(); model.put("defaultList", listId); return new ModelAndView("todos", model); } }

Lors de lomission de la valeur de lannotation RequestParam, le nom du paramtre sur lequel elle porte est utilis. Ainsi, lutilisation de lannotation dans lexemple prcdent est similaire la suivante ( ) :
@Controller public class ShowTodosController { (...) @RequestMapping("/showTodos.do") public ModelAndView showTodos( @RequestParam("listId") String listId) throws Exception { (...) } }

Par dfaut, lutilisation de lannotation RequestParam ncessite la prsence du paramtre dans la requte. Lattribut required de lannotation permet de paramtrer ce comportement an de rendre le paramtre optionnel, comme le montre le code suivant ( ) :
@RequestMapping("/showTodos.do") public ModelAndView showTodos( @RequestParam(value="listId", required="false") String listId) throws Exception { (...) }

Les mthodes de traitement des contrleurs acceptent galement un paramtre de type ModelMap, ce paramtre correspondant aux donnes du modle. En utilisant ce paramtre, il est possible de manipuler les donnes du modle et den ajouter de nouvelles. Dans ce cas, il nest plus ncessaire de retourner un objet de type ModelAndView ; une chane de caractres correspondant lidentiant de la vue suft. Le code suivant illustre ladaptation de lexemple prcdent ( ) an dutiliser ce mcanisme :
@Controller public class ShowTodosController { (...) @RequestMapping("/showTodos.do") public String showTodos( @RequestParam String listId, ModelMap model) throws Exception { Collection<TodoList> todoLists = new TreeSet<TodoList>( userManager.getCurrentUser().getTodoLists());

198

Les frameworks de prsentation PARTIE II

if (!todoLists.isEmpty()) { if (listId != null) { listId = todoLists.iterator().next().getListId(); } } model.addAttribute("defaultList", listId); return "todos"; } }

Les principaux autres types de paramtres et de retour sont dcrits dans les sections suivantes.
Contrleur de gestion de formulaire

Spring MVC fournit un support pour lafchage des donnes des formulaires et leur soumission laide dannotations. Ce support se fonde sur les diffrents concepts et annotations dcrits aux sections prcdentes. Bien que ce type de contrleur utilise un Bean an de stocker les informations des formulaires, aucune conguration nest raliser pour linjection de dpendances. Il suft que ce Bean soit prsent dans les donnes du modle et que lidentiant correspondant soit spci dans le formulaire. La section suivante se penche sur la faon dimplmenter la gestion des formulaires HTML au moyen de lapproche oriente annotations de Spring MVC.
Afchage du formulaire

Lutilisation des annotations RequestMapping, ModelAttribute et InitBinding permet de charger les diffrentes entits ncessaires lafchage du formulaire dans la vue. Les mthodes sur lesquelles sont appliques ces annotations, prennent alors part au cycle de traitement de la requte et adressent des problmatiques distinctes et senchanent dans un ordre bien prcis. Lafchage du formulaire est ralis grce lappel dune mthode de traitement de la requte par le biais de la mthode GET. Le cycle denchanement des mthodes est illustr la gure 7-4. Spring MVC permet dinitialiser lobjet de formulaire en se fondant sur une mthode annote par ModelAttribute. Cet objet doit tre retourn par la mthode et est automatiquement ajout dans le modle. Il peut donc tre utilis par la suite dans la vue pour initialiser le formulaire correspondant. Le comportement habituel consiste crer une instance vierge chaque demande dafchage du formulaire si aucun paramtre nest spci. Si un paramtre est prsent dans la requte, celui-ci peut tre alors utilis, par exemple, an de rcuprer une instance initialise avec des valeurs de la base de donnes.

Spring MVC CHAPITRE 7


Figure 7-4

199

Requte GET

Enchanement des mthodes permettant lafchage des donnes dun formulaire

Mthodes annotes par ModelAttribute

Mthode annote par InitBinder

Mthode annote par RequestMapping avec method=RequestMethod.GET

Mthode annote par InitBinder

Vue

Le code suivant, tir de Tudu Lists, donne un exemple dutilisation de la mthode initFormObject ( ) de ce type :
(...) public class MyInfoController { (...) @ModelAttribute("userinfo") public UserInfoData initFormObject( HttpServletRequest request) { String login = request.getRemoteUser(); User user = userManager.findUser(login); UserInfoData data = new UserInfoData(); data.setPassword(user.getPassword()); data.setVerifyPassword(user.getPassword()); data.setFirstName(user.getFirstName()); data.setLastName(user.getLastName()); data.setEmail(user.getEmail()); return data; } (...) }

Les PropertyEditor personnaliss sont ajouts par lintermdiaire dune mthode annote par InitBinder an de convertir les proprits du Bean de formulaire en chanes de caractres afchables dans des champs. Cette mthode doit possder un paramtre de type WebDataBinder an de pouvoir les enregistrer.

200

Les frameworks de prsentation PARTIE II

Le code suivant indique la faon dajouter un PropertyEditor dans un contrleur de gestion de formulaire en se fondant sur lannotation InitBinder ( ) :
(...) public class MyInfoController { (...) @InitBinder public void initBinder(WebDataBinder binder) { binder.registerCustomEditor(MyClass.class, new MyPropertyEditor()); } (...) }

Cette mthode est utilise an dafcher les valeurs du Bean de formulaire dans la vue correspondante sous forme de chanes de caractres. Il est possible dajouter des lments dans le modle par lintermdiaire de lannotation ModelAttribute. Ces lments peuvent tre utiliss dans la construction du formulaire an notamment dinitialiser des listes de slection, des boutons radio ou des cases cocher. Autant de mthodes que dlments ajouter doivent tre dnies. Le code suivant montre la faon dajouter les donnes ncessaires an dinitialiser un formulaire en se fondant sur lannotation ModelAttribute ( ) :
(...) public class MyInfoController { (...) @ModelAttribute("datas") public List<String> populateDataList() { List<String> datas = new ArrayList<String>(); datas.add("my data"); return datas; } (...) }

Pour nir, il convient de dnir une mthode de traitement ddie lafchage du formulaire. Cette dernire doit tre annote avec RequestMapping et possder la proprit method avec la valeur RequestMethod.GET. Le mappage avec lURI peut tre spci ce niveau ou globalement au niveau de la classe. Cette mthode ne possde pas particulirement de traitements, mais spcie la vue correspondant au formulaire. Le code suivant illustre un exemple de mthode de ce type annot par RequestMapping ( ) :
(...) public class MyInfoController { (...) @RequestMapping(method = RequestMethod.GET) public String showForm() { return "userinfo"; } (...) }

Spring MVC CHAPITRE 7

201

Soumission du formulaire

Lutilisation des annotations RequestMapping, ModelAttribute et InitBinding permet de dnir des mthodes de remplissage de lobjet de formulaire avec les donnes soumises et de les traiter. Ces mthodes adressent des problmatiques distinctes et senchanent dans un ordre prcis. La soumission du formulaire est traite grce lappel dune mthode de traitement de la requte par la mthode POST. Le cycle denchanement des mthodes est illustr la gure 7-5.
Figure 7-5
Requte POST

Enchanement des mthodes permettant la soumission des donnes dun formulaire

Mthodes annotes par ModelAttribute

Mthode annote par InitBinder

Mthode annote par RequestMapping avec method=RequestMethod.POST

Mthode annote par InitBinder

Vue

Les premires mthodes annotes avec RequestMapping et InitBinder (respectivement initFormObject, initBinder) fonctionnent de la mme manire que prcdemment Une validation des donnes dun formulaire peut tre mise en uvre si ncessaire. La validation lie au mappage des donnes du formulaire dans lobjet correspondant est directement intgre dans le cycle de traitements. Par contre, avec lapproche fonde sur les annotations, Spring MVC nintgre pas les validations personnalises dans ce cycle. Nanmoins, il est recommand dutiliser linterface Validator an de regrouper ces traitements. Le code de cette interface est le suivant :
public interface Validator { boolean supports(Class clazz); void validate(Object obj, Errors errors); }

La mthode supports permet de spcier sur quel Bean de formulaire peut tre applique lentit de validation. La mthode validate doit contenir limplmentation de la validation et utiliser linstance de linterface Errors associe.

202

Les frameworks de prsentation PARTIE II

Le ou les validateurs sont associs au contrleur soit par injection de dpendances, soit par une instanciation directe, cette dernire tant peu coteuse. Le code suivant de la classe RegisterValidator montre que limplmentation du validateur permet de spcier des erreurs aussi bien un niveau global ( ) que sur chaque proprit du formulaire ( ) en sappuyant sur linterface Errors :
public class RegisterValidator implements Validator { public boolean supports(Class clazz) { return RegisterData.class.isAssignableFrom(clazz); } public void validate(Object command, Errors errors) { ValidationUtils.rejectIfEmptyOrWhitespace(errors, "login", "errors.required", new Object[] {"login"}, ""); ValidationUtils.rejectIfEmptyOrWhitespace(errors, "password", "errors.required", new Object[] {"password"}, ""); ValidationUtils.rejectIfEmptyOrWhitespace( errors, "verifyPassword", "errors.required", new Object[] {"verifyPassword"}, ""); if( !data.getPassword().equals(data.getVerifyPassword()) ) { errors.rejectValue("verifyPassword", "errors.required", new Object[] {"verifyPassword"}, ""); } ValidationUtils.rejectIfEmptyOrWhitespace(errors, "firstName", "errors.required", new Object[] {"firstName"}, ""); ValidationUtils.rejectIfEmptyOrWhitespace( errors, "lastName", "errors.required", new Object[] {"lastName"}, ""); if( errors.hasErrors() ) { errors.reject("register.info.1"); } } }

La mthode de traitement ddie la soumission du formulaire doit tre annote avec RequestMapping et possder la proprit method avec la valeur RequestMethod.POST. Cette dernire prend en paramtre lobjet de formulaire, objet annot par ModelAttribute et a la responsabilit de traiter cet objet. Le code suivant illustre la mise en uvre dune mthode de ce type dans le cadre du contrleur MyInfoController, mthode nomme submitForm ( ) :
(...) public class MyInfoController { (...) @RequestMapping(method = RequestMethod.POST)

Spring MVC CHAPITRE 7

203

public String submitForm( @ModelAttribute("userinfo") UserInfoData userInfo, BindingResult result) { User user = userManager.findUser(userInfo.getLogin()); user.setPassword(userInfo.getPassword()); user.setFirstName(userInfo.getFirstName()); user.setLastName(userInfo.getLastName()); user.setEmail(userInfo.getEmail()); userManager.updateUser(user); return "userinfo"; } (...) }

Si une validation est mise en uvre, cette mthode a en charge la spcication de la vue dafchage du formulaire en cas dchec de validation. cet effet, elle doit prendre un paramtre de type BindingResult correspondant au rsultat du mappage. Ce paramtre pourra tre pass la mthode validate du validateur. Le code suivant illustre lintgration dun validateur ( ) dans les traitements de soumission du contrleur :
(...) public class MyInfoController { (...) @RequestMapping(method = RequestMethod.POST) public String submitForm( @ModelAttribute("userinfo") UserInfoData userInfo, BindingResult result) { (new RegisterValidator()).validate(userInfo, result); if (!result.hasErrors()) { User user = userManager.findUser(userInfo.getLogin()); user.setPassword(userInfo.getPassword()); user.setFirstName(userInfo.getFirstName()); user.setLastName(userInfo.getLastName()); user.setEmail(userInfo.getEmail()); userManager.updateUser(user); } return "userinfo"; } (...) }

Lors de lutilisation dune vue fonde sur JSP/JSTL, les balises du taglib form de Spring offrent un support lafchage des donnes du formulaire ou des erreurs de validation. Son utilisation est dtaille plus loin dans ce chapitre.

204

Les frameworks de prsentation PARTIE II

Support des formulaires sur plusieurs pages Spring MVC supporte la mise en uvre dun formulaire sur plusieurs pages, la session Web devant dans ce cas tre utilise. Le framework offre la possibilit de grer implicitement le stockage de lobjet de formulaire ce niveau. Pour ce faire, il convient de prciser que lobjet de formulaire est stock en session par lintermdiaire de lannotation SessionAttributes au niveau de la classe du contrleur. Cette annotation permet de spcier lidentiant correspondant. Pour librer les ressources associes lors dun succs de la soumission du formulaire sur la dernire page, il convient dutiliser la mthode setComplete sur un objet de type SessionStatus. Un paramtre de ce type peut tre pass directement en tant que paramtre de mthodes de traitement de requtes dans les contrleurs. Le code suivant est un exemple simple dutilisation de cette approche, savoir la conguration de lobjet de formulaire pour un stockage en session ( ), le passage dun paramtre de type SessionStatus ( ) et lutilisation de la mthode setComplete ( ) sur cet objet :

(...) @SessionAttributes("userinfo") public class MyInfoController { (...)

@RequestMapping(method = RequestMethod.POST) public String submitForm( @ModelAttribute("userinfo") UserInfoData userInfo, BindingResult result, SessionStatus status) { (new RegisterValidator()).validate(userInfo, result); if (!result.hasErrors()) { status.setComplete(); (...) } (...) }
}

Gestion des exceptions


Par dfaut, Spring MVC fait remonter les diffrentes exceptions leves dans le conteneur de servlets. Il est cependant possible de modier ce comportement par lintermdiaire de linterface HandlerExceptionResolver, localise dans le package org.springframework.web.servlet :
public interface HandlerExceptionResolver { ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex); }

Le dveloppeur peut choisir dutiliser ses propres implmentations ou la classe SimpleMappingExceptionResolver du package org.springframework.web.servlet.handler fournie par le framework. Cette dernire permet de congurer les exceptions traiter ainsi que les vues qui leur sont associes. Lexception est alors stocke dans la requte avec la cl exception, ce qui la rend disponible pour un ventuel afchage.

Spring MVC CHAPITRE 7

205

Cette implmentation se paramtre de la manire suivante :


<bean id="exceptionResolver" class="org.springframework.web .servlet.handler.SimpleMappingExceptionResolver"> <property name="exceptionMappings"> <props> <prop key="org.springframework.dao.DataAccessException"> dataAccessFailure </prop> <prop key="org.springframework.transaction .TransactionException"> dataAccessFailure </prop> </props> </property> </bean>

En rsum
Spring MVC met en uvre une approche intressante pour les contrleurs MVC fonde sur les annotations. Elle offre ainsi la possibilit de sabstraire de lAPI Servlet en laissant le framework raliser cette manipulation. Les signatures des points dentre des contrleurs peuvent tre adaptes en fonction des besoins et de lapproche souhaite. Au-del du cadre gnral propos par le framework, plusieurs dclinaisons sont possibles, comme lutilisation de contrleurs simples ou de formulaire pour la rcupration des paramtres de la requte, le remplissage du modle et la slection de la vue.

Spring MVC et la gestion de la vue


Cette section se penche sur la faon dont sont traites les vues au sein du framework Spring MVC.

Slection de la vue et remplissage du modle


Spring MVC abstrait compltement la vue du contrleur, masquant ainsi sa technologie et sa mise en uvre. Au niveau du contrleur, le dveloppeur a la responsabilit de remplir le modle avec les instances utilises dans la vue et de spcier son identiant. Diffrentes approches sont possibles pour cela, qui visent toutes faciliter lutilisation de Spring et la mise en uvre des contrleurs. La premire se fonde sur la classe ModelAndView dans le package org.springframework.web.servlet. Les donnes vhicules par cette classe sont utilises an de slectionner la vue, la classe lui fournissant les donnes du modle. De ce fait, le dveloppeur ne manipule plus lAPI Servlet pour remplir le modle et passer la main aux traitements de la vue.

206

Les frameworks de prsentation PARTIE II

Cette classe doit tre utilise en tant que retour dune mthode de traitement de requtes annote avec RequestMapping. Une instance de la classe ModelAndView doit alors tre instancie et remplie ce niveau. Les donnes du modle sont stockes sous forme de table de hachage. Le code suivant donne un exemple de mise en uvre de ce mcanisme ( ), dans lequel lidentiant todos correspond un nom symbolique de vue congur dans Spring MVC :
@RequestMapping("/showTodos.do") public ModelAndView showTodos(HttpServletRequest request, HttpServletResponse response) throws Exception { String listId = (...); Map<String,Object> model = new HashMap<String,Object>(); model.put("defaultList", listId); return new ModelAndView("todos", model); }

La seconde approche consiste en lutilisation de la classe Map ou Model ou ModelMap en tant que paramtre dune mthode de traitement annote avec RequestMapping. Dans ce cas, ce paramtre correspond lentit de stockage des lments du modle. Lidentiant de la vue et ces donnes sont dsormais dissocies. Si aucun identiant de vue nest prcis, Spring MVC le dduit de lURI. Par exemple, si la vue se nit par /showTodos.do, lidentiant dduit est showTodos. Il est nanmoins possible de spcier explicitement lidentiant de la vue choisie en le faisant retourner sous forme de chane de caractres par la mthode. Le code suivant illustre lutilisation de la classe ModelMap pour grer les donnes du modle, ainsi que la manire de spcier implicitement ( ) et explicitement ( ) lidentiant de la vue :
@RequestMapping("/welcome.do") public void welcome(ModelMap model) throws Exception { (...) //Lidentifiant de la vue est dduit //et correspond welcome } @RequestMapping("/showTodos.do") public String showTodos(ModelMap model) throws Exception { String listId = (...); model.addAttribute("defaultList", listId); //Lidentifiant de la vue est retourn return "todos"; }

En parallle des mthodes de traitement des requtes, il est possible dajouter dautres lments dans le modle en utilisant le retour des mthodes annotes par ModelAttribute. Dans ce cas, le retour est automatiquement ajout au modle, avant mme que la mthode de traitement de la requte soit appele.

Spring MVC CHAPITRE 7

207

Le code suivant illustre lutilisation de lannotation ModelAttribute ( ) an dajouter le retour dune mthode dans le modle et la vrication de la prsence de cet objet ( ) dans la mthode de traitement dune requte :
@ModelAttribute("user") public User getCurrentUser() { return userManager.getCurrentUser(); } @RequestMapping("/showTodos.do") public String showTodos(ModelMap model) throws Exception { User user = (User)model.get("user"); (...) return "todos"; }

Conguration de la vue
La slection des vues dans Spring MVC est effectue par le biais dune implmentation de linterface ViewResolver dans le package org.springframework.web.servlet, comme le montre le code suivant :
public interface ViewResolver { View resolveViewName(String viewName, Locale locale); }

Les sections qui suivent dtaillent les diffrentes implmentations de cette interface. La gure 7-6 illustre la hirarchie de ces classes et interfaces.
Figure 7-6
ViewResolver

Hirarchie des implmentations de linterface ViewResolver

AbstractCachingViewResolver

UrlBasedViewResolver

ResourceBundleViewResolver

XmlViewResolver

InternalResourceViewResolver

AbstractTemplateViewResolver

208

Les frameworks de prsentation PARTIE II

ResourceBundleViewResolver

La premire implmentation, ResourceBundleViewResolver, correspond une conguration au cas par cas des vues utilises. Cette approche est particulirement intressante pour une utilisation des vues fondes sur diffrentes technologies de prsentation. Sa conguration seffectue par le biais dun chier de proprits contenant le paramtrage des diffrentes vues. Cette classe peut toutefois devenir vite contraignante si la majeure partie des vues utilise la mme technologie de prsentation. Les applications qui utilisent JSP/JSTL et des vues PDF ou Excel pour afcher des tats sont un exemple de cette contrainte. Spring MVC offre une solution fonde sur le chanage de ViewResolver pour optimiser la rsolution de ce problme. Le code suivant montre de quelle manire congurer cette implmentation avec Spring MVC :
<bean id="viewResolver" class="org.springframework .web.servlet.view.ResourceBundleViewResolver"> <property name="basename" value="views"/> </bean>

La proprit basename permet de spcier le chier de proprits utilis, qui, dans lexemple suivant, a pour nom views.properties :
register_ok.class=org.springframework.web.servlet.view.RedirectView register_ok.url=welcome.action recover_password_ok.class =org.springframework.web.servlet.view.RedirectView recover_password_ok.url=welcome.action todo_lists_report.class=tudu.web.ShowTodoListsPdfView rssFeed.class=tudu.web.RssFeedView rssFeed.stylesheetLocation=/WEB-INF/xsl/rss.xsl

Ce chier possde les congurations des vues de redirection ainsi que des vues fondes sur la technologie XSLT et le framework iText.
XmlViewResolver

Les vues sont dnies par lintermdiaire de cette implmentation au cas par cas, comme prcdemment, mais dans un sous-contexte de Spring. Lutilisation de toutes les fonctionnalits et mcanismes du framework est donc envisageable, de mme que linjection de dpendances sur la classe dimplmentation des vues. La conguration de cette implmentation se ralise de la manire suivante en utilisant par dfaut le chier /WEB-INF/views.xml, tout en ncartant pas la possibilit den spcier un autre par le biais de la proprit location :
<bean id="viewResolver"

Spring MVC CHAPITRE 7

209

class="org.springframework.web.servlet.view.XmlViewResolver"> <property name="order" value="2" /> <property name="localtion" value="/WEB-INF/views.xml" /> </bean>

InternalResourceViewResolver

Limplmentation InternalResourceViewResolver utilise les URI dans le but de rsoudre les vues fondes, par exemple, sur les technologies JSP/JSTL. Ce mcanisme construit lURI partir de lidentiant de la vue puis dirige les traitements vers dautres ressources gres par le conteneur de servlets, telles que des servlets ou des JSP, comme dans lexemple ci-dessous :
<bean id="jspViewResolver" class="org.springframework.web .servlet.view.InternalResourceViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"/> </bean>

Cette implmentation gnrale sapplique toutes les vues, except celles qui sont rsolues prcdemment par une autre implmentation dans une chane de ViewResolver.
Chanage dimplmentations de ViewResolver

Spring MVC offre la possibilit de chaner les entits de rsolution des vues. Le framework parcourt dans ce cas la chane jusqu la dcouverte du ViewResolver appropri. Certaines de ces entits sappliquant toutes les vues, une stratgie par dfaut de rsolution des vues peut tre dnie. Les implmentations fondes sur UrlBasedViewResolver, telles que InternalResourceViewResolver, fonctionnent sur ce principe. Lutilisation des vues fondes sur JSP/JSTL peut tre spcie. Dautres vues, comme des redirections ou des vues gnrant des ux PDF ou Excel, sont dnies ponctuellement dans un chier. La gure 7-7 illustre un chanage dimplmentations de linterface de ViewResolver tir de Tudu Lists. Sans cette fonctionnalit, la conguration de toutes les vues au cas par cas dans un chier serait ncessaire, mme pour celles ne ncessitant pas de paramtrage spcique. Lexemple suivant dcrit la conguration du chanage de ViewResolver :
<bean id="jspViewResolver" class="org.springframework.web .servlet.view.InternalResourceViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"/> </bean>

210

Les frameworks de prsentation PARTIE II

<bean id="viewResolver" class="org.springframework.web.servlet.view.XmlViewResolver"> <property name="order" value="1"/> <property name="location" value="/WEB-INF/views.xml"/> </bean>

La proprit order permet de spcier la position du ViewResolver dans la chane. Cet exemple met en vidence que la classe InternalResourceViewResolver ne possde pas cette proprit, ce ViewResolver ne pouvant tre utilis quen n de chane.
Figure 7-7

Chanage de ViewR esolver

Chanage de ViewResolver dans Tudu Lists

XmlViewResolver

InternalResourceViewResolver

Traitements des vues spcifies dans la configuration du rsolveur

Traitements par dfaut des vues en utilisant les technologies JSP /JSTL

View

JstlView

Traitements de la vue en utilisant la technologie spcifie dans la configuration du rsolveur

Traitements de la vue en utilisant les technologies JSP/JSTL

Les technologies de prsentation


Spring MVC propose plusieurs fonctionnalits qui simplient normment la mise en uvre des technologies et frameworks de prsentation. Dans Spring MVC, une vue correspond une implmentation de linterface View du package org.springframework.web.servlet telle que dcrite dans le code suivant :
public interface View { void render(Map model, HttpServletRequest request, HttpServletResponse response); }

Cette interface possde plusieurs implmentations, localises dans le package org.springframework.web.servlet.view ou dans un de ses sous-packages. La gure 7-8 illustre la hirarchie de ses classes et interfaces.

Spring MVC CHAPITRE 7


Figure 7-8

211

Hirarchie des implmentations de linterface View

View

AbstractView

AbstractUrlBasedView

AbstractExcelView

AbstractJExcelView InternalResourceView RedirectView AbstractPdfView

AbstractXsltView JstlView TilesView

Vue de redirection

Spring MVC dnit un type de vue particulier an de rediriger les traitements vers un URI ou une URL par lintermdiaire de la classe RedirectView. Elle se congure avec limplmentation ResourceBundleViewResolver ou XmlViewResolver en imposant de dnir la proprit url. Le code suivant donne un exemple de sa mise en uvre dans Tudu Lists :
register_ok.class=org.springframework.web.servlet.view.RedirectView register_ok.url=welcome.action

La proprit url permet de spcier ladresse de redirection correspondante, laquelle est, dans notre cas, relative au contexte de lapplication. La gure 7-9 illustre lenchanement des traitements an dutiliser une vue de type RedirectView.
Figure 7-9
DispatchServlet RedirectView

Enchanement des traitements pour la vue

Mthode render Appelle la mthode render pour la vue dtermine par un ViewResolver. Appelle la mthode sendRedirect sur la requte en utilisant une proprit url.

212

Les frameworks de prsentation PARTIE II

Cette vue peut tre congure plus rapidement et directement dans la conguration des contrleurs grce au prxe redirect ( ), comme lillustre le code suivant :
public class RestoreTodoListController { (...) @RequestMapping(method = RequestMethod.POST) public String submitForm( @ModelAttribute("restoredata") RestoreData restoreData, BindingResult result, SessionStatus status) { (...) return "redirect:showTodos.action"; } }

Vue fonde sur JSP/JSTL

Spring MVC fournit une vue fonde sur JSP/JSTL, dirigeant les traitements de la requte vers une page JSP dont lURI est construit partir de lidentiant de la vue. La gure 7-10 illustre lenchanement des traitements an dutiliser une vue de type JstlView.

InternalResourceView

DispatchServlet

JstlView

Mthode render Appelle la mthode render pour la vue dtermine par un ViewResolver. Appelle la mthode forward sur une instance de RequestDispatcher.

Figure 7-10

Enchanement des traitements pour la vue

Le dveloppeur prend uniquement en charge le dveloppement de la page JSP, tandis que Spring MVC a la responsabilit de mettre disposition dans la requte tout le contenu du modle ainsi quventuellement des informations concernant le formulaire. Les balises et expressions JSTL peuvent tre utilises dune manire classique en utilisant les donnes du modle, ces dernires tant mises disposition par Spring MVC pour les pages JSP. Pour une entre ayant pour cl maVariable dans le modle, la page JSP rcupre la valeur de sa proprit maPropriete correspondante de la manire suivante :

Spring MVC CHAPITRE 7

213

<c:out value="${maVariable.maPropriete}"/>

An dutiliser les taglibs JSTL, des importations doivent tre places dans les pages JSP, comme dans le code suivant, tir de la page WEB-INF/jspf/header.jsp :
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %> <%@ taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt_rt" %>

Ainsi, lafchage de la liste des todos dans une page JSP se ralise de la manire suivante (cette liste ayant t spcie dans le modle) :
Affichage de la liste des todos: <c:forEach items="${todos}" var="todo"> - <c:out value="${todo.id}"/>, <c:out value="${todo.name}"/><br/> </c:forEach>

Au niveau des formulaires, un taglib ddi permet de raliser le mappage entre les donnes du formulaire et les champs correspondants. Pour pouvoir lutiliser, limportation suivante (tire de la page WEB-INF/jspf/header.jsp) doit tre place dans les pages JSP :
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>

Le tableau 7-4 rcapitule les balises proposes par ce taglib pour construire des formulaires.
Tableau 7-4. Balises du taglib form de gestion de formulaires
Balise Description
Dnit un lment de formulaire de type case cocher pour un attribut du Bean de formulaire. Dnit un ensemble dlments de formulaire de type case cocher pour un attribut de formulaire. Linitialisation des valeurs des lments se ralise par tir dune liste prsente dans le modle. Afche les erreurs survenues lors de la soumission dun formulaire un niveau global ou par champ. Dnit un formulaire et le rattache ventuellement un Bean de formulaire. Dnit un lment de formulaire cach pour un attribut du Bean de formulaire. Dnit un lment de formulaire de type texte pour un attribut du Bean de formulaire. Dnit un lment de liste. Dnit un ensemble dlments de liste. Linitialisation des valeurs des lments se ralise partir dune liste prsente dans le modle. Dnit un lment de formulaire de type mot de passe pour un attribut du Bean de formulaire. Dnit un lment de formulaire de type bouton radio pour un attribut du Bean de formulaire. Dnit un ensemble dlments de formulaire de type bouton radio pour un attribut du Bean de formulaire. Linitialisation des valeurs des lments se ralise partir dune liste prsente dans le modle. Dnit un lment de formulaire de type liste pour un attribut du Bean de formulaire. Cette balise doit tre utilise conjointement avec les balises option et options an de spcier les valeurs de la liste. Dnit un lment de formulaire de type zone de texte pour un attribut du Bean de formulaire.

checkbox checkboxes

errors form hidden input option options password radiobutton radiobuttons select

textarea

214

Les frameworks de prsentation PARTIE II

Ces balises permettent de rfrencer les attributs dun Bean de formulaire mis disposition dans le modle laide des techniques dcrites prcdemment la section Contrleur de gestion de formulaire . La correspondance entre le formulaire et le Bean de formulaire se ralise au niveau de la balise form par lintermdiaire du champ modelAttribute, qui spcie le nom de lentre dans le modle. Lutilisation des balises du taglib form permet dinitialiser automatiquement les champs du formulaire avec les donnes du formulaire et dafcher les ventuelles erreurs survenues. Le code suivant montre lutilisation de cette balise dans la page JSP WEB-INF/jsp/user_info.jsp de ltude de cas :
<form:form modelAttribute="userinfo"> <tr class="odd"> <td> <fmt:message key="user.info.first.name"/> </td> <td> <form:input path="firstName" size="15" maxlength="60"/> &#160;<font color="red"> <form:errors path="firstName"/></font> </td> </tr> (...) </form:form>

La balise form permet de dnir lidentiant de llment dans le modle correspondant au Bean de formulaire en se fondant sur lattribut modelAttribute ( ). Elle permet galement de dlimiter les lments du formulaire. Au sein du formulaire, les champs correspondant aux attributs du Bean de formulaire peuvent tre spcis. La correspondance entre le champ et lattribut correspondant se ralise par lintermdiaire de lattribut path de la balise. Dans notre exemple, la balise input ( ) porte sur la proprit firstName du Bean de formulaire ayant pour nom userinfo. Lafchage des erreurs, gnrales ou associes un champ, se ralise par lintermdiaire de la balise errors. Lattribut path permet de prciser les erreurs afcher. Avec une valeur *, toutes les erreurs relatives au formulaire sont afches. Avec le nom dun champ, comme dans lexemple prcdent ( ), lventuelle erreur correspondant au champ est afche.
Autres vues

Spring MVC apporte des supports pour toutes sortes de vues qui ne sont pas ncessairement fondes sur des redirections internes au conteneur de servlets (mthode forward) ou des redirections de requtes (mthode sendRedirect), notamment des classes abstraites de base pour les technologies suivantes : gnration de documents (PDF, Excel, etc.) ; gnration de rapports avec Jasper Reports ;

Spring MVC CHAPITRE 7

215

gnration de prsentations fondes sur des templates (Velocity, FreeMarker) ; gnration de prsentations fondes sur les technologies XML. Concernant les vues gnrant des documents et celles fondes sur les technologies XML, le framework Spring MVC instancie les ressources reprsentant le document par le biais de mthodes gnriques. Il dlgue ensuite les traitements une mthode de la vue an de construire le document ou de convertir le modle dans une technologie donne. Le framework reprend ensuite en main ces traitements an dexcuter ventuellement une transformation puis dcrire le rsultat sur le ux de sortie. La gure 7-11 illustre lenchanement des traitements dune vue gnrant un document avec le support PDF de Spring MVC.

AbstractPdfView

MyView

Cration du document PDF, initialisation du document en utilisant les API iText

Appel de la mthode buildPdfDocument

Construction du document PDF

Positionnement des en-ttes HTTP

Ecriture du document sur le flux de sortie

Figure 7-11

Enchanement des traitements de la vue

Dans lexemple dcrit la gure 7-11, la classe MyView tend la classe abstraite AbstractPdfView du package org.springframework.web.servlet.view an dimplmenter la mthode abstraite buildPdfDocument. Cest pourquoi la classe MyView ne contient plus que les traitements spciques lapplication pour la construction du document, son instanciation et son renvoi au client tant encapsuls dans la classe AbstractPdfView.

216

Les frameworks de prsentation PARTIE II

En rsum
Approfondissant les principes de gestion de la prsentation au sein du framework Spring MVC, nous avons vu que ce dernier met en uvre des mcanismes de mise en relation dun identiant et de sa vue, tout en favorisant la coexistence de vues fondes sur diverses technologies. Le framework permet lutilisation dun nombre important de technologies de prsentation. La mise disposition des donnes prsentes dans le modle pour les vues est ralise automatiquement par le framework.

Support de REST (Representational State Transfer)


La version 3.0 de Spring introduit le support natif de la technologie REST an dutiliser les URI conformes ce format tout en suivant le modle de programmation de Spring MVC fond sur les annotations.
La technologie REST Cette technologie correspond une manire de construire des applications pour les systmes distribus. REST nest pas un protocole ou un format, mais correspond au style architectural original du Web, bti sur les principes simples suivants : LURI est trs important puisque, dans ce contexte, connatre ce dernier doit sufre pour accder la ressource. Il nest plus besoin de spcier des paramtres supplmentaires. De plus, la manipulation de la ressource se fonde sur lutilisation des oprations du protocole HTTP (GET, POST, PUT et DELETE, essentiellement). Chaque opration est autosufsante, et aucun tat nest stock au niveau de la ressource. Le client a la responsabilit du stockage de cet tat. En parallle, la technologie utilise des standards hypermdias tels que HTML ou XML an de raliser les liens vers dautres ressources et dassurer ainsi la navigation dans lapplication. Il est possible de mettre en uvre des architectures orientes services de manire simple en utilisant des services Web interapplicatifs. La technologie REST propose ainsi une solution de rechange intressante et plus simple au mode RPC et, dans la plupart des cas, SOAP.

Avec la technologie REST, les paramtres font partie intgrante de lURI, comme lillustre le code suivant avec un exemple dURI contenant le paramtre id :
/<alias-webapp>/<ressource-name>/{id}

Spring 3.0 offre non seulement la possibilit dcrire des contrleurs Web REST, mais propose aussi un composant client permettant deffectuer des requtes REST, le RestTemplate.

Contrleur Web REST


Spring MVC offre la possibilit de passer en paramtres des mthodes des contrleurs des valeurs en se fondant sur lannotation PathVariable. Cette dernire fonctionne dune manire

Spring MVC CHAPITRE 7

217

similaire lannotation RequestParam en rfrenant les paramtres prsents dans ladresse daccs, comme lillustre le code suivant ( ) :
@RequestMapping(value = "/todo/{format}/{todoId}") public ModelAndView getTodo(@PathVariable String format, @PathVariable String todoId) { (...) }

Avec REST, il est dsormais possible dutiliser dautres mthodes HTTP que celles utilises habituellement dans les navigateurs par les applications Web classiques, savoir les mthodes GET et POST. Dans ce contexte, lappel dune ressource ralisant la suppression dune entit seffectue avec la mthode DELETE. La mthode correspondante du contrleur doit spcier la mthode HTTP daccs au niveau de lannotation RequestMapping, comme dans le code suivant ( ) :
@RequestMapping( value = "/todo/{todoId}", method = RequestMethod.DELETE ) public void deleteTodo(@PathVariable String todoId, HttpServletResponse response) { todoManager.remove(todoId); // pas de rendu de vue response.setStatus(HttpServletResponse.SC_OK); }

Lappel de cette mthode peut se raliser dans une page JSP par le biais de la balise form du taglib form de Spring, comme dans le code suivant ( ) :
<form:form method="delete"> <input type="submit" value="Supprimer un todo"/></p> </form:form>

En gardant le mme modle de programmation que celui de Spring MVC, le support REST de Spring permet de mettre en uvre REST de manire intressante. Tous les mcanismes de Spring MVC sont utilisables dans ce contexte, contribuant dautant la simplicit de mise en uvre de cette technologie.

Le RestTemplate
Le RestTemplate est la classe centrale du support client REST dans Spring. Il permet deffectuer des requtes HTTP selon les diffrentes mthodes du protocole, tout en facilitant la gestion des rponses, avec la possibilit de transformer directement le ux de rponses en objets Java. Le RestTemplate fonctionne suivant la philosophie des templates daccs aux donnes de Spring, dont les principes sont prsents au chapitre 10. Il peut nanmoins tre utilis directement, sans connatre ces principes sous-jacents, lessentiel consistant savoir que le

218

Les frameworks de prsentation PARTIE II

RestTemplate gre les connexions HTTP et laisse le dveloppeur se concentrer sur le code

applicatif. Le RestTemplate peut tre instanci de faon programmatique, mais il est plus judicieux de le dclarer dans le contexte Spring, an de proter de linjection de dpendances, notamment pour de la conguration plus ne :
<bean id="restTemplate" class="org.springframework.web.client.RestTemplate"> <property name="requestFactory"> <bean class="org.springframework.http.client. CommonsClientHttpRequestFactory" /> </property> </bean>

Le RestTemplate est dclar comme tout autre Bean, avec la classe correspondante ( ). Pour effectuer les accs HTTP, le RestTemplate utilise une abstraction, la ClientHttpRequestFactory, que lon positionne avec la proprit requestFactory ( ). Nous utilisons dans notre exemple une implmentation fonde sur la bibliothque Jakarta Commons HttpClient, qui offre des possibilits intressantes de conguration (authentication, pool de connexions, etc.). Une fois congur, le RestTemplate peut tre utilis pour rcuprer le rsultat dune requte HTTP, par exemple pour appeler la mthode getTodo du contrleur REST de la section prcdente :
String xml = restTemplate.getForObject( "http://localhost:8080/rest/todo/{format}/{todoId}", String.class, "xml","1");

La mthode getForObject du RestTemplate prend en premier paramtre lURL appeler ( ). On remarque lutilisation de la syntaxe {nomParametre} pour indiquer les diffrents paramtres ; dans notre cas, le format souhait de la rponse (XML, HTML ou PDF) et lidentiant du Todo. Le deuxime paramtre de getForObject est la classe de retour attendue ( ). Le RestTemplate est en effet capable de transformer le ux de la rponse en un objet Java. Par dfaut, les transformations sont limites (chanes de caractres ou tableau doctets), mais nous verrons par la suite que ce mcanisme est paramtrable. Dans notre exemple, nous nous contentons de rcuprer la rponse sous forme de chane de caractres. La mthode getForObject accepte en derniers paramtres une liste variable dobjets, qui constituent les paramtres insrer dans la requte HTTP ( ). La combinaison de lURL demande et des paramtres fera que lURL appele sera la suivante :
http://localhost:8080/rest/todo/xml/1

La rponse est bien sr gre par notre contrleur REST, qui renvoie pour une telle requte un ux XML :
<todo> <todoId>1</todoId>

Spring MVC CHAPITRE 7

219

<description>todo 1</description> <priority>1</priority> <completed>true</completed> <hasNotes>true</hasNotes> </todo>

La variable locale xml dans lexemple ci-dessus contiendra donc ce code XML. Il est important de noter que lutilisation du RestTemplate nest pas limite linterrogation de contrleurs REST implments par Spring MVC. La rponse pourrait tout aussi bien tre gnre par un autre type de contrleur Web, dans un langage diffrent de Java. Nous venons de voir comment faire une requte GET (au sens HTTP du terme) avec le RestTemplate. Celui-ci propose une API complte pour effectuer dautres types de requtes, suivant les mthodes du protocole HTTP. Nous pouvons effectuer une requte DELETE, par exemple, sur la mthode deleteTodo de notre contrleur :
restTemplate.delete( "http://localhost:8080/rest/todo/{todoId}", "1");

Cet appel va supprimer le Todo didentiant 1. Aucune rponse nest attendue. Le tableau 7-5 rcapitule les principales mthodes disponibles dans le RestTemplate. Remarquez lexistence de la mthode execute, qui, moyennant une utilisation plus complexe, permet de construire des requtes et dexploiter les rponses pour des besoins avancs, selon le principe des templates Spring.
Tableau 7-5. Mthodes du RestTemplate
Mthode HTTP Mthode du RestTemplate

DELETE GET HEAD OPTIONS POST PUT Toutes

delete(String, String, ) delete(String, Class, String, ) headForHeaders(String, String ) optionsForAllow(String, String ) postForLocation(String, Object, String ) put(String, Object, String ) execute(String, HttpMethod, RequestCallback, ResponseExtractor, String )

Nous avons vu dans notre premire utilisation du RestTemplate quil facilitait grandement lappel de services REST, mais que sa gestion de la rponse tait relativement limite : nous avons rcupr un document XML sous forme de chane de caractres. Cette rponse contient les informations demandes, mais ncessite une exploitation (analyse du code XML), qui savre fastidieuse si elle doit tre faite au niveau de lappel. Lidal serait de rcuprer lobjet mtier attendu, cest--dire une instance de Todo, le RestTemplate prenant sa charge la transformation.

220

Les frameworks de prsentation PARTIE II

Le RestTemplate propose un mcanisme de convertisseur qui permet de contrler trs nement la conversion des objets Java qui lui sont passs ainsi que ceux quil renvoie. Nous allons ici nous intresser aux objets renvoys, en convertissant le ux XML reu prcdemment en un objet Todo. Cette conversion nous permettra deffectuer lappel suivant, pour lequel nous demandons et rcuprons directement un Todo, plutt quun document XML :
Todo todo = restTemplate.getForObject( "http://localhost:8080/rest/todo/{format}/{todoId}", Todo.class, "xml","1");

Pour arriver ce rsultat, il faut implmenter un HttpMessageConverter, qui va se charger de la conversion de la rponse, puis lassigner au RestTemplate. Voici le code de limplmentation de TodoHttpMessageConverter :
package tudu.web.rest; (...) import org.springframework.http.HttpInputMessage; import org.springframework.http.HttpOutputMessage; import org.springframework.http.MediaType; import org.springframework.http.converter.HttpMessageConverter; import tudu.domain.model.Todo; import com.thoughtworks.xstream.XStream; public class TodoHttpMessageConverter implements HttpMessageConverter<Todo> { public List<MediaType> getSupportedMediaTypes() { return Collections.singletonList( new MediaType("text","xml") ); } public boolean supports(Class<? extends Todo> clazz) { return Todo.class.equals(clazz); } public Todo read(Class<Todo> clazz, HttpInputMessage inputMessage) throws IOException { XStream xstream = new XStream(); xstream.alias("todo", Todo.class); return (Todo) xstream.fromXML(inputMessage.getBody()); } public void write(Todo t, HttpOutputMessage outputMessage) throws IOException { throw new UnsupportedOperationException(); } }

Spring MVC CHAPITRE 7

221

Le rle dun HttpMessageConverter est deffectuer des transformations dobjets Java vers des messages HTTP et inversement. Il doit donc indiquer le type de mdia quil est capable de grer ( ) : dans notre cas les rponses de type text/xml, ainsi que la hirarchie de classes quil peut convertir ( ), cest--dire des Todos. La mthode read nous intresse particulirement, car cest elle qui se charge de la transformation de la rponse en Todo. Nous recevons ici une reprsentation XML dun Todo, et nous utilisons XStream pour la convertir en objet Java ( ). XStream prsente lintrt dtre trs simple dutilisation et concis, mais tout autre mcanisme de dsrialisation aurait pu tout aussi bien convenir. Lopration inverse, qui consiste transformer lobjet Java en message HTTP, ne nous intressant pas, elle nest pas implmente ( ). Le convertisseur tant crit, il faut maintenant le positionner au sein du RestTemplate, grce sa proprit messageConverters, qui contient la liste de ses diffrents convertisseurs :
<bean id="restTemplate" class="org.springframework.web.client.RestTemplate"> (...) <property name="messageConverters"> <list> <bean class="org.springframework.http.converter. ByteArrayHttpMessageConverter"/> <bean class="org.springframework.http.converter. StringHttpMessageConverter"/> <bean class="tudu.web.rest.TodoHttpMessageConverter" /> </list> </property> </bean>

Un RestTemplate dispose de convertisseurs positionns par dfaut, qui grent les conversions sous forme de chanes de caractres ou de tableau doctets. Il faut les positionner explicitement ds que nous paramtrons la proprit messageConverters, an que ces cas simples soient toujours grs ( ). Notre convertisseur de Todo est lui paramtr au repre . Le mcanisme de convertisseurs apporte au RestTemplate une extensibilit et une adaptabilit trs intressantes, lui permettant de grer la conversion des messages HTTP en objets Java, an dobtenir un code applicatif le plus pur possible.

En rsum
Spring 3.0 apporte un support REST Spring MVC. Il devient alors possible dimplmenter des contrleurs REST en suivant le modle de programmation de Spring MVC, fond sur les annotations. Le support client nest pas en reste, avec le RestTemplate, qui propose une API trs simple et extensible an dinterroger des services REST (indpendamment de leur technologie) et dexploiter au mieux leur rponse.

222

Les frameworks de prsentation PARTIE II

Mise en uvre de Spring MVC dans Tudu Lists


Les principaux concepts et composants de Spring MVC ayant t introduits, nous pouvons passer leur mise en pratique dans notre tude de cas.

Conguration des contextes


Le premier contexte renvoie lapplication Web. Il est charg avec le support de la classe ContextLoaderListener en utilisant les chiers dont le nom correspond au pattern /WEB-INF/ applicationContext*.xml. Le second contexte est utilis par Spring MVC et est charg par la servlet DispatcherServlet en utilisant le chier action-servlet.xml localis dans le rpertoire WEB-INF. Les diffrentes entits relatives Spring MVC sont dnies dans ce chier. Cette servlet est congure dans le chier web.xml de lapplication Web, comme lillustre le code suivant :
<?xml version="1.0" encoding="UTF-8"?> <web-app> (...) <servlet> <servlet-name>action</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>action</servlet-name> <url-pattern>*.action</url-pattern> </servlet-mapping> (...) </web-app>

Dans le chier action-servlet.xml suivant, lapproche fonde sur les annotations a t active en se fondant sur la balise component-scan ( ) de lespace de nommage context (seuls les contrleurs localiss dans les packages dont le nom commence par tudu.web tant utiliss) :
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/ context/spring-context.xsd"> <context:component-scan base-package="tudu.web" /> (...) </beans>

Spring MVC CHAPITRE 7

223

Commons Validator

Le projet Spring Modules offre le support de Commons Validator, le framework dApache visant spcier les rgles de validation par dclaration communment utilis avec Struts. Commons Validator se congure de la manire suivante dans le cadre de Spring MVC :
<bean id="validatorFactory" class="org.springmodules.commons .validator.DefaultValidatorFactory"> <property name="validationConfigLocations"> <list> <value>/WEB-INF/validator-rules.xml</value> <value>/WEB-INF/validation.xml</value> </list> </property> </bean> <bean id="beanValidator" class="org.springmodules.commons .validator.DefaultBeanValidator"> <property name="validatorFactory" ref="validatorFactory"/> </bean>

Dans chaque contrleur de gestion de formulaire, le Bean beanValidator doit tre inject par lintermdiaire de lannotation Autowired. Le nom du Bean de formulaire utilis par le contrleur permet de dterminer la rgle utiliser de la conguration de la validation WEB-INF/validation.xml. La mthode validate de ce Bean est ensuite utilise an de raliser la validation.

Implmentation des contrleurs


Au travers de lapplication Tudu Lists, diffrents mcanismes et types de contrleurs sont implments par le biais des annotations RequestMapping, ModelAttribute et InitBinder dcrites dans les sections prcdentes. Les sections suivantes se penchent sur la faon dont sont mis en uvre des contrleurs entre multiple et de formulaire ralisant respectivement un afchage de donnes et une gestion de formulaire HTML. La prsentation associe ces deux contrleurs utilise les technologies JSP/JSTL.
Contrleur simple

Le contrleur ShowTodosAction du package tudu.web dispose de traitements pour afcher les todos dune liste. Comme lillustre lextrait de code ci-aprs, il utilise Spring MVC laide des lments suivants : Annotation Controller au niveau de la classe ( ) an de prciser que cette dernire joue le rle dun contrleur dans Spring MVC. Annotation RequestMapping au niveau de la mthode showTodos ( ) an de dnir le point dentre. Plusieurs points dentre peuvent tre spcis ce niveau.

224

Les frameworks de prsentation PARTIE II

Annotation RequestParam an de rcuprer directement en tant que paramtres du point dentre les paramtres de la requte Web. Dans notre cas, le paramtre optionnel listId ( ) est pris directement dans la requte sil est prsent. Dans le cas contraire, sa valeur vaut null. Paramtre de type ModelMap ( ) an de manipuler les donnes du modle. Des ajouts dans ce dernier peuvent tre raliss par lintermdiaire de la mthode addAttribute de la classe ( ). Type de retour an de prciser la vue utilise pour prsenter les donnes ( ).
@Controller public class ShowTodosController { (...) @RequestMapping("/secure/showTodos.action") public String showTodos( @RequestParam(value="listId", required=false) String listId, ModelMap model ) { log.debug("Execute show action"); Collection<TodoList> todoLists = new TreeSet<TodoList>( userManager.getCurrentUser().getTodoLists()); if (!todoLists.isEmpty()) { if (listId != null) { model.addAttribute("defaultList", listId); } else { model.addAttribute("defaultList", todoLists.iterator().next().getListId()); } } return "todos"; } }

Aucune conguration nest requise dans le chier WEB-INF/action-servlet.xml pour le contrleur. Les congurations relatives Spring MVC ( ) et linjection de dpendances ( ) se ralise directement dans la classe par lintermdiaire dannotations, comme lillustre le code suivant :
@Controller public class ShowTodosController { @Autowired private UserManager userManager; (...) @RequestMapping("/secure/showTodos.action") public String showTodos(

Spring MVC CHAPITRE 7

225

@RequestParam(value="listId", required=false) String listId, ModelMap model (...) } }

La manire daccder aux points dentre du contrleur est dnie dans les annotations RequestMapping. Aucune conguration supplmentaire nest ncessaire. Dans le cas prcdent, le contrleur ShowTodosController est accessible partir de lURI /secure/showTodos.action. Cette tude de cas met galement en pratique le mcanisme de chanage de ViewResolver. Ainsi, retrouve-t-on dans le chier /WEB-INF/action-servlet.xml la conguration de plusieurs ViewResolver : Le premier est implment par la classe ResourceBundleViewResolver, qui utilise le chier de proprits views.properties an de congurer les vues. Le deuxime est implment par la classe XmlViewResolver, qui utilise le chier /WEBINF/views.xml pour congurer les vues. Le dernier est implment par la classe InternalResourceViewResolver, qui se fonde, dans notre cas, sur une vue JSP/JSTL. Il constitue la stratgie de rsolution par dfaut et est utilis dans le cas o un identiant de vue ne peut tre rsolu par les deux entits prcdemment dcrites. La gure 7-12 illustre cette chane en soulignant les identiants des vues congures dans les deux premiers ViewResolver.
ViewResolver1 (views.properties) ViewResolver2 (views.xml) ViewResolver3 (JSP / JSTL)

Vues : register_ok, recover_password_ok, rssFeed

Vues : todol_lists_report, backup

Vues : toutes les pages JSP

Figure 7-12

Chanage des ViewResolver dans Tudu Lists

Le contrleur utilise la vue todos qui est rsolue par le dernier ViewResolver et correspond donc la page JSP todos.jsp localise dans le rpertoire /WEB-INF/jsp/.
Contrleur de gestion de formulaire

La mise en uvre dun contrleur de gestion de formulaire nest gure plus complexe que celle dun contrleur simple : un Bean est utilis pour les donnes du formulaire, et deux points dentre doivent tre dnis, un pour le chargement du formulaire, lautre pour sa validation.

226

Les frameworks de prsentation PARTIE II

Dtaillons le contrleur MyInfosController du package tudu.web, qui permet de modier les informations dun utilisateur de lapplication. Comme lillustre lextrait de code ci-aprs, ce contrleur utilise Spring MVC laide des lments suivants : Annotations Controller et RequestMapping au niveau de la classe an de dnir la classe en tant que contrleur et lURI daccs ce dernier ( ). Mthode showForm ( ) appele par lintermdiaire dune mthode GET et congure avec lannotation RequestMapping. Cette mthode a la responsabilit de charger les donnes du formulaire. Mthode submitForm ( ) appele an de traiter les donnes soumises par le formulaire avec la mthode HTTP POST et congure avec lannotation RequestMapping. Utilisation explicite de la validation Commons Validator dans le corps de la mthode submitForm ( ). Spcication des vues utilises pour lafchage suite la soumission du formulaire par lintermdiaire des retours des deux mthodes prcdentes ( ).
@Controller @RequestMapping("/secure/myinfos.action") public class MyInfoController { (...) @RequestMapping(method = RequestMethod.GET) public String showForm(HttpServletRequest request, ModelMap model) { String login = request.getRemoteUser(); User user = userManager.findUser(login); UserInfoData data=new UserInfoData(); data.setPassword(user.getPassword()); data.setVerifyPassword(user.getPassword()); data.setFirstName(user.getFirstName()); data.setLastName(user.getLastName()); data.setEmail(user.getEmail()); model.addAttribute("userinfo", data); return "userinfo"; } @RequestMapping(method=RequestMethod.POST) public String submitForm( HttpServletRequest request, @ModelAttribute("userinfo") UserInfoData userInfo, BindingResult result) { beanValidator.validate(userInfo, result); if (!result.hasErrors()) { String password = userInfo.getPassword(); String firstName = userInfo.getFirstName(); String lastName = userInfo.getLastName();

Spring MVC CHAPITRE 7

227

String email = userInfo.getEmail(); String login = request.getRemoteUser(); User user = userManager.findUser(login); user.setPassword(password); user.setFirstName(firstName); user.setLastName(lastName); user.setEmail(email); userManager.updateUser(user); } return "userinfo"; } }

Aucune conguration nest requise dans le chier WEB-INF/action-servlet.xml pour le contrleur. Comme le montre le code suivant, les congurations relatives Spring MVC ( ) et linjection de dpendances ( ) se ralisent directement dans la classe par lintermdiaire dannotations :
@Controller public class MyInfoController { @Autowired private UserManager userManager; @Autowired private DefaultBeanValidator beanValidator; (...) @RequestMapping(method = RequestMethod.GET) public String showForm(HttpServletRequest request, ModelMap model) { (...) } @RequestMapping(method=RequestMethod.POST) public String submitForm( HttpServletRequest request, @ModelAttribute("userinfo") UserInfoData userInfo, BindingResult result) { (...) } }

La manire daccder aux points dentre du contrleur est dnie dans les annotations RequestMapping. Aucune conguration supplmentaire nest ncessaire. Dans lexemple prcdent, le contrleur MyInfoController est accessible partir de lURI /secure/ myinfos.action par lintermdiaire des mthodes GET et POST.

228

Les frameworks de prsentation PARTIE II

Les donnes du formulaire soumises peuvent tre valides par le biais de labstraction Validator vue prcdemment, et plus particulirement les implmentations constituant le support de Commons Validator, qui permet de rutiliser les rgles de validation userinfo. Le contrleur utilise la vue user_info dans le but dafcher le formulaire dans les cas dchec ou de succs lors de la validation. Cette vue est rsolue par le dernier ViewResolver de la chane et correspond donc la page JSP user_info.jsp localise dans le rpertoire /WEBINF/jsp/. Cette page doit tre modie an de remplacer les taglibs de gestion des formulaires de Struts par ceux de Spring MVC. Comme lillustre le code suivant, le framework met en uvre le taglib form an de remplir les champs du formulaire ( ) et dafcher les ventuelles erreurs de validation ( ) :
(...) <form:form modelAttribute="userinfo" focus="firstName"> <font color="red"> <b><form:errors path="*"/></b> </font> (...) <form:input path="firstName" size="15" maxlength="60"/> &#160;<font color="red"> <form:errors path="firstName"/></font> (...) <input type="submit" value="<fmt:message key="form.submit"/>"/> <input type="button" onclick="document.location.href='<c:url value="../welcome.action"/>';" value="<fmt:message key="form.cancel"/>"/> </form>

Le contrleur afche la page de formulaire suite au succs de la soumission des donnes par lappel de la mthode showForm dans la mthode onSubmit. Lutilisation dune autre vue grce aux mthodes setSuccessView et getSuccessView serait aussi possible.

Implmentation de vues spciques


Tudu Lists utilise plusieurs technologies de prsentation an de gnrer diffrents formats de sortie (HTML, XML, RSS, PDF). Spring MVC offre une infrastructure facilitant leur utilisation conjointement dans une mme application. Dans la mesure o lentit ViewResolver utilise prcdemment pour les vues utilise les technologies JSP et JSTL, elle ne peut servir pour les vues dcrites ci-dessous. Dans les sections suivantes, nous utiliserons donc limplmentation XmlViewResolver an de les congurer.
XML

Lapplication Tudu Lists permet de sauvegarder au format XML les informations contenues dans une liste de todos. Cette fonctionnalit est implmente par le contrleur BackupTodoListController du package tudu.web, qui a la responsabilit de charger la liste correspondant

Spring MVC CHAPITRE 7

229

lidentiant spci puis de la placer dans le modle an de la rendre disponible lors de la construction de la vue. Ce contrleur dirige les traitements vers la vue ayant pour identiant backup la n de ses traitements. Cette vue, implmente par la classe BackupTodoListView du package tudu.web, est rsolue par le second ViewResolver de la chane. Sa conguration se trouve dans le chier views.xml localis dans le rpertoire WEB-INF. Elle utilise le support de la classe AbstractXsltView de Spring MVC an de gnrer une sortie XML, comme dans le code suivant :
public class BackupTodoListView extends AbstractXsltView { (...) protected Node createDomNode(Map model, String rootName, HttpServletRequest request, HttpServletResponse response) throws Exception { TodoList todoList = (TodoList)model.get("todoList"); Document doc = todoListsManager.backupTodoList(todoList); return new DOMOutputter().output( doc ); } }

la n de lexcution de la mthode createDomNode, la classe BackupTodoListView rend la main sa classe mre an de raliser ventuellement une transformation XSLT et dcrire le contenu sur le ux de sortie. Lutilisation de XmlViewResolver permet dinjecter une instance du composant TodoListsManager dans la classe de la vue, comme dcrit dans le chier views.xml suivant :
<bean id="backup" class="tudu.web.BackupTodoListView"> <property name="todoListsManager" ref="todoListsManager"/> </bean>

PDF

Lapplication de ltude de cas permet galement de gnrer un rapport au format PDF avec les informations contenues dans une liste de todos. Cette fonctionnalit est implmente par lintermdiaire du contrleur ShowTodoListsReportController du package tudu.web, qui a la responsabilit de charger la liste correspondant lidentiant spci puis de la placer dans le modle an de la rendre disponible lors de la construction de la vue. Ce contrleur dirige les traitements vers la vue ayant pour identiant todo_lists_report la n de ses traitements. Cette vue, implmente par la classe ShowTodoListsPdfView du package tudu.web, est rsolue par le second ViewResolver de la chane. Sa conguration se trouve dans le chier views.xml localis dans le rpertoire WEB-INF. Elle utilise le support de la classe AbstractPdfView de Spring MVC an de gnrer une sortie PDF par le biais du framework iText, comme dans le code suivant :
public class ShowTodoListsPdfView extends AbstractPdfView { protected void buildPdfDocument(

230

Les frameworks de prsentation PARTIE II

Map model, Document doc, PdfWriter writer, HttpServletRequest req, HttpServletResponse resp) throws Exception { TodoList todoList=(TodoList)model.get("todolist"); doc.add(new Paragraph(todoList.getListId())); doc.add(new Paragraph(todoList.getName())); (...) } }

La classe mre de la classe ShowTodoListsPdfView a la responsabilit dinstancier les diffrentes classes de iText an de les lui fournir. la n de lexcution de la mthode buildPdfDocument, la classe ShowTodoListsPdfView rend la main sa classe mre pour crire le contenu sur le ux de sortie. Notons que cette vue aurait pu aussi bien tre congure dans le chier views.properties, puisquelle ne ncessite pas dinjection de dpendances.

Conclusion
Pour mettre en uvre le patron de conception MVC, Spring MVC offre une approche intressante fonde sur les mcanismes dinjection de dpendances et les mtadonnes congures dans des annotations. Les principaux atouts du framework rsident dans son ouverture ainsi que dans la modularit et lisolation des composants du patron MVC. Le dveloppement des applications utilisant diffrentes technologies sen trouve facilit, et le changement de briques nimpacte pas le reste de lapplication ni lextension du framework. Lutilisation de linjection de dpendances de Spring dans limplmentation du pattern MVC permet de congurer avec une relle facilit ces diffrents composants ainsi que leurs dpendances. Cette conguration est centralise dans le contexte applicatif de Spring, lequel peut de la sorte mettre disposition toute la puissance du conteneur lger. Spring MVC propose une approche fonde sur les annotations an dimplmenter les contrleurs. Introduite avec la version 2.5 du framework, cette approche dune grande facilit dutilisation permet de sabstraire de lAPI Servlet. Le framework propose ainsi une gestion des formulaires dune exibilit remarquable. Le framework Spring MVC propose enn une sparation claire entre le contrleur et la vue ainsi quun support pour les diffrentes technologies et frameworks de prsentation. En rsum, ce framework fournit un socle solide pour dvelopper des applications Web sans donner la possibilit dabstraire la navigation et lenchanement des pages. Un framework tel que Spring Web Flow, prsent en dtail au chapitre suivant, peut sappuyer sur ce socle an de rsoudre cette problmatique.

You might also like