devstory

Le Tutoriel de Spring MVC Form et Hibernate

  1. Introduction
  2. Préparer la base de données
  3. Créer le projet
  4. Configurer Web.xml & Maven
  5. Configurer Spring MVC
  6. Des classes participées dans l'exemple
  7. Spring MVC Validator
  8. Spring Controller
  9. Des fichiers Jsps
  10. Exécution de l'exemple

1. Introduction

Ce document est basé sur :
  • Spring MVC 4.2.5

  • Hibernate 5.x

  • Database: Oracle, MySQL, SQL Server

L'avant- première d'exemple :

2. Préparer la base de données

ORACLE
-- Create table
create table APPLICANTS
(
  ID       VARCHAR2(50) not null,
  GENDER   VARCHAR2(10) not null,
  NAME     VARCHAR2(50) not null,
  POSITION VARCHAR2(50) not null,
  SKILLS   VARCHAR2(255) not null,
  EMAIL    VARCHAR2(50) not null
) ;

alter table APPLICANTS
  add constraint APPLICANT_PK primary key (ID);
MYSQL & SQL SERVER
-- Create table
create table APPLICANTS
(
  ID       VARCHAR(50) not null,
  GENDER   VARCHAR(10) not null,
  NAME     VARCHAR(50) not null,
  POSITION VARCHAR(50) not null,
  SKILLS   VARCHAR(255) not null,
  EMAIL    VARCHAR(50) not null,
  primary key (ID)
) ;

3. Créer le projet

Sur Eclipse sélectionnez :
  • File/New/Others..
  • Group Id: org.o7planning
  • Artifact Id: SpringMVCAnnotationForm
Le projet est créé.
Fix Project:
Cliquez sur le bouton droit du Projet, sélectionnez Properties.

Sélectionnez Java Compiler 7 ou 8:

4. Configurer Web.xml & Maven

Vous devez éditer web.xml en but d'utiliser Web App 3.x.
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns="http://java.sun.com/xml/ns/javaee"
 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
 id="WebApp_ID" version="3.0">

 <display-name>Spring MVC Form</display-name>
 

</web-app>
Configurer Maven:
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
  http://maven.apache.org/maven-v4_0_0.xsd">
 
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.o7planning</groupId>
  <artifactId>SpringMVCAnnotationForm</artifactId>
  <packaging>war</packaging>
  <version>1.0.0</version>
  <name>SpringMVCAnnotationForm Maven Webapp</name>
  <url>http://maven.apache.org</url>


  <properties>
      <java-version>1.7</java-version>
  </properties>

  <repositories>
      <!-- Repository for ORACLE JDBC Driver -->
      <repository>
          <id>codelds</id>
          <url>https://code.lds.org/nexus/content/groups/main-repo</url>
      </repository>
  </repositories>

  <dependencies>

      <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>3.8.1</version>
          <scope>test</scope>
      </dependency>

      <!-- Servlet API -->
      <!-- http://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
      <dependency>
          <groupId>javax.servlet</groupId>
          <artifactId>javax.servlet-api</artifactId>
          <version>3.1.0</version>
          <scope>provided</scope>
      </dependency>

      <!-- Jstl for jsp page -->
      <!-- http://mvnrepository.com/artifact/javax.servlet/jstl -->
      <dependency>
          <groupId>javax.servlet</groupId>
          <artifactId>jstl</artifactId>
          <version>1.2</version>
      </dependency>


      <!-- JSP API -->
      <!-- http://mvnrepository.com/artifact/javax.servlet.jsp/jsp-api -->
      <dependency>
          <groupId>javax.servlet.jsp</groupId>
          <artifactId>jsp-api</artifactId>
          <version>2.2</version>
          <scope>provided</scope>
      </dependency>

      <!-- Spring dependencies -->
      <!-- http://mvnrepository.com/artifact/org.springframework/spring-core -->
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-core</artifactId>
          <version>4.2.5.RELEASE</version>
      </dependency>

      <!-- http://mvnrepository.com/artifact/org.springframework/spring-web -->
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-web</artifactId>
          <version>4.2.5.RELEASE</version>
      </dependency>

      <!-- http://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-webmvc</artifactId>
          <version>4.2.5.RELEASE</version>
      </dependency>

      <!-- http://mvnrepository.com/artifact/org.springframework/spring-orm -->
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-orm</artifactId>
          <version>4.2.5.RELEASE</version>
      </dependency>

      <!-- Hibernate -->
      <!-- http://mvnrepository.com/artifact/org.hibernate/hibernate-core -->
      <dependency>
          <groupId>org.hibernate</groupId>
          <artifactId>hibernate-core</artifactId>
          <version>5.1.0.Final</version>
      </dependency>

      <!-- http://mvnrepository.com/artifact/org.hibernate/hibernate-entitymanager -->
      <dependency>
          <groupId>org.hibernate</groupId>
          <artifactId>hibernate-entitymanager</artifactId>
          <version>5.1.0.Final</version>
      </dependency>


      <!-- http://mvnrepository.com/artifact/org.hibernate/hibernate-c3p0 -->
      <dependency>
          <groupId>org.hibernate</groupId>
          <artifactId>hibernate-c3p0</artifactId>
          <version>5.1.0.Final</version>
      </dependency>


      <!-- MySQL JDBC driver -->
      <!-- http://mvnrepository.com/artifact/mysql/mysql-connector-java -->
      <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          <version>5.1.34</version>
      </dependency>

      <!-- Oracle JDBC driver -->
      <dependency>
          <groupId>com.oracle</groupId>
          <artifactId>ojdbc6</artifactId>
          <version>11.2.0.3</version>
      </dependency>

    <!-- SQLServer JDBC driver (JTDS) -->
    <!-- http://mvnrepository.com/artifact/net.sourceforge.jtds/jtds -->
    <dependency>
        <groupId>net.sourceforge.jtds</groupId>
        <artifactId>jtds</artifactId>
        <version>1.3.1</version>
    </dependency>

    <!-- Email validator,... -->
    <!-- http://mvnrepository.com/artifact/commons-validator/commons-validator -->
    <dependency>
        <groupId>commons-validator</groupId>
        <artifactId>commons-validator</artifactId>
        <version>1.5.0</version>
    </dependency>

  </dependencies>


  <build>
      <finalName>SpringMVCAnnotationForm</finalName>
      <plugins>
    
          <!-- Config: Maven Tomcat Plugin -->
          <!-- http://mvnrepository.com/artifact/org.apache.tomcat.maven/tomcat7-maven-plugin -->
          <plugin>
              <groupId>org.apache.tomcat.maven</groupId>
              <artifactId>tomcat7-maven-plugin</artifactId>
              <version>2.2</version>
              <!-- Config: contextPath and Port (Default - /SpringMVCAnnotationForm : 8080) -->
              <!--
              <configuration>
                  <path>/</path>
                  <port>8899</port>
              </configuration>
              -->   
          </plugin>
      </plugins>
  </build>   
 

</project>

5. Configurer Spring MVC

SpringWebAppInitializer sert à initialiser la configuration Spring, ul est le point départ de Spring MVC. Il remplace la configuration Spring MVC dans web.xml.
** web.xml **
<!-- With SpringWebAppInitializer, you do not need to configure in web.xml -->

  <servlet>
      <servlet-name>spring-mvc</servlet-name>
      <servlet-class>
          org.springframework.web.servlet.DispatcherServlet
      </servlet-class>
      <load-on-startup>1</load-on-startup>
  </servlet>   
 
  <servlet-mapping>
      <servlet-name>spring-mvc</servlet-name>
      <url-pattern>/</url-pattern>
  </servlet-mapping>
SpringWebAppInitializer.java
package org.o7planning.springmvcforms.config;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;

import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;

public class SpringWebAppInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        AnnotationConfigWebApplicationContext appContext = new AnnotationConfigWebApplicationContext();
        appContext.register(ApplicationContextConfig.class);

        ServletRegistration.Dynamic dispatcher = servletContext.addServlet("SpringDispatcher",
                new DispatcherServlet(appContext));
        dispatcher.setLoadOnStartup(1);
        dispatcher.addMapping("/");
    }

}
La classe ApplicationContextConfig sert à configurer Spring MVC Context, y compris :
  • View Resolver
  • Datasouce
  • Hiberante (Hibernate Transaction Manager, Hibernate Session,..)
  • DAO
  • Bean
  • ....
ApplicationContextConfig.java
package org.o7planning.springmvcforms.config;

import java.util.Properties;

import javax.sql.DataSource;

import org.hibernate.SessionFactory;
import org.o7planning.springmvcforms.dao.ApplicantDAO;
import org.o7planning.springmvcforms.dao.impl.ApplicantDAOImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@Configuration
@ComponentScan("org.o7planning.springmvcforms.*")
@EnableTransactionManagement
// Load to Environment.
@PropertySource("classpath:ds-hibernate-cfg.properties")
public class ApplicationContextConfig {

 // The Environment class serves as the property holder
 // and stores all the properties loaded by the @PropertySource
 @Autowired
 private Environment env;



 @Bean
 public ResourceBundleMessageSource messageSource() {
     ResourceBundleMessageSource rb = new ResourceBundleMessageSource();
     // Load property in message/validator.properties
     rb.setBasenames(new String[] { "messages/validator"});
     return rb;
 }


 @Bean(name = "viewResolver")
 public InternalResourceViewResolver getViewResolver() {
     InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
     viewResolver.setPrefix("/WEB-INF/pages/");
     viewResolver.setSuffix(".jsp");
     return viewResolver;
 }

 @Bean(name = "dataSource")
 public DataSource getDataSource() {
     DriverManagerDataSource dataSource = new DriverManagerDataSource();

     dataSource.setDriverClassName(env.getProperty("ds.database-driver"));
     dataSource.setUrl(env.getProperty("ds.url"));
     dataSource.setUsername(env.getProperty("ds.username"));
     dataSource.setPassword(env.getProperty("ds.password"));

     return dataSource;
 }

 @Autowired
 @Bean(name = "sessionFactory")
 public SessionFactory getSessionFactory(DataSource dataSource) throws Exception {
     Properties properties = new Properties();
   
     // See: ds-hibernate-cfg.properties
     properties.put("hibernate.dialect", env.getProperty("hibernate.dialect"));
     properties.put("hibernate.show_sql", env.getProperty("hibernate.show_sql"));
     properties.put("current_session_context_class", env.getProperty("current_session_context_class"));
     

     LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean();
     factoryBean.setPackagesToScan(new String[] { "org.o7planning.springmvcforms.entity" });
     factoryBean.setDataSource(dataSource);
     factoryBean.setHibernateProperties(properties);
     factoryBean.afterPropertiesSet();
     //
     SessionFactory sf = factoryBean.getObject();
     return sf;
 }

 @Autowired
 @Bean(name = "transactionManager")
 public HibernateTransactionManager getTransactionManager(SessionFactory sessionFactory) {
     HibernateTransactionManager transactionManager = new HibernateTransactionManager(sessionFactory);

     return transactionManager;
 }

 @Bean(name = "applicantDAO")
 public ApplicantDAO getApplicantDAO() {
     return new ApplicantDAOImpl();
 }

}
ApplicationContextConfig lira les information de la configuration Datasource, Hibernate properties dans le fichier ds-hibernate-cfg.properties.
Des configurations de Oracle, MySQL ou SQL Server:
ds-hibernate-cfg.properties (For ORACLE)
# DataSource

ds.database-driver=oracle.jdbc.driver.OracleDriver
ds.url=jdbc:oracle:thin:@localhost:1521:db12c
ds.username=shoppingcart
ds.password=12345


# Hibernate Config

hibernate.dialect=org.hibernate.dialect.Oracle10gDialect
hibernate.show_sql=true
current_session_context_class=thread
ds-hibernate-cfg.properties (For MYSQL)
# DataSource

ds.database-driver=com.mysql.jdbc.Driver
ds.url=jdbc:mysql://localhost:3306/mydatabase
ds.username=root
ds.password=12345


# Hibernate Config

hibernate.dialect=org.hibernate.dialect.MySQLDialect
hibernate.show_sql=true
current_session_context_class=thread
ds-hibernate-cfg.properties (For SQL SERVER)
# DataSource

ds.database-driver=net.sourceforge.jtds.jdbc.Driver
ds.url=jdbc:jtds:sqlserver://localhost:1433/simplehr;instance=SQLEXPRESS
ds.username=shoppingcart
ds.password=12345


# Hibernate Config

hibernate.dialect=org.hibernate.dialect.SQLServerDialect
hibernate.show_sql=true
current_session_context_class=thread
La configuration de la ressource statique (html, image, css,..)
WebMvcConfig.java
package org.o7planning.springmvcforms.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;


@Configuration
@EnableWebMvc
public class WebMvcConfig extends WebMvcConfigurerAdapter {

    // Static Resource Config
    // equivalents for <mvc:resources/> tags
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/css/**").addResourceLocations("/css/").setCachePeriod(31556926);
        registry.addResourceHandler("/img/**").addResourceLocations("/img/").setCachePeriod(31556926);
        registry.addResourceHandler("/js/**").addResourceLocations("/js/").setCachePeriod(31556926);
    }

    // equivalent for <mvc:default-servlet-handler/> tag
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }
 
}

6. Des classes participées dans l'exemple

Applicant est une entity class, qui simule le tableau APPLICANTS dans la base de données.
Applicant.java
package org.o7planning.springmvcforms.entity;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "Applicants")
public class Applicant implements Serializable {

   private static final long serialVersionUID = -7893237204476214050L;
   private String id;
   private String name;
   private String email;

   private String position;
   private String gender;
   private String skills;

   @Id
   @Column(name = "ID", length = 50, nullable = false)
   public String getId() {
       return id;
   }

   public void setId(String id) {
       this.id = id;
   }

   @Column(name = "Name", length = 50, nullable = false)
   public String getName() {
       return name;
   }

   public void setName(String name) {
       this.name = name;
   }

   @Column(name = "Position", length = 50, nullable = false)
   public String getPosition() {
       return position;
   }

   public void setPosition(String position) {
       this.position = position;
   }

   @Column(name = "Gender", length = 10, nullable = false)
   public String getGender() {
       return gender;
   }

   public void setGender(String gender) {
       this.gender = gender;
   }

   @Column(name = "Email", length = 50, nullable = false)
   public String getEmail() {
       return email;
   }

   public void setEmail(String email) {
       this.email = email;
   }

   @Column(name = "Skills", length = 255, nullable = false)
   public String getSkills() {
       return skills;
   }

   public void setSkills(String skills) {
       this.skills = skills;
   }
}
ApplicantInfo.java
package org.o7planning.springmvcforms.model;

public class ApplicantInfo {

    private String id;
    private String name;
    private String email;

    private String position;
    private String gender;
    private String skillsString;
    private String[] skills;

    public ApplicantInfo() {

    }

    // Do not change this constructor,
    // it is used in the Hibernate Query
    public ApplicantInfo(String id, String name, String email, String gender, String position, String skillsString) {
        this.id = id;
        this.name = name;
        this.email = email;

        this.position = position;
        this.gender = gender;
        this.skillsString = skillsString;
        this.skills = toArray(skillsString);
    }

    private String[] toArray(String skillStrings) {
        if (skillStrings == null) {
            return new String[0];
        }
        String[] ret = skillStrings.split(",");
        return ret;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPosition() {
        return position;
    }

    public void setPosition(String position) {
        this.position = position;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public String[] getSkills() {
        return skills;
    }

    public void setSkills(String[] skills) {
        this.skills = skills;
        this.skillsString = this.joinString(skills);
    }

    private String joinString(String[] skills) {
        if (skills == null) {
            return "";
        }
        return String.join(",", skills);
    }

    public String getSkillsString() {
        return this.skillsString;
    }

}
ApplicantDAO est un Spring Bean, pour gérer des insert, update, query des données dans le tableau APPLICANTS.
ApplicantDAO.java
package org.o7planning.springmvcforms.dao;

import java.util.List;

import org.o7planning.springmvcforms.entity.Applicant;
import org.o7planning.springmvcforms.model.ApplicantInfo;

public interface ApplicantDAO {

    public Applicant findApplicant(String id);

    public List<ApplicantInfo> listApplicantInfos();

    public void saveApplicant(ApplicantInfo applicantInfo);

    public ApplicantInfo findApplicantInfo(String id);

    public void deleteApplicant(String id);
   
}
ApplicantDAOImpl.java
package org.o7planning.springmvcforms.dao.impl;

import java.util.List;
import java.util.UUID;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Restrictions;
import org.o7planning.springmvcforms.dao.ApplicantDAO;
import org.o7planning.springmvcforms.entity.Applicant;
import org.o7planning.springmvcforms.model.ApplicantInfo;
import org.springframework.beans.factory.annotation.Autowired;

public class ApplicantDAOImpl implements ApplicantDAO {

    @Autowired
    private SessionFactory sessionFactory;

    @Override
    public Applicant findApplicant(String id) {
        Session session = sessionFactory.getCurrentSession();
        Criteria crit = session.createCriteria(Applicant.class);
        crit.add(Restrictions.eq("id", id));
        return (Applicant) crit.uniqueResult();
    }

    @Override
    public ApplicantInfo findApplicantInfo(String id) {
        Applicant applicant = this.findApplicant(id);
        if (applicant == null) {
            return null;
        }
        return new ApplicantInfo(applicant.getId(), applicant.getName(), //
                applicant.getEmail(), applicant.getGender(), //
                applicant.getPosition(), applicant.getSkills());
    }

    @Override
    public List<ApplicantInfo> listApplicantInfos() {
        String sql = "Select new " + ApplicantInfo.class.getName()//
                + "(a.id, a.name, a.email, a.gender, a.position, a.skills) "//
                + " from " + Applicant.class.getName() + " a ";
        Session session = sessionFactory.getCurrentSession();
        Query query = session.createQuery(sql);
        return query.list();
    }

    public void saveApplicant(ApplicantInfo applicantInfo) {
        String id = applicantInfo.getId();
        Applicant applicant = null;
        if (id != null) {
            applicant = this.findApplicant(id);
        }
        boolean isNew = false;
        if (applicant == null) {
            isNew = true;
            applicant = new Applicant();
            applicant.setId(UUID.randomUUID().toString());
        }
        applicant.setEmail(applicantInfo.getEmail());
        applicant.setGender(applicantInfo.getGender());
        applicant.setName(applicantInfo.getName());
        applicant.setPosition(applicantInfo.getPosition());
        String skillsString = applicantInfo.getSkillsString();

        applicant.setSkills(skillsString);
        //

        if (isNew) {
            Session session = this.sessionFactory.getCurrentSession();
            session.persist(applicant);
        }
    }

    @Override
    public void deleteApplicant(String id) {
        Applicant applicant = this.findApplicant(id);
        if (applicant != null) {
            this.sessionFactory.getCurrentSession().delete(applicant);
        }
    }

}

7. Spring MVC Validator

ApplicantValidator est une classe qui vérifie les données utilisateur saisies dans un formulaire. Dans le cas où l'utilisateur saisie des données erronnées, il y aura une notification comme indiquée ci-dessous:
ApplicantValidator.java
package org.o7planning.springmvcforms.validator;

import org.apache.commons.validator.routines.EmailValidator;
import org.o7planning.springmvcforms.model.ApplicantInfo;
import org.springframework.stereotype.Component;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;

@Component
public class ApplicantValidator implements Validator {
   
    // common-validator library.
    private EmailValidator emailValidator =   EmailValidator.getInstance();

    // The classes is supported to Validate
    @Override
    public boolean supports(Class<?> clazz) {
        return clazz == ApplicantInfo.class;
    }

    @Override
    public void validate(Object target, Errors errors) {
        ApplicantInfo applicantInfo = (ApplicantInfo) target;

        // Check the fields of ApplicantInfo.
        // (See more in property file: messages/validator.property)
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "name", "NotEmpty.applicantForm.name");
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "email", "NotEmpty.applicantForm.email");
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "position", "NotEmpty.applicantForm.position");
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "gender", "NotEmpty.applicantForm.gender");
       
        if(!emailValidator.isValid(applicantInfo.getEmail())) {
            // Error in email field.
            errors.rejectValue("email", "Pattern.applicantForm.email");
        }
       
        if(applicantInfo.getSkills()== null || applicantInfo.getSkills().length==0 ) {
            errors.rejectValue("skills", "Select.applicantForm.skills");
        }
     
    }

}
Les messages d'erreur sont configurés dans le fichier messages/validator.properties:
messages/validator.properties
NotEmpty.applicantForm.name=Name is required
NotEmpty.applicantForm.email=Email is required
NotEmpty.applicantForm.position=Position is required
NotEmpty.applicantForm.gender=Gender is required

Pattern.applicantForm.email=Email is not valid

Select.applicantForm.skills=Must select at least one skill
Le contenu de validator.properties est chargé (téléchargé dans l'application) par ApplicationContextConfig:
** ApplicationContextConfig.java **
// Load property in message/validator.properties

@Bean
public ResourceBundleMessageSource messageSource() {
   ResourceBundleMessageSource rb = new ResourceBundleMessageSource();
   // Load property in message/validator.properties
   rb.setBasenames(new String[] { "messages/validator"});
   return rb;
}

8. Spring Controller

MyController.java
package org.o7planning.springmvcforms.controller;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.o7planning.springmvcforms.dao.ApplicantDAO;
import org.o7planning.springmvcforms.model.ApplicantInfo;
import org.o7planning.springmvcforms.validator.ApplicantValidator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

@Controller
// Enable Hibernate Transaction.
@Transactional
// Need To use RedirectAttributes
@EnableWebMvc
public class MyController {

   @Autowired
   private ApplicantDAO applicantDAO;

   @Autowired
   private ApplicantValidator applicantValidator;

   @RequestMapping("/")
   public String homePage(Model model) {

       return applicantList(model);
   }

   @RequestMapping("/applicantList")
   public String applicantList(Model model) {
       List<ApplicantInfo> list = applicantDAO.listApplicantInfos();
       model.addAttribute("applicantInfos", list);
       return "applicantList";
   }

   private Map<String, String> dataForPositions() {
       Map<String, String> positionMap = new LinkedHashMap<String, String>();
       positionMap.put("Developer", "Developer");
       positionMap.put("Leader", "Leader");
       positionMap.put("Tester", "Tester");
       return positionMap;
   }

   private List<String> dataForSkills() {
       List<String> list = new ArrayList<String>();
       list.add("Java");
       list.add("C/C++");
       list.add("C#");
       return list;
   }

   private String formApplicant(Model model, ApplicantInfo applicantInfo) {
       model.addAttribute("applicantForm", applicantInfo);

       Map<String, String> positionMap = this.dataForPositions();

       model.addAttribute("positionMap", positionMap);

       List<String> list = dataForSkills();
       model.addAttribute("skills", list);

       if (applicantInfo.getId() == null) {
           model.addAttribute("formTitle", "Create Applicant");
       } else {
           model.addAttribute("formTitle", "Edit Applicant");
       }

       return "formApplicant";
   }

   @RequestMapping("/createApplicant")
   public String createApplicant(Model model) {

       ApplicantInfo applicantInfo = new ApplicantInfo();

       return this.formApplicant(model, applicantInfo);
   }

   @RequestMapping("/editApplicant")
   public String editApplicant(Model model, @RequestParam("id") String id) {
       ApplicantInfo applicantInfo = null;
       if (id != null) {
           applicantInfo = this.applicantDAO.findApplicantInfo(id);
       }
       if (applicantInfo == null) {
           return "redirect:/applicantList";
       }

       return this.formApplicant(model, applicantInfo);
   }

   @RequestMapping("/deleteApplicant")
   public String deleteApplicant(Model model, @RequestParam("id") String id) {
       if (id != null) {
           this.applicantDAO.deleteApplicant(id);
       }
       return "redirect:/applicantList";
   }

   // Set a form validator
   @InitBinder
   protected void initBinder(WebDataBinder dataBinder) {
       // Form target
       Object target = dataBinder.getTarget();
       if (target == null) {
           return;
       }
       System.out.println("Target=" + target);

       if (target.getClass() == ApplicantInfo.class) {
           dataBinder.setValidator(applicantValidator);
       }
   }

   // Save or update Applicant
   // 1. @ModelAttribute bind form value
   // 2. @Validated form validator
   // 3. RedirectAttributes for flash value
   @RequestMapping(value = "/saveApplicant", method = RequestMethod.POST)
   public String saveApplicant(Model model, //
           @ModelAttribute("applicantForm") @Validated ApplicantInfo applicantInfo, //
           BindingResult result, //
           final RedirectAttributes redirectAttributes) {

   
       if (result.hasErrors()) {
           return this.formApplicant(model, applicantInfo);
       }

       this.applicantDAO.saveApplicant(applicantInfo);

       // Important!!: Need @EnableWebMvc
       // Add message to flash scope
       redirectAttributes.addFlashAttribute("message", "Save Applicant Successful");

       return "redirect:/applicantList";

   }

}

9. Des fichiers Jsps

WEB-INF/pages/applicantList.jsp
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Applicant List</title>
<style>
   table  {
       margin-top: 10px;
       border: solid black 1px;
   }
   table  td {
        padding: 5px;
   }
   .message  {
        font-size:90%;
        color:blue;
        font-style:italic;
        margin-top:30px;
   }
</style>
</head>
<body>



<a href="${pageContext.request.contextPath}/createApplicant">Create Applicant</a>

<br/>


<table border="1">
 <tr>
   <th>Name</th>
   <th>Position</th>
   <th>Gender</th>
   <th>Email</th>
   <th>Skills</th>
   <th>Edit</th>
   <th>Delete</th>
 </tr>
 <c:forEach items="${applicantInfos}" var="info">

 <tr>
   <td> ${info.name}  </td>
   <td> ${info.position}  </td>
   <td> ${info.gender} </td>
   <td> ${info.email} </td>
   <td> ${info.skillsString} </td>
   <td> <a href="deleteApplicant?id=${info.id}">Delete</a> </td>
   <td> <a href="editApplicant?id=${info.id}">Edit</a> </td>
 </tr>    

 </c:forEach>
</table>
<c:if test="${not empty message}">
 
   <div class="message">${message}</div>
</c:if>



</body>
</html>
WEB-INF/pages/formApplicant.jsp
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Create Applicant</title>
<style>
.error-message {
   color: red;
   font-size:90%;
   font-style: italic;
}
</style>
</head>
<body>

   <h3>${formTitle}</h3>

   <form:form action="saveApplicant" method="POST"
       modelAttribute="applicantForm">

       <form:hidden path="id" />

       <table>
           <tr>
               <td>Name</td>
               <td><form:input path="name" /></td>
               <td><form:errors path="name"
                       class="error-message" /></td>      
           </tr>
           <tr>
               <td>Gender</td>
               <td><form:select path="gender">
                       <form:option value="" label="- Gender -" />
                       <form:option value="M" label="Male" />
                       <form:option value="F" label="Female" />
                   </form:select></td>
               <td><form:errors path="gender" class="error-message" /></td>
           </tr>
           <tr>
               <td>Email</td>
               <td><form:input path="email" /></td>
               <td><form:errors path="email" class="error-message" /></td>
           </tr>
           <tr>
               <td>Position</td>
               <td><form:select path="position">
                       <form:options items="${positionMap}" />
                   </form:select></td>
               <td><form:errors path="position" class="error-message" /></td>
           </tr>

           <tr>
               <td>Skills</td>
               <td><c:forEach items="${skills}" var="skill">
                       <form:checkbox path="skills" value="${skill}" label="${skill}" />
                   </c:forEach></td>
               <td><form:errors path="skills" class="error-message" /></td>
           </tr>

           <tr>
               <td>&nbsp;</td>
               <td><input type="submit" value="Submit" />
                  <a href="${pageContext.request.contextPath}/applicantList">Cancel</a>
               </td>
               <td>&nbsp;</td>
           </tr>
       </table>
   </form:form>

</body>
</html>

10. Exécution de l'exemple

Cliquez sur le bouton droit du projet, sélectionnez :
  • Run As/Run Applications:
Saisissez :
  • Name: Spring MVC Form
  • Base directory: ${workspace_loc:/SpringMVCAnnotationForm}
  • Goals: tomcat7:run