# SpringMVC數據驗證——第七章 注解式控制器的數據驗證、類型轉換及格式化——跟著開濤學SpringMVC
## 7.4、數據驗證
### 7.4.1、編程式數據驗證
Spring 2.x提供了編程式驗證支持,詳見【4.16.2 數據驗證】章節,在此我們重寫【4.16.2.4.1、編程式驗證器】一節示例。
**(1、驗證器實現**
復制cn.javass.chapter4.web.controller.support.validator.UserModelValidator
到cn.javass.chapter7.web.controller.support.validator.UserModelValidator。
**(2、控制器實現**
```
@Controller
public class RegisterSimpleFormController {
private UserModelValidator validator = new UserModelValidator();
@ModelAttribute("user") //① 暴露表單引用對象為模型數據
public UserModel getUser() {
return new UserModel();
}
@RequestMapping(value = "/validator", method = RequestMethod.GET)
public String showRegisterForm() { //② 表單展示
return "validate/registerAndValidator";
}
@RequestMapping(value = "/validator", method = RequestMethod.POST)
public String submitForm(
@ModelAttribute("user") UserModel user,
Errors errors) { //③ 表單提交
validator.validate(user, errors); //1 調用UserModelValidator的validate方法進行驗證
if(errors.hasErrors()) { //2如果有錯誤再回到表單展示頁面
return showRegisterForm();
}
return "redirect:/success";
}
}?
```
在submitForm方法中,我們首先調用之前寫的UserModelValidator的validate方法進行驗證,當然此處可以直接驗證并通過Errors接口來保留錯誤;此處還通過 Errors接口的hasErrors方法來決定當驗證失敗時顯示的錯誤頁面。
**(3、spring配置文件chapter7-servlet.xml**
```
<bean class="cn.javass.chapter7.web.controller.RegisterSimpleFormController"/>?
```
**(4、錯誤碼配置(messages.properties),需要執行NativeToAscii**
直接將【springmvc-chapter4】項目中src下的messages.properties復制到src目錄下。
在spring配置文件`chapter7-servlet.xml中添加`messageSource:
```
<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="classpath:messages"/>
<property name="fileEncodings" value="utf-8"/>
<property name="cacheSeconds" value="120"/>
</bean>?
```
**(5、視圖頁面(/WEB-INF/jsp/registerAndValidator.jsp)**
直接將【springmvc-chapter4】項目中的/WEB-INF/jsp/registerAndValidator.jsp復制到當前項目下的/WEB-INF/jsp/validate/registerAndValidator.jsp。
**(6、啟動服務器測試:**
在瀏覽器地址欄輸入http://localhost:9080/springmvc-chapter7/validator進行測試,測試步驟和【4.16.2.4.1、編程式驗證器】一樣。
其他編程式驗證的使用,請參考【4.16.2 數據驗證】章節。
### 7.4.2、聲明式數據驗證
Spring3開始支持JSR-303驗證框架,JSR-303支持XML風格的和注解風格的驗證,接下來我們首先看一下如何和Spring集成。
7.4.2.1、集成
**(1、添加jar包:**
此處使用Hibernate-validator實現(版本:hibernate-validator-4.3.0.Final-dist.zip),將如下jar包添加到classpath(WEB-INF/lib下即可):
寫道dist/lib/required/validation-api-1.0.0.GA.jar JSR-303規范API包
dist/hibernate-validator-4.3.0.Final.jar Hibernate 參考實現
**(2、在Spring配置總添加對JSR-303驗證框架的支持**???
```
<!-- 以下 validator ConversionService 在使用 mvc:annotation-driven 會 自動注冊-->
<bean id="validator"
class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
<property name="providerClass" value="org.hibernate.validator.HibernateValidator"/>
<!-- 如果不加默認到 使用classpath下的 ValidationMessages.properties -->
<property name="validationMessageSource" ref="messageSource"/>
</bean>?
```
此處使用Hibernate validator實現:
validationMessageSource屬性:指定國際化錯誤消息從哪里取,此處使用之前定義的messageSource來獲取國際化消息;如果此處不指定該屬性,則默認到classpath下的ValidationMessages.properties取國際化錯誤消息。
通過ConfigurableWebBindingInitializer注冊validator:
```
<bean id="webBindingInitializer"
class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
<property name="conversionService" ref="conversionService"/>
<property name="validator" ref="validator"/>
</bean>?
```
其他配置和之前學習7.2.2.4一節一樣。
如上集成過程看起來比較麻煩,后邊我們會介紹<mvc:annotation-driven>和@EnableWebMvc,ConversionService會自動注冊,后續章節再詳細介紹。
**(3、使用JSR-303驗證框架注解為模型對象指定驗證信息**
```
package cn.javass.chapter7.model;
import javax.validation.constraints.NotNull;
public class UserModel {
@NotNull(message="{username.not.empty}")
private String username;
}?
```
通過@NotNull指定此username字段不允許為空,當驗證失敗時將從之前指定的messageSource中獲取“username.not.empty”對于的錯誤信息,此處只有通過“{錯誤消息鍵值}”格式指定的才能從messageSource獲取。
**(4、控制器**
```
package cn.javass.chapter7.web.controller.validate;
//省略import
@Controller
public class HelloWorldController {
@RequestMapping("/validate/hello")
public String validate(@Valid @ModelAttribute("user") UserModel user, Errors errors) {
if(errors.hasErrors()) {
return "validate/error";
}
return "redirect:/success";
}
}?
```
通過在命令對象上注解@Valid來告訴Spring MVC此命令對象在綁定完畢后需要進行JSR-303驗證,如果驗證失敗會將錯誤信息添加到errors錯誤對象中。
**(5、驗證失敗后需要展示的頁面(/WEB-INF/jsp/validate/error.jsp)**
```
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<form:form commandName="user">
<form:errors path="*" cssStyle="color:red"></form:errors><br/>
</form:form>?
```
**(6、測試**
在瀏覽器地址欄中輸入[http://localhost:9080/springmvc-chapter7/validate/hello](http://localhost:9080/springmvc-chapter7/validate/hello),即沒有username數據,請求后將直接到驗證失敗界面并顯示錯誤消息“用戶名不能為空”,如果請求時帶上“?username=zhang”將重定向到成功頁面。
到此集成就完成,接下來我們詳細學習下有哪些驗證約束注解吧。
### 7.4.2.2、內置的驗證約束注解
內置的驗證約束注解如下表所示(摘自hibernate validator reference):
| **驗證注解** | **驗證的數據類型** | **說明** |
| --- | --- | --- |
| @AssertFalse | Boolean,boolean | 驗證注解的元素值是false |
| @AssertTrue | Boolean,boolean | 驗證注解的元素值是true |
| @NotNull | 任意類型 | 驗證注解的元素值不是null |
| @Null | 任意類型 | 驗證注解的元素值是null |
| @Min(value=值) | BigDecimal,BigInteger, byte,short, int, long,等任何Number或CharSequence(存儲的是數字)子類型 | 驗證注解的元素值大于等于@Min指定的value值 |
| @Max(value=值) | 和@Min要求一樣 | 驗證注解的元素值小于等于@Max指定的value值 |
| @DecimalMin(value=值) | 和@Min要求一樣 | 驗證注解的元素值大于等于@ DecimalMin指定的value值 |
| @DecimalMax(value=值) | 和@Min要求一樣 | 驗證注解的元素值小于等于@ DecimalMax指定的value值 |
| @Digits(integer=整數位數, fraction=小數位數) | 和@Min要求一樣 | 驗證注解的元素值的整數位數和小數位數上限 |
| @Size(min=下限, max=上限) | 字符串、Collection、Map、數組等 | 驗證注解的元素值的在min和max(包含)指定區間之內,如字符長度、集合大小 |
| @Past | java.util.Date,java.util.Calendar;Joda Time類庫的日期類型 | 驗證注解的元素值(日期類型)比當前時間早 |
| @Future | 與@Past要求一樣 | 驗證注解的元素值(日期類型)比當前時間晚 |
| @NotBlank | CharSequence子類型 | 驗證注解的元素值不為空(不為null、去除首位空格后長度為0),不同于@NotEmpty,@NotBlank只應用于字符串且在比較時會去除字符串的首位空格 |
| @Length(min=下限, max=上限) | CharSequence子類型 | 驗證注解的元素值長度在min和max區間內 |
| @NotEmpty | CharSequence子類型、Collection、Map、數組 | 驗證注解的元素值不為null且不為空(字符串長度不為0、集合大小不為0) |
| @Range(min=最小值, max=最大值) | BigDecimal,BigInteger,CharSequence, byte, short, int, long等原子類型和包裝類型 | 驗證注解的元素值在最小值和最大值之間 |
| @Email(regexp=正則表達式,flag=標志的模式) | CharSequence子類型(如String) | 驗證注解的元素值是Email,也可以通過regexp和flag指定自定義的email格式 |
| @Pattern(regexp=正則表達式,flag=標志的模式) | String,任何CharSequence的子類型 | 驗證注解的元素值與指定的正則表達式匹配 |
| @Valid | 任何非原子類型 | 指定遞歸驗證關聯的對象;如用戶對象中有個地址對象屬性,如果想在驗證用戶對象時一起驗證地址對象的話,在地址對象上加@Valid注解即可級聯驗證 |
此處只列出Hibernate Validator提供的大部分驗證約束注解,請參考hibernate validator官方文檔了解其他驗證約束注解和進行自定義的驗證約束注解定義。
具體演示實例請參考cn.javass.chapter7.web.controller.validate.ValidatorAnnotationTestController。
### 7.4.2.3、錯誤消息
當驗證出錯時,我們需要給用戶展示錯誤消息告訴用戶出錯的原因,因此我們要為驗證約束注解指定錯誤消息。錯誤消息是通過在驗證約束注解的message屬性指定。驗證約束注解指定錯誤消息有如下兩種方式:
1、硬編碼錯誤消息;
2、從資源消息文件中根據消息鍵讀取錯誤消息。
**一、硬編碼錯誤消息**
直接在驗證約束注解上指定錯誤消息,如下所示:
```
@NotNull(message = "用戶名不能為空")
@Length(min=5, max=20, message="用戶名長度必須在5-20之間")
@Pattern(regexp = "^[a-zA-Z_]\\w{4,19}$", message = "用戶名必須以字母下劃線開頭,可由字母數字下劃線組成")
private String username;?
```
如上所示,錯誤消息使用硬編碼指定,這種方式是不推薦使用的,因為在如下場景是不適用的:
1、在國際化場景下,需要對不同的國家顯示不同的錯誤消息;
2、需要更換錯誤消息時是比較麻煩的,需要找到相應的類進行更換,并重新編譯發布。
**二、從資源消息文件中根據消息鍵讀取錯誤消息**
**2.1、默認的錯誤消息文件及默認錯誤消息鍵值**
默認的錯誤消息文件是/org/hibernate/validator/ValidationMessages.properties,如下圖所示:

默認的錯誤消息鍵值如下圖所示:

消息鍵默認為:驗證約束注解的全限定類名.message
在我們之前的測試文件中,錯誤消息鍵值是使用默認的,如何自定義錯誤消息文件和錯誤消息鍵值呢?
**2.2、自定義的錯誤消息文件和錯誤消息鍵值**
自定義的錯誤消息文件里的錯誤消息鍵值將覆蓋默認的錯誤消息文件中的錯誤消息鍵值。我們自定義的錯誤消息文件是具有國際化功能的。
**(1、定義錯誤消息文件**
在類裝載路徑的根下創建ValidationMessages.properties文件,如在src目錄下創建會自動復制到類裝載路徑的根下,并添加如下消息鍵值(需要native2ascii,可以在eclipse里裝Properties?Editor,自動保存為ASCII碼):
```
javax.validation.constraints.Pattern.message=用戶名必須以字母或下劃線開頭,后邊可以跟字母數字下劃線,長度在5-20之間
```
需要在你的spring配置文件WEB-INF/chapter7-servlet.xml修改之前的validator Bean:
```
<bean id="validator"
class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
<property name="providerClass"
value="org.hibernate.validator.HibernateValidator"/>
</bean>?
```
此時錯誤消息鍵值的查找會先到classpath下ValidationMessages.properties中找,找不到再到默認的錯誤消息文件中找。
輸入測試地址:http://localhost:9080/springmvc-chapter7/validate/pattern?value=zhan,將看到我們自定義的錯誤消息顯示出來了。
**(2、使用Spring的MessageSource Bean進行消息鍵值的查找**
如果我們的環境是與spring集成,還是應該使用Spring提供的消息支持,具體配置如下:
在spring配置文件WEB-INF/chapter7-servlet.xml定義MessageSource Bean:
```
<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="classpath:messages"/>
<property name="fileEncodings" value="utf-8"/>
<property name="cacheSeconds" value="120"/>
</bean>?
```
之前我們已經配置過了,在此就不詳述了。
在spring配置文件WEB-INF/chapter7-servlet.xml定義的validator Bean,添加如下屬性:
```
<property name="validationMessageSource" ref="messageSource"/>
```
驗證失敗的錯誤消息鍵值的查找將使用messageSource Bean進行。
在消息文件src/messages.properties中添加如下錯誤消息:
```
javax.validation.constraints.Pattern.message=用戶名必須以字母或下劃線開頭,后邊可以跟字母數字下劃線,長度在5-20之間
```
輸入測試地址:http://localhost:9080/springmvc-chapter7/validate/pattern?value=zhan,將看到我們自定義的錯誤消息顯示出來了。
**當我們配置了messageSource Bean時,默認將為驗證的對象自動生成如下錯誤消息鍵:**
驗證錯誤注解簡單類名.驗證對象名.字段名
驗證錯誤注解簡單類名.字段名
驗證錯誤注解簡單類名.字段類型全限定類名
驗證錯誤注解簡單類名
使用的優先級是:從高到低,即最前邊的具有最高的優先級,而且以上所有默認的錯誤消息鍵優先級高于自定義的錯誤消息鍵。
如測試用例cn.javass.chapter7.web.controller.validate.ValidatorAnnotationTestController中的public String pattern(@Valid @ModelAttribute("model") PatternModel model, Errors errors)將自動產生如下錯誤消息鍵:
Pattern.model.value=驗證錯誤注解簡單類名.驗證對象名.字段名
Pattern.value=驗證錯誤注解簡單類名.字段名
Pattern.java.lang.String=驗證錯誤注解簡單類名.字段類型全限定類名
Pattern=驗證錯誤注解簡單類名
**(3、自定義錯誤消息鍵值**
之前我們已經學習了硬編碼錯誤消息,及默認的錯誤消息,在大部分場景下,以上兩種方式無法滿足我們的需求,因此我們需要自定義錯誤消息鍵值。
在驗證約束注解上指定錯誤消息鍵:
```
package cn.javass.chapter7.web.controller.validate.model;
public class PatternModel {
@Pattern(regexp = "^[a-zA-Z_][\\w]{4,19}$", message="{user.name.error}")
private String value;
}?
```
我們可以通過驗證約束注解的message屬性指定錯誤消息鍵,格式如“{消息鍵}”。
在消息文件src/messages.properties中添加如下錯誤消息:
```
user.name.error=用戶名格式不合法
```
輸入測試地址:http://localhost:9080/springmvc-chapter7/validate/pattern?value=zhan,將看到我們自定義的錯誤消息顯示出來了。
接下來我們看下如下場景
```
@Length(min=5, max=20, message="{user.name.length.error}")
```
```
user.name.error=用戶名長度必須在5-20之間
```
錯誤消息中的5-20應該是從@Length驗證約束注解中獲取的,而不是在錯誤消息中硬編碼,因此我們需要占位符的支持:
●如@Length(min=5, max=20, message="{user.name.length.error}"),錯誤消息可以這樣寫:用戶名長度必須在{min}-{max}之間
**錯誤消息占位符規則:**
{驗證注解屬性名},如@Length有min和max屬性,則在錯誤消息文件中可以通過{min}和{max}來獲取;如@Max有value屬性,則在錯誤消息文件中可以通過{value}來獲取。
```
user.name.length.error=用戶名長度必須在{min}-{max}之間
```
輸入測試地址:http://localhost:9080/springmvc-chapter7/validate/length?value=1,將看到我們自定義的錯誤消息顯示出來了。
### 7.4.2.4、功能處理方法上多個驗證參數的處理
當我們在一個功能處理方法上需要驗證多個模型對象時,需要通過如下形式來獲取驗證結果:
```
@RequestMapping("/validate/multi")
public String multi(
@Valid @ModelAttribute("a") A a, BindingResult aErrors,
@Valid @ModelAttribute("b") B b, BindingResult bErrors) {
if(aErrors.hasErrors()) { //如果a模型對象驗證失敗
return "validate/error";
}
if(bErrors.hasErrors()) { //如果a模型對象驗證失敗
return "validate/error";
}
return "redirect:/success";
}?
```
每一個模型對象后邊都需要跟一個Errors或BindingResult對象來保存驗證結果,其方法體內部可以使用這兩個驗證結果對象來選擇出錯時跳轉的頁面。詳見cn.javass.chapter7.web.controller.validate.MultiModelController。
在錯誤頁面,需要針對不同的模型來顯示錯誤消息:
```
<form:form commandName="a">
<form:errors path="*" cssStyle="color:red"></form:errors><br/>
</form:form>
<form:form commandName="b">
<form:errors path="*" cssStyle="color:red"></form:errors><br/>
</form:form>?
```
- 跟我學 Spring3
- 【第二章】 IoC 之 2.1 IoC基礎 ——跟我學Spring3
- 【第二章】 IoC 之 2.2 IoC 容器基本原理 ——跟我學Spring3
- 【第二章】 IoC 之 2.3 IoC的配置使用——跟我學Spring3
- 【第三章】 DI 之 3.1 DI的配置使用 ——跟我學spring3
- 【第三章】 DI 之 3.2 循環依賴 ——跟我學spring3
- 【第三章】 DI 之 3.3 更多DI的知識 ——跟我學spring3
- 【第三章】 DI 之 3.4 Bean的作用域 ——跟我學spring3
- 【第四章】 資源 之 4.1 基礎知識 ——跟我學spring3
- 【第四章】 資源 之 4.2 內置Resource實現 ——跟我學spring3
- 【第四章】 資源 之 4.3 訪問Resource ——跟我學spring3
- 【第四章】 資源 之 4.4 Resource通配符路徑 ——跟我學spring3
- 【第五章】Spring表達式語言 之 5.1 概述 5.2 SpEL基礎 ——跟我學spring3
- 【第五章】Spring表達式語言 之 5.3 SpEL語法 ——跟我學spring3
- 【第五章】Spring表達式語言 之 5.4在Bean定義中使用EL—跟我學spring3
- 【第六章】 AOP 之 6.1 AOP基礎 ——跟我學spring3
- 【第六章】 AOP 之 6.2 AOP的HelloWorld ——跟我學spring3
- 【第六章】 AOP 之 6.3 基于Schema的AOP ——跟我學spring3
- 【第六章】 AOP 之 6.4 基于@AspectJ的AOP ——跟我學spring3
- 【第六章】 AOP 之 6.5 AspectJ切入點語法詳解 ——跟我學spring3
- 【第六章】 AOP 之 6.6 通知參數 ——跟我學spring3
- 【第六章】 AOP 之 6.7 通知順序 ——跟我學spring3
- 【第六章】 AOP 之 6.8 切面實例化模型 ——跟我學spring3
- 【第六章】 AOP 之 6.9 代理機制 ——跟我學spring3
- 【第七章】 對JDBC的支持 之 7.1 概述 ——跟我學spring3
- 【第七章】 對JDBC的支持 之 7.2 JDBC模板類 ——跟我學spring3
- 【第七章】 對JDBC的支持 之 7.3 關系數據庫操作對象化 ——跟我學spring3
- 【第七章】 對JDBC的支持 之 7.4 Spring提供的其它幫助 ——跟我學spring3【私塾在線原創】
- 【第七章】 對JDBC的支持 之 7.5 集成Spring JDBC及最佳實踐 ——跟我學spring3
- 【第八章】 對ORM的支持 之 8.1 概述 ——跟我學spring3
- 【第八章】 對ORM的支持 之 8.2 集成Hibernate3 ——跟我學spring3
- 【第八章】 對ORM的支持 之 8.3 集成iBATIS ——跟我學spring3
- 【第八章】 對ORM的支持 之 8.4 集成JPA ——跟我學spring3
- 【第九章】 Spring的事務 之 9.1 數據庫事務概述 ——跟我學spring3
- 【第九章】 Spring的事務 之 9.2 事務管理器 ——跟我學spring3
- 【第九章】 Spring的事務 之 9.3 編程式事務 ——跟我學spring3
- 【第九章】 Spring的事務 之 9.4 聲明式事務 ——跟我學spring3
- 【第十章】集成其它Web框架 之 10.1 概述 ——跟我學spring3
- 【第十章】集成其它Web框架 之 10.2 集成Struts1.x ——跟我學spring3
- 【第十章】集成其它Web框架 之 10.3 集成Struts2.x ——跟我學spring3
- 【第十章】集成其它Web框架 之 10.4 集成JSF ——跟我學spring3
- 【第十一章】 SSH集成開發積分商城 之 11.1 概述 ——跟我學spring3
- 【第十一章】 SSH集成開發積分商城 之 11.2 實現通用層 ——跟我學spring3
- 【第十一章】 SSH集成開發積分商城 之 11.3 實現積分商城層 ——跟我學spring3
- 【第十二章】零配置 之 12.1 概述 ——跟我學spring3
- 【第十二章】零配置 之 12.2 注解實現Bean依賴注入 ——跟我學spring3
- 【第十二章】零配置 之 12.3 注解實現Bean定義 ——跟我學spring3
- 【第十二章】零配置 之 12.4 基于Java類定義Bean配置元數據 ——跟我學spring3
- 【第十二章】零配置 之 12.5 綜合示例-積分商城 ——跟我學spring3
- 【第十三章】 測試 之 13.1 概述 13.2 單元測試 ——跟我學spring3
- 【第十三章】 測試 之 13.3 集成測試 ——跟我學spring3
- 跟我學 Spring MVC
- SpringMVC + spring3.1.1 + hibernate4.1.0 集成及常見問題總結
- Spring Web MVC中的頁面緩存支持 ——跟我學SpringMVC系列
- Spring3 Web MVC下的數據類型轉換(第一篇)——《跟我學Spring3 Web MVC》搶先看
- Spring3 Web MVC下的數據格式化(第二篇)——《跟我學Spring3 Web MVC》搶先看
- 第一章 Web MVC簡介 —— 跟開濤學SpringMVC
- 第二章 Spring MVC入門 —— 跟開濤學SpringMVC
- 第三章 DispatcherServlet詳解 ——跟開濤學SpringMVC
- 第四章 Controller接口控制器詳解(1)——跟著開濤學SpringMVC
- 第四章 Controller接口控制器詳解(2)——跟著開濤學SpringMVC
- 第四章 Controller接口控制器詳解(3)——跟著開濤學SpringMVC
- 第四章 Controller接口控制器詳解 (4)——跟著開濤學SpringMVC
- 第四章 Controller接口控制器詳解(5)——跟著開濤學SpringMVC
- 跟著開濤學SpringMVC 第一章源代碼下載
- 第二章 Spring MVC入門 源代碼下載
- 第四章 Controller接口控制器詳解 源代碼下載
- 第四章 Controller接口控制器詳解(6)——跟著開濤學SpringMVC
- 第四章 Controller接口控制器詳解(7 完)——跟著開濤學SpringMVC
- 第五章 處理器攔截器詳解——跟著開濤學SpringMVC
- 源代碼下載 第五章 處理器攔截器詳解——跟著開濤學SpringMVC
- 注解式控制器運行流程及處理器定義 第六章 注解式控制器詳解——跟著開濤學SpringMVC
- 源代碼下載 第六章 注解式控制器詳解
- SpringMVC3強大的請求映射規則詳解 第六章 注解式控制器詳解——跟著開濤學SpringMVC
- Spring MVC 3.1新特性 生產者、消費者請求限定 —— 第六章 注解式控制器詳解——跟著開濤學SpringMVC
- SpringMVC強大的數據綁定(1)——第六章 注解式控制器詳解——跟著開濤學SpringMVC
- SpringMVC強大的數據綁定(2)——第六章 注解式控制器詳解——跟著開濤學SpringMVC
- SpringMVC數據類型轉換——第七章 注解式控制器的數據驗證、類型轉換及格式化——跟著開濤學SpringMVC
- SpringMVC數據格式化——第七章 注解式控制器的數據驗證、類型轉換及格式化——跟著開濤學SpringMVC
- SpringMVC數據驗證——第七章 注解式控制器的數據驗證、類型轉換及格式化——跟著開濤學SpringMVC