鍍金池/ 教程/ Java/ Spring4 MVC 表單驗(yàn)證和資源處理 (使用注解)
Spring MVC表單處理
Spring MVC多項(xiàng)單選按鈕
Spring MVC Bean名稱Url處理程序映射
Spring MVC下拉選項(xiàng)(Select)
Spring MVC多動(dòng)作控制器
Spring4 MVC RESTFul Web Services CRUD實(shí)例+RestTemplate
Spring MVC頁面重定向
Spring MVC資源綁定視圖解析器
Spring4 MVC+Hibernate4 Many-to-many連接表+MySQL+Maven實(shí)例
Spring4 MVC REST服務(wù)示例使用@RestController
Spring MVC文本域
Spring4 MVC + AngularJS使用$http異步服務(wù)交互
Spring4 MVC文件下載實(shí)例
Spring4 MVC表單驗(yàn)證
Spring4 MVC RESTFul WebServices CRUD實(shí)例+RestTemplate
Spring MVC教程
Spring MVC參數(shù)方法名稱解析器
Spring MVC生成JSON數(shù)據(jù)
Spring MVC生成XML
Spring4 MVC 表單驗(yàn)證和資源處理 (使用注解)
Spring MVC單選按鈕
Spring MVC Xml視圖解析器
Spring MVC復(fù)選框
Spring4 MVC ContentNegotiatingViewResolver多種輸出格式實(shí)例
Spring MVC錯(cuò)誤處理
Spring MVC復(fù)選框(多項(xiàng))
Spring MVC Hibernate驗(yàn)證器
Spring4 MVC Hello World注解 (Java Config)實(shí)例
Spring MVC靜態(tài)頁面
Spring4 MVC ContentNegotiatingViewResolver實(shí)例
Spring MVC列表多選框
Spring MVC生成Excel格式數(shù)據(jù)
Spring MVC文本框
Spring MVC內(nèi)部資源視圖解析器
Spring4 MVC HelloWorld 注解和JavaConfig實(shí)例
Spring4 MVC REST服務(wù)使用@RestController實(shí)例
Spring MVC簡單URL處理程序映射
Spring MVC4使用Servlet3 MultiPartConfigElement文件上傳實(shí)例
Spring MVC概述
Spring4 MVC使用Servlet 3 MultiPartConfigElement文件上傳實(shí)例
Spring4 MVC Hello WorldXML實(shí)例
Spring MVC屬性方法名稱解析器
Spring4 MVC + Hibernate4 + MySQL + Maven使用注解集成實(shí)例
Spring4 MVC + Hibernate4多對多連接表+MySQL+Maven實(shí)例
Spring4 MVC+Hibernate4+MySQL+Maven使用注解集成實(shí)例
Spring MVC配置靜態(tài)資源和資源包教程
Spring MVC可參數(shù)化的視圖控制器
Spring MVC生成RSS源
Spring4 MVC文件下載實(shí)例
Spring MVC密碼處理
Spring MVC隱藏字段域
Spring MVC文件上傳教程
Spring MVC多解析器映射
Spring MVC文件上傳處理
Spring4 MVC HelloWord實(shí)例
Spring MVC集成Log4j
Spring4 MVC+ AngularJS CRUD使用$http實(shí)例
Spring MVC - Hello World示例

Spring4 MVC 表單驗(yàn)證和資源處理 (使用注解)

在這篇文章中,我們將學(xué)習(xí)如何使用Spring表單標(biāo)簽, 表單驗(yàn)證使用 JSR303 的驗(yàn)證注解,hibernate-validators,提供了使用MessageSource和訪問靜態(tài)資源(如CSS,JavaScript,圖片)國際化支持我們的視圖,使用ResourceHandlerRegistry,全部采用基于注解的配置。

我們將創(chuàng)建一個(gè)包含一個(gè)學(xué)生注冊表格的簡單應(yīng)用,用戶輸入表單提交驗(yàn)證通過 JSR303 的驗(yàn)證注釋驗(yàn)證,通過覆蓋屬性文件可使用國際驗(yàn)證消息的默認(rèn)消息,還訪問靜態(tài)資源(如應(yīng)用引導(dǎo)CSS到網(wǎng)頁中)。

請注意,JSR303是一種規(guī)范,hibernate-validator是我們在這篇文章中使用的一種實(shí)現(xiàn),它也提供了幾個(gè)不包含在規(guī)范中自己的驗(yàn)證注釋。

使用以下技術(shù):

  • Spring 4.0.6.RELEASE
  • validation-api 1.1.0.Final
  • hibernate-validator 5.1.2.Final
  • Bootstrap v3.1.0
  • Maven 3
  • JDK 1.6
  • Tomcat 7.0.54
  • Eclipse JUNO Service Release 2

我們現(xiàn)在開始!

第1步:創(chuàng)建目錄結(jié)構(gòu)

以下將是最終的項(xiàng)目結(jié)構(gòu)(這里需要先創(chuàng)建一個(gè)Maven工程為:Spring4MVCFormValidationExample):


現(xiàn)在讓我們在每個(gè)細(xì)節(jié)上述結(jié)構(gòu)中提到的內(nèi)容來做一點(diǎn)解釋。

第2步:更新pom.xml,包括所需的依賴關(guān)系

<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
	xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

	<modelVersion>4.0.0</modelVersion>
	<groupId>com.yiibai.springmvc</groupId>
	<artifactId>Spring4MVCFormValidationExample</artifactId>
	<packaging>war</packaging>
	<version>1.0.0</version>
	<name>Spring4MVCFormValidationExample</name>

	<properties>
		<springframework.version>4.0.6.RELEASE</springframework.version>
		<hibernate.validator.version>5.1.2.Final</hibernate.validator.version>
		<javax.validation.version>1.1.0.Final</javax.validation.version>
	</properties>

	<dependencies>
		<!-- Spring dependencies -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${springframework.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
			<version>${springframework.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${springframework.version}</version>
		</dependency>

		<!-- jsr303 validation dependencies-->
		<dependency>
			<groupId>javax.validation</groupId>
			<artifactId>validation-api</artifactId>
			<version>${javax.validation.version}</version>
		</dependency>
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-validator</artifactId>
			<version>${hibernate.validator.version}</version>
		</dependency>

		<!-- Servlet dependencies -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>3.1.0</version>
		</dependency>
		<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>javax.servlet.jsp-api</artifactId>
			<version>2.3.1</version>
		</dependency>
		<dependency>
		    <groupId>javax.servlet</groupId>
		    <artifactId>jstl</artifactId>
		    <version>1.2</version>
		</dependency>
	</dependencies>

	<build>
		<pluginManagement>
			<plugins>
				<plugin>
					<groupId>org.apache.maven.plugins</groupId>
					<artifactId>maven-war-plugin</artifactId>
					<version>2.4</version>
					<configuration>
						<warSourceDirectory>src/main/webapp</warSourceDirectory>
						<warName>Spring4MVCFormValidationExample</warName>
						<failOnMissingWebXml>false</failOnMissingWebXml>
					</configuration>
				</plugin>
			</plugins>
		</pluginManagement>
		<finalName>Spring4MVCFormValidationExample</finalName>
	</build>
</project>
 

首先要注意這里是 maven-war-plugin 插件聲明。由于我們使用的是全注解配置,我們甚至不包括在 web.xml 中,所以我們需要配置這個(gè)插件,以避免Maven構(gòu)建war包失敗。在驗(yàn)證部分 validation-api 代表規(guī)范, 而hibernate-validator是本規(guī)范的一個(gè)實(shí)現(xiàn)。hibernate-validator還提供了一些它自己的注解(@Email,@NotEmpty等)不屬于規(guī)范的一部分。

伴隨著這一點(diǎn),我們也包括JSP/Servlet/Jstl 的依賴關(guān)系,也將需要為使用 servlet API和JSTL視圖在我們的代碼中。在一般情況下,容器可能已經(jīng)包含了這些庫,從而在pom.xml中我們可以設(shè)置范圍作為“provided”。

此外,這里還單獨(dú)下載了 bootstrap.css ,為了演示在基于注解的配置如何使用資源處理。

第3步:創(chuàng)建POJO/域?qū)ο?

訪問的對象將充當(dāng)一個(gè)輔助bean的形式保存用戶提供簽證申請表提交的數(shù)據(jù)。我們將注釋,以驗(yàn)證屬性(使用驗(yàn)證注釋)。

com.yiibai.springmvc.model.Student

package com.yiibai.springmvc.model;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Past;
import javax.validation.constraints.Size;

import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.NotEmpty;
import org.springframework.format.annotation.DateTimeFormat;

public class Student implements Serializable {

	@Size(min=3, max=30)
	private String firstName;

	@Size(min=3, max=30)
	private String lastName;

	@NotEmpty
	private String sex;

	@DateTimeFormat(pattern="yyyy-MM-dd")
	@Past @NotNull
	private Date dob;

	@Email @NotEmpty
	private String email;

	@NotEmpty
	private String section;

	@NotEmpty
	private String country;

	private boolean firstAttempt;

	@NotEmpty
	private List<String> subjects = new ArrayList<String>();

	public String getFirstName() {
		return firstName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	public String getLastName() {
		return lastName;
	}

	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

	public String getSex() {
		return sex;
	}

	public void setSex(String sex) {
		this.sex = sex;
	}

	public Date getDob() {
		return dob;
	}

	public void setDob(Date dob) {
		this.dob = dob;
	}

	public String getEmail() {
		return email;
	}

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

	public String getSection() {
		return section;
	}

	public void setSection(String section) {
		this.section = section;
	}

	public String getCountry() {
		return country;
	}

	public void setCountry(String country) {
		this.country = country;
	}

	public boolean isFirstAttempt() {
		return firstAttempt;
	}

	public void setFirstAttempt(boolean firstAttempt) {
		this.firstAttempt = firstAttempt;
	}

	public List<String> getSubjects() {
		return subjects;
	}

	public void setSubjects(List<String> subjects) {
		this.subjects = subjects;
	}

	@Override
	public String toString() {
		return "Student [firstName=" + firstName + ", lastName=" + lastName
				+ ", sex=" + sex + ", dob=" + dob + ", email=" + email
				+ ", section=" + section + ", country=" + country
				+ ", firstAttempt=" + firstAttempt + ", subjects=" + subjects
				+ "]";
	}

}

在上面的代碼中:@Size, @Past & @NotNull 是標(biāo)準(zhǔn)的標(biāo)注,而@NotEmpty&@Emailare是規(guī)范的一部分。

第4步:添加控制器

控制器加入將有助于處理GET和POST請求。

com.yiibai.springmvc.controller.HelloWorldController

package com.yiibai.springmvc.controller;

import java.util.ArrayList;
import java.util.List;

import javax.validation.Valid;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.websystique.springmvc.model.Student;

@Controller
@RequestMapping("/")
public class HelloWorldController {

	/*
	 * This method will serve as default GET handler.
	 *
	 */
	@RequestMapping(method = RequestMethod.GET)
	public String newRegistration(ModelMap model) {
		Student student = new Student();
		model.addAttribute("student", student);
		return "enroll";
	}

	/*
	 * This method will be called on form submission, handling POST request
	 * It also validates the user input
	 */
	@RequestMapping(method = RequestMethod.POST)
	public String saveRegistration(@Valid Student student, BindingResult result, ModelMap model){

		if(result.hasErrors()) {
		        return "enroll";
		}

		model.addAttribute("success", "Dear "+ student.getFirstName()+" , your Registration completed successfully");
		return "success";
	}

	/*
	 * Method used to populate the Section list in view.
	 * Note that here you can call external systems to provide real data.
	 */
	@ModelAttribute("sections")
	public List<String> initializeSections() {

		List<String> sections = new ArrayList<String>();
		sections.add("Graduate");
		sections.add("Post Graduate");
		sections.add("Research");
 		return sections;
	}

	/*
	 * Method used to populate the country list in view.
	 * Note that here you can call external systems to provide real data.
	 */
	@ModelAttribute("countries")
	public List<String> initializeCountries() {

		List<String> countries = new ArrayList<String>();
		countries.add("USA");
		countries.add("CHINA");
		countries.add("FRANCE");
		countries.add("GERMANY");
		countries.add("ITALY");
		countries.add("OTHER");
 		return countries;
	}

	/*
	 * Method used to populate the subjects list in view.
	 * Note that here you can call external systems to provide real data.
	 */
	@ModelAttribute("subjects")
	public List<String> initializeSubjects() {

		List<String> subjects = new ArrayList<String>();
		subjects.add("Physics");
		subjects.add("Chemistry");
		subjects.add("Life Science");
		subjects.add("Political Science");
		subjects.add("Computer Science");
		subjects.add("Mathmatics");
 		return subjects;
	}

} 

@Controller表明這個(gè)類是一個(gè)控制器在處理具有模式映射的@RequestMapping請求。這里使用 ‘/’, 它被作為默認(rèn)的控制器。方法newRegistration是相當(dāng)簡單的,注解為@ RequestMethod.GET服務(wù)默認(rèn)是GET請求,使用模型對象,以服務(wù)為形式的數(shù)據(jù),并呈現(xiàn)包含空白表單的網(wǎng)頁。

方法initializeSections, initializeCountries & initializeSubjects是簡單地創(chuàng)建請求級別的對象,其值在視圖/JSP中將被使用。

方法saveRegistration 標(biāo)注有@ RequestMethod.POST,并將處理表單提交POST請求。注意本方法的參數(shù)和它們的順序。

@Valid要求spring來驗(yàn)證相關(guān)的對象(學(xué)生)。 BindingResult包含此驗(yàn)證,并可能在此驗(yàn)證過程中發(fā)生(產(chǎn)生)任何錯(cuò)誤的結(jié)果。請注意,BindingResult一定要在之后立即生效對象,否則spring將無法驗(yàn)證并且將一個(gè)異常拋出。

注意,在校驗(yàn)失敗后,默認(rèn)/廣義錯(cuò)誤消息顯示在屏幕上這可能不是所期望的。相反,可以重寫此行為提供具體到每個(gè)字段中國際化消息。為了做到這一點(diǎn),我們需要配置 MessageSource 在應(yīng)用程序配置類,并提供包含我們下一步將配置實(shí)際的信息屬性文件。

第5步:添加配置類

com.yiibai.springmvc.configuration.HelloWorldConfiguration

package com.yiibai.springmvc.configuration;

import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.yiibai.springmvc")
public class HelloWorldConfiguration extends WebMvcConfigurerAdapter {

	/*
	 * Configure View Resolver
	 */
	@Bean
	public ViewResolver viewResolver() {
		InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
		viewResolver.setViewClass(JstlView.class);
		viewResolver.setPrefix("/WEB-INF/views/");
		viewResolver.setSuffix(".jsp");
		return viewResolver;
	}

	/*
	 * Configure ResourceHandlers to serve static resources like CSS/ Javascript etc...
	 *
	 */
	@Override
	public void addResourceHandlers(ResourceHandlerRegistry registry) {
	    registry.addResourceHandler("/static/**").addResourceLocations("/static/");
	}

	/*
	 * Configure MessageSource to provide internationalized messages
	 *
	 */

	@Bean
	public MessageSource messageSource() {
	    ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
	    messageSource.setBasename("messages");
	    return messageSource;
	}

} 

@Configuration指示該類包含注解為@Bean生產(chǎn)Bean管理是由Spring容器的一個(gè)或多個(gè) bean 的方法。@EnableWebMvc 等效于 mvc:annotation-driven 在XML文件中。它能夠?yàn)槭褂聾RequestMapping 向特定的方法傳入的請求映射@Controller-annotated類。 @ComponentScan 等效于  context:component-scan base-package="..." 提供具有到哪里查找管理Spring beans/類。

方法 ViewResolver 配置一個(gè) ViewResolver 用來找出真正的視圖。方法 addResourceHandlers 配置 ResourceHandler 靜態(tài)資源。CSS, JavaScript, images 等都是靜態(tài)的資源在你的頁面里。上面的配置表示,所有的資源請求開始/static/,將從webapps文件夾下提供/static/。在這個(gè)例子中,我們把所有的css文件放在 Web應(yīng)用程序的 /static/css 目錄中。注意,此方法在 WebMvcConfigurerAdapter 中定義,因此我們需要擴(kuò)展這個(gè)類來注冊我們的靜態(tài)資源覆蓋此方法。

方法為 messageSource 配置消息包,以支持[國際化]消息屬性文件。請注意方法 baseName 提供的參數(shù)(消息)。Spring 將搜索應(yīng)用程序類路徑中一個(gè)名為messages.properties文件。讓我們添加的文件:

src/main/resources/messages.properties

Size.student.firstName=First Name must be between {2} and {1} characters long
Size.student.lastName=Last Name must be between {2} and {1} characters long
NotEmpty.student.sex=Please specify your gender
NotNull.student.dob=Date of birth can not be blank
Past.student.dob=Date of birth must be in the past
Email.student.email=Please provide a valid Email address
NotEmpty.student.email=Email can not be blank
NotEmpty.student.country=Please select your country
NotEmpty.student.section=Please select your section
NotEmpty.student.subjects=Please select at least one subject
typeMismatch=Invalid format
請注意,上述消息按照特定的模式
{ValidationAnnotationClass}.{modelObject}.{fieldName} 

此外,根據(jù)具體的注釋(如@Size),也可以用傳遞參數(shù)給這些消息:{0},{1},..{i}

以XML格式上述結(jié)構(gòu)將是
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
    http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
 
    <context:component-scan base-package="com.yiibai.springmvc" />
    <mvc:annotation-driven/>

    <mvc:resources mapping="/static/**" location="/static/" />
    <mvc:default-servlet-handler />


    <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
        <property name="basename">
            <value>messages</value>
        </property>
    </bean>


    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix">
            <value>/WEB-INF/views/</value>
        </property>
        <property name="suffix">
            <value>.jsp</value>
        </property>
    </bean>
 
</beans>

第6步:添加視圖(簡單的JSP頁面)

我們將添加兩個(gè)簡單的JSP頁面。第一個(gè)將包含一個(gè)表單,從用戶接收輸入, 而第二個(gè)在當(dāng)表單輸入驗(yàn)證成功時(shí)會(huì)顯示成功消息給用戶。

下面是代碼,用于包括靜態(tài)資源(在我們的例子中使用 bootstrap.css)
<link href="<c:url value='/static/css/bootstrap.css' />" rel="stylesheet"></link> 

注意靜態(tài)資源路徑。既然我們已經(jīng)在前面的步驟配置資源處理程序 /static/**, css文件將搜索 /static/文件夾。

完整的JSP文件如下所示:

WEB-INF/views/enroll.jsp

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
	<title>Student Enrollment Form</title>
	<link href="<c:url value='/static/css/bootstrap.css' />" rel="stylesheet"></link>
	<link href="<c:url value='/static/css/custom.css' />" rel="stylesheet"></link>
</head>

<body>
 	<div class="form-container">
 	<h1>Enrollment Form</h1>
	<form:form method="POST" modelAttribute="student" class="form-horizontal">
		<div class="row">
			<div class="form-group col-md-12">
				<label class="col-md-3 control-lable" for="firstName">First Name</label>
				<div class="col-md-7">
					<form:input type="text" path="firstName" id="firstName" class="form-control input-sm"/>
					<div class="has-error">
						<form:errors path="firstName" class="help-inline"/>
					</div>
				</div>
			</div>
		</div>

		<div class="row">
			<div class="form-group col-md-12">
				<label class="col-md-3 control-lable" for="lastName">Last Name</label>
				<div class="col-md-7">
					<form:input type="text" path="lastName" id="lastName" class="form-control input-sm"/>
					<div class="has-error">
						<form:errors path="lastName" class="help-inline"/>
					</div>
				</div>
			</div>
		</div>

		<div class="row">
			<div class="form-group col-md-12">
				<label class="col-md-3 control-lable" for="sex">Sex</label>
				<div class="col-md-7" class="form-control input-sm">
					<form:radiobutton path="sex" value="M" />Male 
	    			<form:radiobutton path="sex" value="F" />Female
					<div class="has-error">
						<form:errors path="sex" class="help-inline"/>
					</div>
				</div>
			</div>
		</div>

		<div class="row">
			<div class="form-group col-md-12">
				<label class="col-md-3 control-lable" for="dob">Date of birth</label>
				<div class="col-md-7">
					<form:input type="text" path="dob" id="dob" class="form-control input-sm"/>
					<div class="has-error">
						<form:errors path="dob" class="help-inline"/>
					</div>
				</div>
			</div>
		</div>

		<div class="row">
			<div class="form-group col-md-12">
				<label class="col-md-3 control-lable" for="email">Email</label>
				<div class="col-md-7">
					<form:input type="text" path="email" id="email" class="form-control input-sm"/>
					<div class="has-error">
						<form:errors path="email" class="help-inline"/>
					</div>
				</div>
			</div>
		</div>


		<div class="row">
			<div class="form-group col-md-12">
				<label class="col-md-3 control-lable" for="section">Section</label>
				<div class="col-md-7" class="form-control input-sm">
					<form:radiobuttons path="section" items="${sections}" />
					<div class="has-error">
						<form:errors path="section" class="help-inline"/>
					</div>
				</div>
			</div>
		</div>


		<div class="row">
			<div class="form-group col-md-12">
				<label class="col-md-3 control-lable" for="country">Country</label>
				<div class="col-md-7">
					<form:select path="country" id="country" class="form-control input-sm">
				        <form:option value="">Select Country</form:option>
			    	    <form:options items="${countries}" />
				    </form:select>
					<div class="has-error">
						<form:errors path="country" class="help-inline"/>
					</div>
				</div>
			</div>
		</div>

		<div class="row">
			<div class="form-group col-md-12">
				<label class="col-md-3 control-lable" for="firstAttempt">First Attempt ?</label>
				<div class="col-md-1">
					<form:checkbox path="firstAttempt" class="form-control input-sm"/>
					<div class="has-error">
						<form:errors path="firstAttempt" class="help-inline"/>
					</div>
				</div>
			</div>
		</div>
	

		<div class="row">
			<div class="form-group col-md-12">
				<label class="col-md-3 control-lable" for="subjects">Subjects</label>
				<div class="col-md-7">
					<form:select path="subjects" items="${subjects}" multiple="true" class="form-control input-sm"/>
					<div class="has-error">
						<form:errors path="subjects" class="help-inline"/>
					</div>
				</div>
			</div>
		</div>

		<div class="row">
			<div class="form-actions floatRight">
				<input type="submit" value="Register" class="btn btn-primary btn-sm">
			</div>
		</div>
	</form:form>
	</div>
</body>
</html>

WEB-INF/views/success.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
	<title>Student Enrollment Detail Confirmation</title>
	<link href="<c:url value='/static/css/custom.css' />" rel="stylesheet"></link>
</head>
<body>
	<div class="success">
		Confirmation message : ${success}
		<br>
		We have also sent you a confirmation mail to your email address : ${student.email}.
	</div>
</body>
</html>

第7步:添加初始化器類

com.yiibai.springmvc.configuration.HelloWorldInitializer

package com.yiibai.springmvc.configuration;

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 HelloWorldInitializer implements WebApplicationInitializer {

	public void onStartup(ServletContext container) throws ServletException {

		AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
		ctx.register(HelloWorldConfiguration.class);
		ctx.setServletContext(container);

		ServletRegistration.Dynamic servlet = container.addServlet(
				"dispatcher", new DispatcherServlet(ctx));

		servlet.setLoadOnStartup(1);
		servlet.addMapping("/");
	}

} 

內(nèi)容上面類似之前教程的 web.xml 文件內(nèi)容,因?yàn)槲覀兪褂玫氖乔岸丝刂破鞯腄ispatcherServlet,分配映射(URL模式的XML)和而不是提供給Spring配置文件(spring-servlet.xml)的路徑,在這里,我們使用注冊配置類。

更新:請注意,上面的類可以寫成更加簡潔[和這是最佳方法],通過擴(kuò)展 AbstractAnnotationConfigDispatcherServletInitializer 基類,如下所示:

package com.websystique.springmvc.configuration;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class HelloWorldInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

	@Override
	protected Class<?>[] getRootConfigClasses() {
		return new Class[] { HelloWorldConfiguration.class };
	}
 
	@Override
	protected Class<?>[] getServletConfigClasses() {
		return null;
	}
 
	@Override
	protected String[] getServletMappings() {
		return new String[] { "/" };
	}

}

第8步:構(gòu)建和部署應(yīng)用程序

有一點(diǎn)要記住,如:WebApplicationInitializer,Spring 基于Java 配置API是依賴Servlet3.0容器的。所以一定要確保你沒有使用 Servlet 聲明任何在 web.xml 小于3.0。對于我們的情況,我們要從應(yīng)用程序中刪除 web.xml 文件。

現(xiàn)在構(gòu)建war 或通過Maven 命令行(mvn clean install)。 部署 war 到Servlet3.0容器。

運(yùn)行應(yīng)用程序,訪問URL:http://localhost:8080/Spring4MVCFormValidationExample
得到的初始頁面如下圖所示:

現(xiàn)在,如果你提交,會(huì)得到驗(yàn)證錯(cuò)誤(在 message.properties 中用戶定義的消息)

現(xiàn)在提供示例輸入

現(xiàn)在提交表單,結(jié)果如下:

到這里,完成!
代碼下載:http://pan.baidu.com/s/1nukn6HV