Le projet est un projet Maven, tout ce qu'il y a de plus simple que vous pouvez télécharger ici.

Sinon je vous propose (et vous conseille) de le construire pas à pas avec moi :

Etape 1 : création du projet

Créons un projet web avec maven :

mvn archetype:create -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-webapp -DgroupId=com.netapsys.springmvc  -DartifactId=spring-mvc-webapp

Pour pouvoir utiliser les annotations notre projet doit être un projet en java 1.5. Ouvrez le pom.xml situé dans le répertoire que vous venez de créér spring-mvc-webapp et ajoutez ces informations entre les balises build. Vous devriez obtenir ceci :

<build>
  <finalName>spring-mvc-webapp</finalName>
  <plugins>
    <plugin>
      <artifactId>maven-compiler-plugin</artifactId>
      <configuration>
        <source>1.5</source>
        <target>1.5</target>
      </configuration>
    </plugin>	
    <plugin>
      <artifactId>maven-eclipse-plugin</artifactId>
      <version>2.4</version>
      <configuration>					
        <downloadSources>true</downloadSources>
        <downloadJavadocs>true</downloadJavadocs>					
      </configuration>
    </plugin>		
  </plugins>
</build>

Pour bien faire, j'indique aussi au plugin eclipse que je souhaite disposer des codes sources, ce qui est toujours un très bon choix quand on travail avec du code open-source.

Ensuite il faut en faire un projet eclipse : allez dans le répertoire que vous venez de créér et lancez la commande maven eclipse:eclipse

cd spring-mvc-webapp
mvn eclipse:eclipse

Puis importez le projet dans eclipse en vous étant assuré que la variable M2_REPO pointe bien vers votre répertoire ~/.m2/repository Si ce n'est pas le cas : windows > preference > Java > Build Path > Class path variables puis New pour créer une nouvelle variable.

Par exemple pour moi M2_REPO = C:/Documents and Settings/michael_courcy/.m2/repository

Etape 2 : Exécution de l'application avec le serveur web jetty

Une fois notre projet créé nous allons modifier le pom.xml pour pouvoir exécuter ce projet sous le serveur web jetty :

Vous devriez obtenir ceci :

<build>
  <finalName>spring-mvc-webapp</finalName>
  <plugins>
    <plugin>
      <artifactId>maven-compiler-plugin</artifactId>
      <configuration>
        <source>1.5</source>
        <target>1.5</target>
      </configuration>
    </plugin>
    <plugin>
      <groupId>org.mortbay.jetty</groupId>
      <artifactId>maven-jetty-plugin</artifactId>
      <version>6.0.1</version>
      <configuration>
        <scanIntervalSeconds>10</scanIntervalSeconds>
      </configuration>
    </plugin>
  </plugins>
</build>

Remarquez qu'ici je n'ai fait que configurer jetty. Maven téléchargera lui-même jetty si nécessaire.

Vérifions que notre configuration fonctionne bien et exécutons l'application.

mvn jetty:run

Si vous n'avez pas l'habitude d'utiliser maven pour vos applications web, Maven téléchargera nécessairement de nombreuses dépendances transitives. C'est peut être l'occasion de prendre un café ...

Enfin, si tout s'est bien passé, vous pouvez vous connecter à l'url : http://localhost:8080/spring-mvc-webapp/

Pour y découvrir l'éternel Hello World.

Etape 3 : Branchement de Spring MVC

Spring mvc fonctionne par certains aspects de façon similaire à Struts : une servlet frontale va prendre l'ensemble des requêtes et les dispatcher à ses contrôleurs, ces contrôleurs sont des singletons issus d'une fabrique Spring.

Donc ce que je vais trouver dans web.xml :

  1. Une servlet pour dispatcher les requêtes aux contrôleurs.
  2. Un mapping de servlet

On aboutit à ce fichier web.xml :

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >
 
<web-app>
  <display-name>Archetype Created Web Application</display-name>
 
  <!-- déclare la servlet frontale (très similaire à struts)  -->
  <servlet>
    <servlet-name>spring-mvc-webapp</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>2</load-on-startup>
  </servlet>
 
  <!-- Toutes les requêtes se terminant par .html seront servis par la servlet frontal -->
  <servlet-mapping>
    <servlet-name>spring-mvc-webapp</servlet-name>
    <url-pattern>*.html</url-pattern>
  </servlet-mapping>
 
</web-app>

Avant de recopier ce fichier, coupez jetty (Ctrl + C dans le terminal).

Ajoutez la dépendances à Spring et à spring-webmvc dans le pom.xml :

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring</artifactId>
  <version>2.5.3</version>
</dependency>
<dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-webmvc</artifactId>
   <version>2.5.3</version>
</dependency>

puis régénérez votre projet eclipse :

mvn eclipse:clean eclipse:eclipse

enfin rafraîchissez votre projet eclipse quand l'opération est finie pour voir apparaitre vos librairies et éventuellement consulter le code source.

On remarque immédiatement à la lecture de web.xml qu'on ne voit pas comment on informe la servlet frontale des contrôleurs auxquels elle va devoir redispatcher les requêtes.

Par convention, si la servlet s'appelle spring-mvc-webapp, alors elle ira chercher sa fabrique de contrôleurs dans WEB-INF/spring-mvc-webapp-servlet.xml. C'est une convention qui peut être surdéfinie mais que nous allons suivre ici.

Voici donc le fichier spring-mvc-webapp-servlet.xml. Les commentaires détaillent chaque élément : je vous invite à les lire.

<?xml version="1.0" encoding="UTF-8"?>
<!--
  - Contexte d'application pour spring-mvc-webapp.
-->
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context"
		xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
 
  <!--
    - Tous les contrôleurs sont automatiquement détectés grâce à l'annotation @Controller.
    - On définit ici dans quel package le post processor doit chercher ces beans éventuellement annotés.
  -->
  <context:component-scan base-package="com.netapsys.springmvc.web"/>
 
    <!--
      - Les controlleurs de cette application fournissent une annotation @RequestMapping 
      - Qui peuvent être déclaré de deux manière différentes : 
      - Au niveau de la classe par exemple : 
      -     @RequestMapping("/addVisit.html")
      -     Pour ce type de controlleurs on peut annoter les méthodes pour qu'elles
      -     prennent en charge une requête Post ou une requête Get
      -     @RequestMapping(method = RequestMethod.GET)
      - Ou alors au niveau de chaque méthode, différents exemples  seront fournis.		 
    -->
 
    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>
      <!--
        Ceci est le view resolver, il permet de définir la technologie de vue utilisée et comment
        sélectionner une vue. Ici on prendra la solution la plus simple, elle permet de mapper 
        le nom de la vue retournée avec la sélection d'une jsp.
        Exemple si le nom de la vue retournée est "foo/bar/hello" alors on utilisera le fichier
        WEB-INF/jsp/foo/bar/hello.jsp pour constuire la vue. 
      -->
      <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix="/WEB-INF/jsp/" p:suffix=".jsp"/>
 
</beans>

Tout est en place maintenant pour écrire notre premier contrôleur et notre première jsp.

Etape 4 : Notre premier contrôleur

Créez le source folder /src/main/java/ et créez la classe HelloSpringMVC dans le package com.netapsys.springmvc.web

package com.netapsys.springmvc.web;
 
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
 
/**
 * Contrôleur que l'on invoquera pour l'url /helloSpringMVC.html.
 * 
 * @author Michael Courcy
 *
 */
@Controller
@RequestMapping("/helloSpringMVC.html")
public class HelloSpringMVC {
 
  /**
    * Handler de la méthode Get pour l'URL /helloSpringMVC.html. 
    * 
    * @param name le nom que l'on doit afficher dans la vue.
    * @param model une map de toutes les données qui seront utilisables dans la vue 
    * @return le nom de la vue qu'il faudra utiliser.
    */
  @RequestMapping(method = RequestMethod.GET)
  public  String sayHelloWithSpringMVC(
    @RequestParam(value="name",required=false) String name, 
    ModelMap model) 
  {
    model.addAttribute("name",name);
    // on utilisera donc le fichier /WEB-INF/jsp/hello.jsp
    //au regard de la stratégie de résolution des vues 
    //utilisée dans cette application.
    return "hello";
  }
}

Plusieurs remarques sont à faire à la lecture de ce contrôleur :

  1. Le contrôleur n'hérite d'aucune classe particulière, il est identifié comme contrôleur grâce à l'annotation @Controller
  2. C'est encore une annotation qui permet de savoir quelle méthode invoquer pour une requê

te de type Get : @RequestMapping(method = RequestMethod.GET)

  1. Notre méthode prend un paramètre supplémentaire ModelMap qui est en fait un HashMap amélioré dans lequel on place toutes les informations que l'on souhaite disponibles lors de la génération de la vue avec la jsp.
  2. Le code n'utilise pas directement l'objet HttpServletRequest mais il indique encore grâce aux annotations comment renseigner les paramètres à partir du contenu de l'objet HttpServletRequest @RequestParam(value="name",required=false)

Ce dernier point est très important : ne pas utiliser directement l'objet HttpServletRequest nous permet de créer des tests unitaires très simplement sans avoir à créer de request mock.

Créez le source folder /src/test/java et créez aussi le package com.netapsys.springmvc.web pour y placer le test suivant

package com.netapsys.springmvc.web;
 
import org.springframework.ui.ModelMap;
 
import junit.framework.TestCase;
 
public class HelloSpringMCVTest extends TestCase {
 
  public void testSayHelloWithSpringMVC(){
    HelloSpringMVC helloSpringMVC = new HelloSpringMVC();
    ModelMap model = new ModelMap();
    String view = helloSpringMVC.sayHelloWithSpringMVC("mic", model);
    //vérifions que c'est bien la vue hello qui est générée
    assertEquals("hello", view);
    //vérifions que le modele contient bien un attribut name
    assertTrue(model.containsAttribute("name"));
    //vérifions que cet attribut name est bien "mic"
    assertEquals("mic",model.get("name"));
  }
}

Vous pouvez lancer ce test avec maven :

mvn -Dtest=HelloSpringMCVTest test

pour un test particulier ou alors

mvn test

pour refaire tous les tests.

Etape 5 : Notre propre jsp

Créez le fichier WEB-INF/jsp/hello.jsp :

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<%@ page isELIgnored ="false" %>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Spring mvc hello !!</title>
</head>
<body>
 
Hello spring mvc vous donne votre nom qui est : ${name}
 
</body>
</html>

Il ne vous reste plus qu'à tester

mvn jetty:run

Puis à essayer l'url suivante : http://localhost:8080/spring-mvc-webapp/helloSpringMVC.html?name=mic