數(shù)據(jù)綁定
數(shù)據(jù)綁定流程
- SpringMVC主框架將ServletRequest對象及目標方法的入?yún)嵗齻鬟f給
WebDataBinderFactory實例,以創(chuàng)建DataBinder實例對象。 -
DataBinder調(diào)用裝配在SpringMVC上下文中的ConversionService組件進行數(shù)據(jù)類型轉(zhuǎn)換、數(shù)據(jù)格式化工作,將Servlet中的請求信息填充到入?yún)ο笾小?/li> - 調(diào)用
Validator組件對已經(jīng)綁定了請求消息的入?yún)ο筮M行數(shù)據(jù)合法性校驗,并最終生成數(shù)據(jù)綁定結果BindingData對象。 - SpringMVC抽取
BindingResult中的入?yún)ο蠛托r炲e誤對象,將他們賦給處理方法的響應入?yún)ⅰ?/li>
類型轉(zhuǎn)換
自定義類型轉(zhuǎn)換器
ConversionService是Spring類型轉(zhuǎn)換體系的核心接口,可以利用ConversionServiceFactoryBean在Spring的IOC容器中定義一個ConversionService。Spring將自動識別出IOC容器中的ConversionService,并在bean屬性配置及SpringMVC處理方法入?yún)⒔壎ǖ葓龊鲜褂盟M行數(shù)據(jù)的轉(zhuǎn)換。
可以通過ConversionServiceFactoryBean的converters屬性注冊自定義的類型轉(zhuǎn)換器。
<bean id="conversionService"
class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<ref bean="employeeConverter"/>
</set>
</property>
</bean>
Spring支持的轉(zhuǎn)換器
Spring定義了3種類型的轉(zhuǎn)換器接口,實現(xiàn)任意一個轉(zhuǎn)換器接口都可以作為自定義轉(zhuǎn)換器注冊到ConversionServiceFactroyBean中:
-
Converter<S,T>:將S類型對象轉(zhuǎn)為T類型對象。 -
ConverterFactory:將相同系列多個“同質(zhì)”Converter封裝在一起,如果希望將一種類型的對象轉(zhuǎn)換為另一種類型及其子類的對象(例如將String轉(zhuǎn)換為Number及Number子類(Integer、Long、Double等)對象)可使用該轉(zhuǎn)換器工廠類。 -
GenericConverter:會根據(jù)源類對象及目標類對象所在的宿主類中的上下文信息進行類型轉(zhuǎn)換。
在配置文件中使用<mvc:annotation-driven conversion-service="xxxxx"/>會將自定義的ConversionService注冊到SpringMVC的上下文中。,其中xxxxx是自定義的類型轉(zhuǎn)換器名,例如:
<mvc:annotation-driven conversion-service="conversionService"/>
<!-- 配置ConversionService-->
<bean id="conversionService"
class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<ref bean="employeeConverter"/>
</set>
</property>
</bean>
我們來自定義一個類型轉(zhuǎn)換器,我們希望輸入一個字符串(lastname-email-gender-department.id),然后提交后能轉(zhuǎn)換為一個Employee對象。
- 首先建立我們的兩個實體類及對應的dao類
package com.cerr.springmvc.crud.entities;
public class Employee {
private Integer id;
private String lastname;
private String email;
private Integer gender;
private Department department;
public Employee(){}
public Employee(Integer id, String lastname, String email, Integer gender, Department department) {
this.id = id;
this.lastname = lastname;
this.email = email;
this.gender = gender;
this.department = department;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Integer getGender() {
return gender;
}
public void setGender(Integer gender) {
this.gender = gender;
}
public Department getDepartment() {
return department;
}
public void setDepartment(Department department) {
this.department = department;
}
@Override
public String toString() {
return "Employee{" +
"id=" + id +
", lastname='" + lastname + '\'' +
", email='" + email + '\'' +
", gender=" + gender +
", department=" + department +
'}';
}
}
package com.cerr.springmvc.crud.entities;
public class Department {
private Integer id;
private String departmentName;
public Department() {}
public Department(Integer id, String departmentName) {
super();
this.id = id;
this.departmentName = departmentName;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getDepartmentName() {
return departmentName;
}
public void setDepartmentName(String departmentName) {
this.departmentName = departmentName;
}
}
package com.cerr.springmvc.crud.dao;
import com.cerr.springmvc.crud.entities.Department;
import com.cerr.springmvc.crud.entities.Employee;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@Repository
public class EmployeeDao {
private static Map <Integer, Employee > employees = null;
@Autowired
private DepartmentDao departmentDao;
static{
employees = new HashMap <Integer, Employee>();
employees.put(1001, new Employee(1001, "E-AA", "aa@163.com", 1, new Department(101, "D-AA")));
employees.put(1002, new Employee(1002, "E-BB", "bb@163.com", 1, new Department(102, "D-BB")));
employees.put(1003, new Employee(1003, "E-CC", "cc@163.com", 0, new Department(103, "D-CC")));
employees.put(1004, new Employee(1004, "E-DD", "dd@163.com", 0, new Department(104, "D-DD")));
employees.put(1005, new Employee(1005, "E-EE", "ee@163.com", 1, new Department(105, "D-EE")));
}
private static Integer initId = 1006;
public void save(Employee employee){
if(employee.getId() == null){
employee.setId(initId++);
}
employee.setDepartment(departmentDao.getDepartment(employee.getDepartment().getId()));
employees.put(employee.getId(), employee);
}
public Collection <Employee> getAll(){
return employees.values();
}
public Employee get(Integer id){
return employees.get(id);
}
public void delete(Integer id){
employees.remove(id);
}
}
- 建立我們自定義的轉(zhuǎn)換器類,需要實現(xiàn)
Converter<S,T>接口
package com.cerr.springmvc.converters;
import com.cerr.springmvc.crud.entities.Department;
import com.cerr.springmvc.crud.entities.Employee;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;
//該注釋讓該類能加載到IOC容器中
@Component
public class EmployeeConverter implements Converter<String, Employee > {
/**
* 這是轉(zhuǎn)換的方法,對傳入的字符串進行分割。
* 然后填充Employee的參數(shù)來初始化一個Employee實例,然后返回
* @param s
* @return
*/
@Override
public Employee convert(String s) {
if (s != null){
String [] vals = s.split("-");
if (vals != null && vals.length == 4){
String lastName = vals[0];
String email = vals[1];
Integer gender = Integer.parseInt(vals[2]);
Department department = new Department();
department.setId(Integer.parseInt(vals[3]));
Employee employee = new Employee(null,lastName,email,gender,department);
System.out.println(employee);
return employee;
}
}
return null;
}
}
- 在配置文件中配置:
<?xml version="1.0" encoding="UTF-8"?>
<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"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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 http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 配置自動掃描的包-->
<context:component-scan base-package="com.cerr.springmvc"/>
<!-- 配置視圖解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/webViews/"/>
<property name="suffix" value=".jsp"/>
</bean>
<mvc:default-servlet-handler/>
<mvc:annotation-driven conversion-service="conversionService"/>
<!-- 配置ConversionService-->
<bean id="conversionService"
class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<!--
因為我們自己寫的自定義轉(zhuǎn)換器類使用了Component進行標識,
所以此處的bean名直接寫employeeConverter(類名第一個字母小寫)即可
-->
<ref bean="employeeConverter"/>
</set>
</property>
</bean>
</beans>
測試:
package com.cerr.springmvc.test;
import com.cerr.springmvc.crud.dao.EmployeeDao;
import com.cerr.springmvc.crud.entities.Employee;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class SpringMVCTest1 {
@Autowired
private EmployeeDao employeeDao;
@RequestMapping(value = "/testConversionServiceConverer",method = RequestMethod.POST)
public String testConverter(@RequestParam("employee") Employee employee){
employeeDao.save(employee);
System.out.println(employee);
return "redirect:/emps";
}
}
表單:
<%@ page import="java.util.Map" %>
<%@ page import="java.util.HashMap" %>
<%--
Created by IntelliJ IDEA.
User: 白菜
Date: 2019/11/13
Time: 21:10
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/testConversionServiceConverer" method="POST">
<!-- 格式:lastname-email-gender-department.id 例如:GG-gg@cerr.com-0-105 -->
Employee : <input type="text" name="employee" />
<input type="submit" value="submit" />
</form>
</body>
</html>
輸入:GG-gg@cerr.com-0-105
結果:在控制臺成功打印出Employee(轉(zhuǎn)換成功)

關于mvc:annotation-driven
<mvc:annotation-driven/>會自動注冊RequestMappingHandlerMapping、RequestMappingHandlerAdapter與ExceptionHandlerExceptionResolver三個bean。
還將提供以下支持:
- 支持使用
ConversionService實例對表單參數(shù)進行類型轉(zhuǎn)換 - 支持使用
@NumberFormatannotation、@DateTimeFormat注解完成數(shù)據(jù)類型的格式化 - 支持使用
@Valid注解對JavaBean實例進行JSR 303驗證 - 支持使用
@RequestBody和@ResponseBody注解
@InitBinder
由@InitBinder標識的方法,可以對WebDataBinder對象進行初始化。WebDataBinder是DataBinder的子類,用于完成由表單字段到JavaBean屬性的綁定。
@InitBinder方法不能有返回值,必須聲明為void;@InitBinder方法的參數(shù)通常是WebDataBinder。
例如我們這里定義一個initBinder方法,然后方法體里面的設置對于表單的lastname屬性不允許綁定到JavaBean順序。
@InitBinder
public void initBinder(WebDataBinder binder){
binder.setDisallowedFields("lastname");
}
數(shù)據(jù)格式化
對屬性對象的輸入/輸出進行格式化,從其本質(zhì)上講依然屬于“類型轉(zhuǎn)換”的范疇。Spring在格式化模塊中定義了一個實現(xiàn)ConversionService接口的FarmattingConversionService實現(xiàn)類,該實現(xiàn)類擴展了GenericConversionService,因此它既具有類型轉(zhuǎn)換的功能,又具有格式化的功能。FormattingConversionService擁有一個FormattingConversionServiceFactoryBean工廠類,后者用于在Spring上下文中構造前者。
對于FormattingConversionServiceFactoryBean,內(nèi)部已經(jīng)注冊了:
-
NumberFormatAnnotationFormatterFactory:支持對數(shù)字類型屬性使用@NumberFormat注解 -
JodaDateTimeFormatAnnotationFormatterFactory:支持對日期類型的屬性使用@DataTimeFormat注解
如果裝配了FormattingConversionServiceFactoryBean,就可以在SpringMVC入?yún)⒔壎澳P蛿?shù)據(jù)輸出時使用注解驅(qū)動了,<mvc:annotation-driven />默認創(chuàng)建的ConversionService實例即為FormattingConversionServiceFactoryBean。
日期格式化
@DateTimeFOrmat注解可對java.util.Date、java.util.Calendar、java.long.Long時間類型進行標注,比較重要的屬性:
-
pattern屬性:類型為字符串,指定解析/格式化字段數(shù)據(jù)的模式,如:"yyyy-MM-dd hh:mm:ss"。
package com.cerr.springmvc.crud.entities;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.format.annotation.NumberFormat;
import java.util.Date;
public class Employee {
private Integer id;
private String lastname;
private String email;
private Integer gender;
private Department department;
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date birth;
private Float sarly;
public Employee(){}
public Employee(Integer id, String lastname, String email, Integer gender, Department department) {
this.id = id;
this.lastname = lastname;
this.email = email;
this.gender = gender;
this.department = department;
}
public Date getBirth() {
return birth;
}
public void setBirth(Date birth) {
this.birth = birth;
}
public Float getSarly() {
return sarly;
}
public void setSarly(Float sarly) {
this.sarly = sarly;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Integer getGender() {
return gender;
}
public void setGender(Integer gender) {
this.gender = gender;
}
public Department getDepartment() {
return department;
}
public void setDepartment(Department department) {
this.department = department;
}
@Override
public String toString() {
return "Employee{" +
"id=" + id +
", lastname='" + lastname + '\'' +
", email='" + email + '\'' +
", gender=" + gender +
", department=" + department +
", birth=" + birth +
", sarly=" + sarly +
'}';
}
}
在上面的例子中,我們注解的pattern為"yyyy-MM-dd",因此當我們輸入的日期為"yyyy-MM-dd"時都能給解析并轉(zhuǎn)換成Date。
數(shù)值格式化
@NumberFormat可對類似數(shù)字類型的屬性進行標注,它擁有兩個互斥的屬性:
-
style
類型為Numberformat.Style。用于指定樣式類型,包括三種:Style.NUMBER(正常數(shù)字類型)、Style.CURRENCY(貨幣類型)、Style.PERCENT(百分數(shù)類型)。 -
pattern
類型為String,自定義樣式,如pattern="#,###"。
package com.cerr.springmvc.crud.entities;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.format.annotation.NumberFormat;
import java.util.Date;
public class Employee {
private Integer id;
private String lastname;
private String email;
private Integer gender;
private Department department;
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date birth;
@NumberFormat(pattern = "#,###,###.#")
private Float sarly;
public Employee(){}
public Employee(Integer id, String lastname, String email, Integer gender, Department department) {
this.id = id;
this.lastname = lastname;
this.email = email;
this.gender = gender;
this.department = department;
}
public Date getBirth() {
return birth;
}
public void setBirth(Date birth) {
this.birth = birth;
}
public Float getSarly() {
return sarly;
}
public void setSarly(Float sarly) {
this.sarly = sarly;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Integer getGender() {
return gender;
}
public void setGender(Integer gender) {
this.gender = gender;
}
public Department getDepartment() {
return department;
}
public void setDepartment(Department department) {
this.department = department;
}
@Override
public String toString() {
return "Employee{" +
"id=" + id +
", lastname='" + lastname + '\'' +
", email='" + email + '\'' +
", gender=" + gender +
", department=" + department +
", birth=" + birth +
", sarly=" + sarly +
'}';
}
}
上面的代碼標識了@NumberFormat(pattern = "#,###,###.#")后,例如輸入1,234,567.8,就能自動轉(zhuǎn)成數(shù)字。
數(shù)據(jù)校驗
JSR303
JSR 303是Java為Bean數(shù)據(jù)合法性校驗提供的標準框架,它已經(jīng)包含在JavaEE6.0中,JSR 303通過在Bean屬性上標注類似于@NotNull、@Max等標準的注解指定校驗規(guī)則,并通過標準的驗證接口對Bean進行驗證。
| 注解 | 功能說明 |
|---|---|
@Null |
被注釋的元素必須為null |
@NotNull |
被注釋的元素必須不為null |
@AssertTure |
被注釋的元素必須為true |
@AssertFalse |
被注釋的元素必須為false |
@Min(value) |
被注釋的元素必須是一個數(shù)字,其值必須大于等于指定的最小值 |
@Max(value) |
被注釋的元素必須是一個數(shù)字,其值必須小于等于指定的最大值 |
@DecimalMin(value) |
被注釋的元素必須是一個數(shù)字,其值必須大于等于指定的最小值 |
@DecimalMax(value) |
被注釋的元素必須是一個數(shù)字,其值必須小于等于指定的最大值 |
@Size(max,min) |
被注釋的元素必須在指定的范圍內(nèi) |
@Digits(integer,fraction) |
被注釋的元素必須是一個數(shù)字,其值必須在可接受的范圍內(nèi) |
@Past |
被注釋的元素必須是一個過去的日期 |
@Future |
被注釋的元素必須是一個將來的日期 |
@Pattern(value) |
被注釋的元素必須符合指定的正則表達式 |
Hibernate Validator擴展注解
Hibernate Validator是JSR 303的一個參考實現(xiàn),除支持所有標準的校驗注解外,它還支持以下的擴展注解
| 注解 | 功能說明 |
|---|---|
@Email |
被注釋的元素必須是電子郵箱地址 |
@Length |
被注釋的字符串的大小必須在指定的范圍內(nèi) |
@NotEmpty |
被注釋的字符串必須非空 |
@Range |
被注釋的元素必須在合適的范圍內(nèi) |
SpringMVC數(shù)據(jù)校驗
Spring4.0擁有自己獨立的數(shù)據(jù)校驗框架,同時支持JSR 303標準的校驗框架。Spring在進行數(shù)據(jù)綁定時,可同時調(diào)用校驗框架完成數(shù)據(jù)校驗工作。在SpringMVC中,可直接通過注解驅(qū)動的方式進行數(shù)據(jù)校驗。
Spring的LocalValidatorFactoryBean既實現(xiàn)了Spring的Validator接口,也實現(xiàn)了JSR 303的Validator接口,只要在Spring容器中定義一個LocalValidatorFactoryBean,即可將其注入到需要數(shù)據(jù)校驗的Bean中。
Spring本身并沒有提供JSR 303的實現(xiàn),所以必須將JSR 303的jar包放到類路徑下。
<mvc:annotation-driven />會默認裝配好一個LocalValidatorFactroyBean,通過在處理方法的入?yún)⑸蠘俗?code>@valid注解即可讓SpringMVC在完成數(shù)據(jù)綁定后執(zhí)行數(shù)據(jù)校驗的工作。
在已經(jīng)標注了JSR 303注解的表單/命令對象前標注一個@Valid,SpringMVC框架在將請求參數(shù)綁定到該入?yún)ο蠛?,就會調(diào)用校驗框架根據(jù)注解聲明的校驗規(guī)則實施校驗。
SpringMVC是通過對處理方法簽約的規(guī)約來保存校驗結果的:前一個表單/命令對象的校驗結果保存到隨后的入?yún)⒅?,這個保存校驗結果的入?yún)⒈仨毷?code>BindingResult或Errors類型,這兩個類都位于org.springframework.validation包中。要注意的一點是:需要校驗的Bean對象和其綁定結果對象或錯誤對象是成對出現(xiàn)的,它們之間不允許聲明其他的入?yún)?/strong>
例如下面的代碼是錯誤的:
@RequestMapping(value = "/emp",method = RequestMethod.POST)
public String save(@Valid Employee employee, Map<String,Object> map,BindingResult result){
return "redirect:/emps";
}
Employee和BindingResult兩個參數(shù)應該是在一起的,例如下面的才是正確的:
@RequestMapping(value = "/emp",method = RequestMethod.POST)
public String save(@Valid Employee employee, BindingResult result,Map<String,Object> map){
return "redirect:/emps";
}
Errors接口提供了獲取錯誤信息的方法,如getErrorCount()或getFieldErrors(String field),BindingResult擴展了Errors接口。
@RequestMapping(value = "/emp",method = RequestMethod.POST)
public String save(@Valid Employee employee, BindingResult result,Map<String,Object> map){
System.out.println("save:"+employee);
/**
* 如果轉(zhuǎn)換出錯
*/
if (result.getErrorCount() > 0){
System.out.println("出錯了:");
for (FieldError error : result.getFieldErrors()){
System.out.println(error.getField() + ":" + error.getDefaultMessage());
}
map.put("departments",departmentDao.getDepartments());
//若驗證出錯,則轉(zhuǎn)向定制的頁面
return "input";
}
employeeDao.save(employee);
return "redirect:/emps";
}
SpringMVC整合擴展的Hibernate Validator驗證框架數(shù)據(jù)校驗的步驟
- 使用JSR 303驗證標準完成數(shù)據(jù)校驗。
- 加入hibernate validator驗證框架的jar包。
- 在SpringMVC配置文件中添加
<mvc:annotation-dirven /> - 需要在bean的屬性上添加對應的注解
- 在目標方法bean類型的前面添加
@Valid注解
首先在idea中加入jar包,并添加在Artifacts中

然后在配置文件中添加<mvc:annotation-dirven />,因為該配置在上面類型轉(zhuǎn)換時定義了一個自定義的類型轉(zhuǎn)換器,因此配置了FormattingConversionServiceFactoryBean,如果不需要使用自定義類型轉(zhuǎn)換器的話,這部分代碼可以去掉:
<?xml version="1.0" encoding="UTF-8"?>
<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"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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 http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 配置自動掃描的包-->
<context:component-scan base-package="com.cerr.springmvc"/>
<!-- 配置視圖解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/webViews/"/>
<property name="suffix" value=".jsp"/>
</bean>
<mvc:default-servlet-handler/>
<mvc:annotation-driven conversion-service="conversionService"/>
<!-- 配置ConversionService org.springframework.context.support.ConversionServiceFactoryBean也可以-->
<bean id="conversionService"
class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="converters">
<set>
<ref bean="employeeConverter"/>
</set>
</property>
</bean>
</beans>
對上面的Employee類,我們可以做一些驗證如下,添加@NotNull、@Email、@Past注解:
package com.cerr.springmvc.crud.entities;
import org.hibernate.validator.constraints.Email;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.format.annotation.NumberFormat;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Past;
import java.util.Date;
public class Employee {
private Integer id;
@NotNull
private String lastname;
@Email
private String email;
private Integer gender;
private Department department;
@Past
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date birth;
@NumberFormat(pattern = "#,###,###.#")
private Float sarly;
public Employee(){}
public Employee(Integer id, String lastname, String email, Integer gender, Department department) {
this.id = id;
this.lastname = lastname;
this.email = email;
this.gender = gender;
this.department = department;
}
public Date getBirth() {
return birth;
}
public void setBirth(Date birth) {
this.birth = birth;
}
public Float getSarly() {
return sarly;
}
public void setSarly(Float sarly) {
this.sarly = sarly;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Integer getGender() {
return gender;
}
public void setGender(Integer gender) {
this.gender = gender;
}
public Department getDepartment() {
return department;
}
public void setDepartment(Department department) {
this.department = department;
}
@Override
public String toString() {
return "Employee{" +
"id=" + id +
", lastname='" + lastname + '\'' +
", email='" + email + '\'' +
", gender=" + gender +
", department=" + department +
", birth=" + birth +
", sarly=" + sarly +
'}';
}
}
并在處理的方法中的入?yún)⒅袑σr灥膶嶓w類標注@Valid,如果需要使用到BindingResult等類的話要注意要和@Valid標注的實體類成對存在:
@RequestMapping(value = "/emp",method = RequestMethod.POST)
public String save(@Valid Employee employee, BindingResult result,Map<String,Object> map){
System.out.println("save:"+employee);
/**
* 如果轉(zhuǎn)換出錯
*/
if (result.getErrorCount() > 0){
System.out.println("出錯了:");
for (FieldError error : result.getFieldErrors()){
System.out.println(error.getField() + ":" + error.getDefaultMessage());
}
map.put("departments",departmentDao.getDepartments());
//若驗證出錯,則轉(zhuǎn)向定制的頁面
return "input";
}
employeeDao.save(employee);
return "redirect:/emps";
}
如果輸入錯誤,則輸出結果如下:

在頁面上顯示錯誤
在JSP頁面上通過<form:errors path="屬性名" />顯示錯誤消息
<form:errors path="lastname"/><br>
如果要一次性顯示所有錯誤消息,可以將path寫為*,即:
<form:errors path="*"/><br>
提示消息的國際化
每個屬性在數(shù)據(jù)綁定和數(shù)據(jù)校驗發(fā)生錯誤時,都會生成一個對應的FieldError對象。當一個屬性校驗失敗后,校驗框架會為該屬性生成4個消息代碼,這些代碼以校驗注解類名為前綴,結合modleAttribute、屬性名及屬性類型名生成多個對應的消息代碼。
例如User類中的password屬性標注了一個@Pattern注解,當該屬性值不滿足@Pattern所定義的規(guī)則時,就會產(chǎn)生以下4個錯誤代碼:
- Pattern.user.password
- Pattern.password
- Pattern.java.lang.String
- Pattern
當使用SpringMVC標簽顯示錯誤消息時,SpringMVC會查看WEB上下文是否裝配了對應的國際化消息,如果沒有,則顯示默認的錯誤消息,否則使用國際化消息。
定制提示消息的話,我們要先定義一個國際化資源文件,例如i18n.properties文件,并且寫入需要定制化的消息:
NotNull.employee.lastname=lastname\u4e0d\u80fd\u4e3a\u7a7a
Email.employee.email=Email\u4e0d\u5408\u6cd5
Past.employee.birth=Birth\u4e0d\u80fd\u662f\u4e00\u4e2a\u5c06\u6765\u7684\u65f6\u95f4