# 第四章 Controller接口控制器詳解(7 完)——跟著開濤學SpringMVC
### 4.16.2、數據驗證
**1、數據綁定失敗:**比如需要數字卻輸入了字母;
**2、數據不合法:**可以認為是業務錯誤,通過自定義驗證器驗證,如用戶名長度必須在5-20之間,我們卻輸入了100個字符等;
**3、錯誤對象:**當我們數據綁定失敗或驗證失敗后,錯誤信息存放的對象,我們叫錯誤對象,在Spring Web MVC中Errors是具體的代表者;線程不安全對象;
**4、錯誤消息:**是硬編碼,還是可配置?實際工作應該使用配置方式,我們只是把錯誤碼(errorCode)放入錯誤對象,在展示時讀取相應的錯誤消息配置文件來獲取要顯示的錯誤消息(errorMessage);
4.16.2.1、驗證流程
?
1、首先進行數據綁定驗證,如果驗證失敗會通過MessageCodesResolver生成錯誤碼放入Errors錯誤對象;
2、數據不合法驗證,通過自定義的驗證器驗證,如果失敗需要手動將錯誤碼放入Errors錯誤對象;
4.16.2.2、錯誤對象和錯誤消息
錯誤對象的代表者是Errors接口,并且提供了幾個實現者,在Spring Web MVC中我們使用的是如下實現:

**相關的錯誤方法如下:**
**Errors:**存儲和暴露關于數據綁定錯誤和驗證錯誤相關信息的接口,提供了相關存儲和獲取錯誤消息的方法:
```
package org.springframework.validation;
public interface Errors {
//=========================全局錯誤消息(驗證/綁定對象全局的)=============================
//注冊一個全局的錯誤碼()
void reject(String errorCode);
//注冊一個全局的錯誤碼,當根據errorCode沒有找到相應錯誤消息時,使用defaultMessage作為錯誤消息
void reject(String errorCode, String defaultMessage);
//注冊一個全局的錯誤碼,當根據errorCode沒有找到相應錯誤消息時(帶錯誤參數的),使用defaultMessage作為錯誤消息
void reject(String errorCode, Object[] errorArgs, String defaultMessage);
//=========================全局錯誤消息(驗證/綁定整個對象的)=============================
//=========================局部錯誤消息(驗證/綁定對象字段的)=============================
//注冊一個對象字段的錯誤碼,field指定驗證失敗的字段名
void rejectValue(String field, String errorCode);
void rejectValue(String field, String errorCode, String defaultMessage);
void rejectValue(String field, String errorCode, Object[] errorArgs, String defaultMessage);
//=========================局部錯誤消息(驗證/綁定對象字段的)=============================
boolean hasErrors(); ////是否有錯誤
boolean hasGlobalErrors(); //是否有全局錯誤
boolean hasFieldErrors(); //是否有字段錯誤
Object getFieldValue(String field); //返回當前驗證通過的值,或驗證失敗時失敗的值;
}
```
getFieldValue:可以得到驗證失敗的失敗值,這是其他Web層框架很少支持的,這樣就可以給用戶展示出錯時的值(而不是空或其他的默認值等)。
**BindingResult:**代表數據綁定的結果,繼承了Errors接口。
**BindException:**代表數據綁定的異常,它繼承Exception,并實現了BindingResult,這是內部使用的錯誤對象。
**示例:**
**(1、控制器**
```
package cn.javass.chapter4.web.controller;
//省略import
public class ErrorController extends AbstractCommandController {
public ErrorController() {
setCommandClass(DataBinderTestModel.class);
setCommandName("command");
}
@Override
protected ModelAndView handle(HttpServletRequest req, HttpServletResponse resp, Object command, BindException errors) throws Exception {
//表示用戶名不為空
errors.reject("username.not.empty");
//帶有默認錯誤消息
errors.reject("username.not.empty1", "用戶名不能為空1");
//帶有參數和默認錯誤消息
errors.reject("username.length.error", new Object[]{5, 10});
//得到錯誤相關的模型數據
Map model = errors.getModel();
return new ModelAndView("bindAndValidate/error", model);
}
}
```
```
errors.reject("username.not.empty"):注冊全局錯誤碼“username.not.empty”,我們必須提供messageSource來提供錯誤碼“username.not.empty”對應的錯誤信息(如果沒有會拋出NoSuchMessageException異常);
```
**errors.reject("username.not.empty1", "用戶名不能為空1"):**注冊全局錯誤碼“username.not.empty1”,如果從messageSource沒沒有找到錯誤碼“username.not.empty1”對應的錯誤信息,則將顯示默認消息“用戶名不能為空1”;
**errors.reject("username.length.error", new Object[]{5, 10}):**錯誤碼為“username.length.error”,而且錯誤信息需要兩個參數,如我們在我們的配置文件中定義“用戶名長度不合法,長度必須在{0}到{1}之間”,則實際的錯誤消息為“用戶名長度不合法,長度必須在5到10之間”
**errors.getModel():**當有錯誤信息時,一定將errors.getModel()放入我們要返回的ModelAndView中,以便使用里邊的錯誤對象來顯示錯誤信息。
`**(2、spring配置文件chapter4-servlet.xml**`
```
<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>
<bean name="/error" class="cn.javass.chapter4.web.controller.ErrorController"/>
```
**messageSource:**用于獲取錯誤碼對應的錯誤消息的,而且bean名字默認必須是messageSource。
messages.properties(需要執行NativeToAscii)
```
username.not.empty=用戶名不能為空
username.length.error=用戶名長度不合法,長度必須在{0}到{1}之間
```
**(3、視圖頁面(WEB-INF/jsp/bindAndValidate/error.jsp)**
```
<%@taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<!-- 表單的默認命令對象名為command -->
<form:form commandName="command">
<form:errors path="*"></form:errors>
</form:form>
```
**form標簽庫:**此處我們使用了spring的form標簽庫;
**<form:form commandName="command">:**表示我們的表單標簽,commandName表示綁定的命令對象名字,默認為command;
**<form:errors path="*"></form:errors>:**表示顯示錯誤信息的標簽,如果path為“*”表示顯示所有錯誤信息。
接下來我們來看一下 數據綁定失敗和數據不合法時,如何處理。
4.16.2.3、數據綁定失敗
如我們的DataBinderTestModel類:
bool:boolean類型,此時如果我們前臺傳入非兼容的數據,則會數據綁定失敗;
date:Date類型,此時如果我們前臺傳入非兼容的數據,同樣會數據綁定失敗;
phoneNumber:自定義的PhoneNumberModel類型,如果如果我們前臺傳入非兼容的數據,同樣會數據綁定失敗。
**示例:**
**(1、控制器,DataBinderErrorTestController。**
```
package cn.javass.chapter4.web.controller;
//省略import
public class DataBinderErrorTestController extends SimpleFormController {
public DataBinderErrorTestController() {
setCommandClass(DataBinderTestModel.class);
setCommandName("dataBinderTest");
}
@Override
protected ModelAndView showForm(HttpServletRequest request, HttpServletResponse response, BindException errors) throws Exception {
//如果表單提交有任何錯誤都會再回到表單展示頁面
System.out.println(errors);
return super.showForm(request, response, errors);
}
@Override
protected void doSubmitAction(Object command) throws Exception {
System.out.println(command); //表單提交成功(數據綁定成功)進行功能處理
}
@Override
protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception {
super.initBinder(request, binder);
//注冊自定義的屬性編輯器
//1、日期
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
CustomDateEditor dateEditor = new CustomDateEditor(df, true);
//表示如果命令對象有Date類型的屬性,將使用該屬性編輯器進行類型轉換
binder.registerCustomEditor(Date.class, dateEditor);
//自定義的電話號碼編輯器
binder.registerCustomEditor(PhoneNumberModel.class, new PhoneNumberEditor());
}
}
```
此處我們使用SimpleFormController;
**showForm:**展示表單,當提交表單有任何數據綁定錯誤會再回到該方法進行表單輸入(在此處我們打印錯誤對象);
**doSubmitAction:**表單提交成功,只要當表單的數據到命令對象綁定成功時,才會執行;
`**(2、spring配置文件chapter4-servlet.xml**`
```
<bean name="/dataBindError"
class="cn.javass.chapter4.web.controller.DataBinderErrorTestController">
<property name="formView" value="bindAndValidate/input"/>
<property name="successView" value="bindAndValidate/success"/>
</bean>
```
**(3、視圖頁面(WEB-INF/jsp/bindAndValidate/**?**input.jsp)**
```
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<!-- 表單的命令對象名為dataBinderTest -->
<form:form commandName="dataBinderTest">
<form:errors path="*" cssStyle="color:red"></form:errors><br/><br/>
bool:<form:input path="bool"/><br/>
phoneNumber:<form:input path="phoneNumber"/><br/>
date:<form:input path="date"/><br/>
<input type="submit" value="提交"/>
</form:form>
```
此處一定要使用form標簽庫,借此我們可以看到它的強大支持(別的大部分Web框架所不具備的,展示用戶驗證失敗的數據)。
<form:form commandName=_"dataBinderTest"_>:指定命令對象為dataBinderTest,默認command;
<form:errors path=_"*"_?cssStyle=_"color:red"_></form:errors>:顯示錯誤消息,當提交表單有錯誤時展示錯誤消息(數據綁定錯誤/數據不合法);
<form:input path=_"bool"_/>:等價于(<input type=’text’>),但會從命令對象中取出bool屬性進行填充value屬性,或如果表單提交有錯誤會從錯誤對象取出之前的錯誤數據(而非空或默認值);
<input type=_"submit"_?value=_"__提交__"_/>:spring沒有提供相應的提交按鈕,因此需要使用html的。
**(4、測試**
在地址欄輸入如下地址:http://localhost:9080/springmvc-chapter4/dataBindError

全部是錯誤數據,即不能綁定到我們的命令對象;
當提交表單后,我們又回到表單輸入頁面,而且輸出了一堆錯誤信息

1、錯誤消息不可讀;
2、表單元素可以顯示之前的錯誤的數據,而不是默認值/空;
**(5、問題**
**這里最大的問題是不可讀的錯誤消息,如何讓這些錯誤消息可讀呢?**
首先我們看我們的showForm方法里輸出的“errors”錯誤對象信息:
```
org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 3 errors
Field error in object 'dataBinderTest' on field 'bool': rejected value [www]; codes [typeMismatch.dataBinderTest.bool,typeMismatch.bool,typeMismatch.boolean,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [dataBinderTest.bool,bool]; arguments []; default message [bool]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'boolean' for property 'bool'; nested exception is java.lang.IllegalArgumentException: Invalid boolean value [www]]
Field error in object 'dataBinderTest' on field 'date': rejected value [123]; codes [typeMismatch.dataBinderTest.date,typeMismatch.date,typeMismatch.java.util.Date,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [dataBinderTest.date,date]; arguments []; default message [date]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.util.Date' for property 'date'; nested exception is java.lang.IllegalArgumentException: Could not parse date: Unparseable date: "123"]
Field error in object 'dataBinderTest' on field 'phoneNumber': rejected value [123]; codes [typeMismatch.dataBinderTest.phoneNumber,typeMismatch.phoneNumber,typeMismatch.cn.javass.chapter4.model.PhoneNumberModel,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [dataBinderTest.phoneNumber,phoneNumber]; arguments []; default message [phoneNumber]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'cn.javass.chapter4.model.PhoneNumberModel' for property 'phoneNumber'; nested exception is java.lang.IllegalArgumentException: 類型轉換失敗,需要格式[010-12345678],但格式是[123]]
```
數據綁定失敗(類型不匹配)會自動生成如下錯誤碼(錯誤碼對應的錯誤消息按照如下順序依次查找):
1、typeMismatch.命令對象名.屬性名
2、typeMismatch.屬性名
3、typeMismatch.屬性全限定類名(包名.類名)
4、typeMismatch
⊙內部使用MessageCodesResolver解析數據綁定錯誤到錯誤碼,默認DefaultMessageCodesResolver,因此想要詳細了解如何解析請看其javadoc;
⊙建議使用第1個進行錯誤碼的配置。
因此修改我們的messages.properties添加如下錯誤消息(需要執行NativeToAscii):
```
typeMismatch.dataBinderTest.date=您輸入的數據格式錯誤,請重新輸入(格式:2012-03-19 22:17:17)
#typeMismatch.date=2
#typeMismatch.java.util.Date=3
#typeMismatch=4
```
再次提交表單我們會看到我們設置的錯誤消息:

到此,數據綁定錯誤我們介紹完了,接下來我們再看一下數據不合法錯誤。
4.16.2.4、數據不合法
1、比如用戶名長度必須在5-20之間,而且必須以字母開頭,可包含字母、數字、下劃線;
2、比如注冊用戶時 用戶名已經存在或郵箱已經存在等;
3、比如去一些論壇經常會發現,您發的帖子中包含×××屏蔽關鍵字等。
還有很多數據不合法的場景,在此就不羅列了,對于數據不合法,Spring Web MVC提供了兩種驗證方式:
◆編程式驗證器驗證
◆聲明式驗證
先從編程式驗證器開始吧。
4.16.2.4.1、編程式驗證器
**一、驗證器接口**
```
package org.springframework.validation;
public interface Validator {
boolean supports(Class<?> clazz);
void validate(Object target, Errors errors);
}
```
**Validator接口:**驗證器,編程實現數據驗證的接口;
**supports方法:**當前驗證器是否支持指定的clazz驗證,如果支持返回true即可;
**validate方法:**驗證的具體方法,target參數表示要驗證的目標對象(如命令對象),errors表示驗證出錯后存放錯誤信息的錯誤對象。
**示例:**
**(1、驗證器實現**
```
package cn.javass.chapter4.web.controller.support.validator;
//省略import
public class UserModelValidator implements Validator {
private static final Pattern USERNAME_PATTERN = Pattern.compile("[a-zA-Z]\\w{4,19}");
private static final Pattern PASSWORD_PATTERN = Pattern.compile("[a-zA-Z0-9]{5,20}");
private static final Set<String> FORBINDDDEN_WORD_SET = new HashSet<String>();
static {
FORBINDDDEN_WORD_SET.add("fuc k"); //刪掉空格
FORBINDDDEN_WORD_SET.add("admin");
}
@Override
public boolean supports(Class<?> clazz) {
return UserModel.class == clazz;//表示只對UserModel類型的目標對象實施驗證
}
@Override
public void validate(Object target, Errors errors) {
//這個表示如果目標對象的username屬性為空,則表示錯誤(簡化我們手工判斷是否為空)
ValidationUtils.rejectIfEmpty(errors, "username", "username.not.empty");
UserModel user = (UserModel) target;
if(!USERNAME_PATTERN.matcher(user.getUsername()).matches()) {
errors.rejectValue("username", "username.not.illegal");//如果用戶名不合法
}
for(String forbiddenWord : FORBINDDDEN_WORD_SET) {
if(user.getUsername().contains(forbiddenWord)) {
errors.rejectValue("username", "username.forbidden", new Object[]{forbiddenWord}, "您的用戶名包含非法關鍵詞");//用戶名包含屏蔽關鍵字
break;
}
}
if(!PASSWORD_PATTERN.matcher(user.getPassword()).matches()) {
errors.rejectValue("password","password.not.illegal", "密碼不合法");//密碼不合法
}
}
}
```
**supports方法:**表示只對UserModel類型的對象驗證;
**validate方法:**數據驗證的具體方法,有如下幾個驗證:
1、用戶名不合法(長度5-20,以字母開頭,隨后可以是字母、數字、下劃線)
_USERNAME_PATTERN_.matcher(user.getUsername()).matches() //使用正則表達式驗證
errors.rejectValue("username", "username.not.illegal");//驗證失敗為username字段添加錯誤碼
2、屏蔽關鍵詞:即用戶名中含有不合法的數據(如admin)
user.getUsername().contains(forbiddenWord) //用contains來判斷我們的用戶名中是否含有非法關鍵詞
errors.rejectValue("username", "username.forbidden",?**new**?Object[]{forbiddenWord}, "您的用戶名包含非法關鍵詞");//驗證失敗為username字段添加錯誤碼(參數為當前屏蔽關鍵詞)(默認消息為"您的用戶名包含非法關鍵詞")
3、密碼不合法
在此就不羅列代碼了;
4、ValidationUtils
ValidationUtils._rejectIfEmpty_(errors, "username", "username.not.empty");
表示如果目標對象的username屬性數據為空,則添加它的錯誤碼;
內部通過(value == null || !StringUtils.hasLength(value.toString()))實現判斷value是否為空,從而簡化代碼。
`**(2、spring配置文件chapter4-servlet.xml**`
```
<bean id="userModelValidator"
class="cn.javass.chapter4.web.controller.support.validator.UserModelValidator"/>
<bean name="/validator"
class="cn.javass.chapter4.web.controller.RegisterSimpleFormController">
<property name="formView" value="registerAndValidator"/>
<property name="successView" value="redirect:/success"/>
<property name="validator" ref="userModelValidator"/>
</bean>
```
此處使用了我們第4.9節創建的RegisterSimpleFormController。
**(3、錯誤碼配置(messages.properties),需要執行NativeToAscii**
```
username.not.empty=用戶名不能為空
username.not.illegal=用戶名錯誤,必須以字母開頭,只能出現字母、數字、下劃線,并且長度在5-20之間
username.forbidden=用戶名中包含非法關鍵詞【{0}】
password.not.illegal=密碼長度必須在5-20之間
```
**(4、視圖頁面(/WEB-INF/jsp/registerAndValidator.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/>
username:<form:input path="username"/>
<form:errors path="username" cssStyle="color:red"></form:errors>
<br/>
password:<form:password path="password"/>
<form:errors path="password" cssStyle="color:red"></form:errors>
<br/>
<input type="submit" value="注冊"/>
</form:form>
```
form:errors path=_"username"__:_表示只顯示username字段的錯誤信息;
**(5、測試**
地址:http://localhost:9080/springmvc-chapter4/validator

當我們輸入錯誤的數據后,會報錯(form:errors path=_"*"_顯示所有錯誤信息,而form:errors path=_"username"_只顯示該字段相關的)。
**問題:**
如MultiActionController控制器相關方法沒有提供給我們errors對象(Errors),我們應該怎么進行錯誤處理呢?
此處給大家一個思路,errors本質就是一個Errors接口實現,而且在頁面要讀取相關的錯誤對象,該錯誤對象應該存放在模型對象里邊,因此我們可以自己創建個errors對象并將其添加到模型對象中即可。
此處我們復制4.15節的UserController類為UserAndValidatorController,并修改它的create(新增)方法添加如下代碼片段:
```
BindException errors = new BindException(user, getCommandName(user));
//如果用戶名為空
if(!StringUtils.hasLength(user.getUsername())) {
errors.rejectValue("username", "username.not.empty");
}
if(errors.hasErrors()) {
return new ModelAndView(getCreateView()).addAllObjects(errors.getModel());
}
```
**√?new?BindException(user, getCommandName(user)):**使用當前的命令對象,和命令對象的名字創建了一個BindException作為errors;
**√StringUtils._hasLength_(user.getUsername()):**如果用戶名為空就是用errors.rejectValue("username", "username.not.empty");注入錯誤碼;
**√errors.hasErrors():**表示如果有錯誤就返回到新增頁面并顯示錯誤消息;
**√ModelAndView(getCreateView()).addAllObjects(errors.getModel()):**此處一定把errors對象的模型數據放在當前的ModelAndView中,作為當前請求的模型數據返回。
在瀏覽器地址欄輸入:http://localhost:9080/springmvc-chapter4/userAndValidator/create 到新增頁面

用戶名什么都不輸入,提交后又返回到新增頁面 而且顯示了錯誤消息說明我們的想法是正確的。
4.16.2.4.2、聲明式驗證器
從Spring3開始支持JSR-303驗證框架,支持XML風格和注解風格的驗證,目前在@RequestMapping時才能使用,也就是說基于Controller接口的實現不能使用該方式(但可以使用編程式驗證,有需要的可以參考hibernate validator實現),我們將在第七章詳細介紹。
到此Spring2風格的控制器我們就介紹完了,以上控制器從spring3.0開始已經不推薦使用了(但考慮到還有部分公司使用這些@Deprecated類,在此也介紹了一下),而是使用注解控制器實現(@Controller和@RequestMapping)。
[
私塾在線學習網](http://sishuok.com/)原創內容([http://sishuok.com](http://sishuok.com/))
原創內容,轉載請注明私塾在線【[http://sishuok.com/forum/blogPost/list/5837.html](http://sishuok.com/forum/blogPost/list/5837.html)】
- 跟我學 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