lundi 7 mars 2011

Utilisation de Spring MVC dans un projet WTP/Maven

Après avoir installé Eclipse et configuré notre premier projet web à l'aide de maven, nous allons aujourd'hui nous intéresser à un Framework très en vogue : Spring

Dans cet article, nous allons mettre en œuvre un petit site d'exemple sous forme d'un login en utilisant les possibilités MVC de Spring.

Installation de Spring

Grâce à Maven, nous allons pouvoir ajouter facilement les librairies nécessaires à Spring pour notre application.
Il suffit d'ajouter l'artifact de Spring dans le fichier pom.xml. Pour celà, nous avons 2 possibilités :

Ajouter directement le code dans le fichier

<dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>3.0.5.RELEASE</version>
        <optional>false</optional>
 </dependency>

Nous allons demander directement le téléchargement du module MVC de Spring, Maven va alors se charger pour nous de télécharger toutes les dépendances nécessaires à l'utilisation de spring

Utiliser le plugin IAM

Le 1er onglet de configuration propose 4 sous-onglets, dont  un nommé Dependencies :

En cliquant sur New, nous pouvons saisir directement les informations concernant la librairie


Le bouton [...] en haut à droite offre une option intéressante, il suffit de saisir une partie du nom de la librairie pour que maven télécharge les artifacts disponibles correspondant aux patterns saisis.


Sur cet écran, nous pouvons télécharger spring-webmvc en version 3.0.5.RELEASE. Une fois enregistré, le fichier pom.xml est modifié de la même manière que manuellement.

Si nous regardons les librairies, nous voyons que Maven a téléchargé toutes les librairies nécessaires à l'utilisation de Spring en mode MVC


Nous voyons par ailleurs que l'ensemble des librairies sont téléchargées dans le repository local de maven (Ici C:\Users\Eric\.m2\). Ce repository sera commun à tous nos projets maven.

Nous allons également avoir besoin de 2 autres librairies que nous ajouterons directement dans notre fichier pom.xml :


   <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>servlet-api</artifactId>
        <version>2.5</version>
        <optional>false</optional>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>jstl</artifactId>
        <version>1.2</version>
        <optional>false</optional>
    </dependency>

Configuration du projet Web

Maintenant que nous disposons de toutes les libraires nécessaires à la réalisation de notre projet, il nous faut créer et configurer les fichiers.

Le premier fichier à configurer est le fichier \src\main\webapp\WEB-INF\web.xml. Nous allons demander à spring de s'occuper du mapping de notre application. Pour cela, il nous faut définir une servlet spécifique.

<servlet>
   <servlet-name>sample</servlet-name>
   <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
   <load-on-startup>1</load-on-startup>
</servlet>

 Nous allons également définir un mapping pour renvoyer toutes les requêtes finissant par .form dans
 la servlet que nous venons de créer.
 
<servlet-mapping>
    <servlet-name>sample</servlet-name>
    <url-pattern>*.form</url-pattern>
</servlet-mapping>

Le fichier web.xml est maintenant configuré pour transmettre toutes les requêtes se terminant par form à la classe DispatcherServlet, il ne nous reste plus qu'à configurer Spring pour lui indiquer vers quelle classe transmettre les requêtes en fonction de leur URL.

Notre servlet s'appelant sample, le fichier de configuration Spring doit, par convention, se nommer sample-servlet.xml et se trouver dans le répertoire WEB-INF de notre projet.

Ce fichier va contenir la définition de nos beans.

Le bean est le concept à la base de spring : Il s'agit d'une description XML faisant référence à une classe java. Ce formalisme permet de mettre en œuvre les 2 concepts fondamentaux de spring : L'inversion de contrôle et l'injection de dépendance. Spring et sa syntaxe feront l'objet d'un article à part entière. L'important, ici, est de comprendre que nous allons définir un ensemble d'objets (appelés bean) au format XML que Spring va utiliser pour réaliser son mapping.


<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
               http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">




     <!-- Spécification du mapping -->
     <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <prop key="/login.form">loginController</prop>
            </props>
        </property>
    </bean>

    <!-- les contrôleurs de l'application -->
    <bean id="loginController" class="com.myjavaland.spring.mvc.LoginController" />
 
    <!-- le résolveur de vues -->
    <bean
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass">
            <value>org.springframework.web.servlet.view.JstlView</value>
        </property>
        <property name="prefix">
            <value>/WEB-INF/views/</value>
        </property>
        <property name="suffix">
            <value>.jsp</value>
        </property>
    </bean>


</beans>

Nous définissons 3 beans dans ce fichier :
  • Le premier bean va indiquer à Spring quelle méthodologie de mapping, nous allons utiliser. Le bean s'appelle SimpleUrlHandlerMapping, ce qui signifie que nous allons utiliser le nom de l'URL pour lui associer un contrôleur. La propruniété mappings va nous permettre de spécifier que l'url /login.form va être traité par le contrôleur loginController
  • Le 2ème bean est le contrôleur proprement dit. Nous lui donnons un Id afin qu'il puisse être identifié par les autres beans (notamment le bean de mapping défini auparavant)  ainsi que le nom de la classe associée. Nous verrons plus tard comment cette classe est codée.
  • Le 3ème est dernier bean va nous permettre de spécifier comment vont être trouvées les vues de notre modèle MVC. Nous voyons ici que nous allons utiliser JsltView et que nos vues vont avoir le pattern /WEB-INF/views/*.jsp.
Développement des vues et du contrôleur.

 Notre application est maintenant configurée, il ne nous reste plus qu'à développer nos différents composants : les vues et le contrôleur.

La page d'index :


La première chose à faire est de coder notre page de démarrage. C'est elle qui affichera le formulaire de login. Nous créerons cette page dans le répertoire webapp de notre projet et nous la nommerons index.html

<html>
<body>
<form method="POST" action="login.form">
    <table align="center">
        <tr>
            <td colspan="2" align="center">Connexion</td>
        </tr>
        <tr>
            <td>Login</td>
            <td><input type="text" name="login" /></td>
        </tr>
        <tr>
            <td>Password</td>
            <td><input type="text" name="password" /></td>
        </tr>
        <tr>
        <tr>
            <td colspan="2" align="center"><input type="submit" /></td>
        </tr>
    </table>
</form>
</body>
</html>

Nous voyons dans ce code que nous avons définit 2 champs : login et password et que l'appui sur le bouton de soumission appelle la page login.form

Le contrôleur :

Dans le fichier Spring que nous venons d'écrire, nous avons défini le nom de notre contrôleur :  com.myjavaland.spring.mvc.LoginController. Nous allons donc créer cette classe dans le répertoire src/main/java de notre application. Pour fonctionner, cette classe doit implémenter l'interface org.springframework.web.servlet.mvc.Controller. Cette interface impose l'implémentation d'une méthode : handleRequest.


Cette méthode prend 2 paramètres très connus des développeurs de servlets : HttpServletRequest et HttpServletResponse. Ces 2 paramètres vont nous permettre de travailler avec les données de la requêtes (paramètres, attributs, locales, etc...) et celles de la réponse.


La type de retour de cette méthode est ModelAndView, nous allons donc devoir renvoyer ce type d'objet pour que Spring puisse afficher correctement notre page.


Voyons maintenant le code de notre programme.


package com.myjavaland.spring.mvc;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

public class LoginController implements Controller {

    public ModelAndView handleRequest(HttpServletRequest request,
            HttpServletResponse response) throws Exception {
        String login = request.getParameter("login");
        String password = request.getParameter("password");
        request.setAttribute("login", login);
        if("foo".equals(login) && "123".equals(password)){   
            return new ModelAndView("main");
        } else {
            return new ModelAndView("loginError");
        }
    }
}


L'implémentation de la méthode est très basique, nous allons dans un premier temps récupérer les valeurs de login et password et les vérifier. Puis, en fonction de ces valeurs, nous allons appeler l'une ou l'autre des vues. 

Souvenons-nous de notre fichier de configuration Spring dans lequel nous spécifions le pattern des vues. La ligne return new ModelAndView("main") aura pour conséquence l'appel de la jsp /WEB-INF/views/main.jsp alors que return new ModelAndView("loginError") appellera /WEB-INF/views/loginError.jsp

Passons tout de suite à la création des vues


Les vues :



Dans le répertoire WEB-INF, nous allons créer un répertoire views dans lequel nous allons mettre 2 jsp : main.jsp et loginError.jsp servant respectivement à valider une connexion ou afficher un message d'erreur.


Les 2 JSP sont on ne peut plus simple :


main.jsp


<%@ page language="java" pageEncoding="ISO-8859-1" contentType="text/html;charset=ISO-8859-1"%>
<%@ page isELIgnored="false" %>
<html>
    <body>
        <h1>Bienvenue ${login}</h1>
    </body>
</html>

loginError.jsp 



<%@ page language="java" pageEncoding="ISO-8859-1" contentType="text/html;charset=ISO-8859-1"%>
<%@ page isELIgnored="false" %>
<html>
    <body>
        <p>
        Impossible de connecter en tant que ${login}
        </p>
    </body>
</html>


Voilà, notre application est prête à être testée, il ne nous reste plus qu'à ajouter le projet sur tomcat si ça n'est pas déjà fait et à lancer le serveur pour pouvoir tester que tout fonctionne bien !




Sources du programme