# 【第九章】 Spring的事務 之 9.4 聲明式事務 ——跟我學spring3
## 9.4? 聲明式事務
### 9.4.1? 聲明式事務概述
從上節編程式實現事務管理可以深刻體會到編程式事務的痛苦,即使通過代理配置方式也是不小的工作量。
本節將介紹聲明式事務支持,使用該方式后最大的獲益是簡單,事務管理不再是令人痛苦的,而且此方式屬于無侵入式,對業務邏輯實現無影響。
接下來先來看看聲明式事務如何實現吧。
### 9.4.2? 聲明式實現事務管理
**1、定義業務邏輯實現,此處使用ConfigUserServiceImpl和ConfigAddressServiceImpl:**
**2、定義配置文件(chapter9/service/ applicationContext-service-declare.xml):**
**2.1、XML命名空間定義,定義用于事務支持的tx命名空間和AOP支持的aop命名空間:**
```
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
```
**2.2、業務實現配置,非常簡單,使用以前定義的非侵入式業務實現:**
```
<bean id="userService" class="cn.javass.spring.chapter9.service.impl.ConfigUserServiceImpl">
<property name="userDao" ref="userDao"/>
<property name="addressService" ref="addressService"/>
</bean>
<bean id="addressService" class="cn.javass.spring.chapter9.service.impl.ConfigAddressServiceImpl">
<property name="addressDao" ref="addressDao"/>
</bean>
```
**2.3、事務相關配置:**
```
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="save*" propagation="REQUIRED" isolation="READ_COMMITTED"/>
<tx:method name="*" propagation="REQUIRED" isolation="READ_COMMITTED" read-only="true"/>
</tx:attributes>
</tx:advice>
```
```
<aop:config>
<aop:pointcut id="serviceMethod" expression="execution(* cn..chapter9.service..*.*(..))"/>
<aop:advisor pointcut-ref="serviceMethod" advice-ref="txAdvice"/>
</aop:config>
```
* <tx:advice>:事務通知定義,用于指定事務屬性,其中“transaction-manager”屬性指定事務管理器,并通過< tx:attributes >指定具體需要攔截的方法;
* <tx:method name="save*">:表示將攔截以save開頭的方法,被攔截的方法將應用配置的事務屬性:propagation="REQUIRED"表示傳播行為是Required,isolation="READ_COMMITTED"表示隔離級別是提交讀;
* <tx:method name="*">:表示將攔截其他所有方法,被攔截的方法將應用配置的事務屬性:propagation="REQUIRED"表示傳播行為是Required,isolation="READ_COMMITTED"表示隔離級別是提交讀,read-only="true"表示事務只讀;
* <aop:config>:AOP相關配置:
* <aop:pointcut/>:切入點定義,定義名為"serviceMethod"的aspectj切入點,切入點表達式為"execution(* cn..chapter9.service..*.*(..))"表示攔截cn包及子包下的chapter9\. service包及子包下的任何類的任何方法;
* <aop:advisor>:Advisor定義,其中切入點為serviceMethod,通知為txAdvice。
從配置中可以看出,將對cn包及子包下的chapter9\. service包及子包下的任何類的任何方法應用“txAdvice”通知指定的事務屬性。
**3、修改測試方法并測試該配置方式是否好用:**
將TransactionTest 類的testServiceTransaction測試方法拷貝一份命名為testDeclareTransaction:
并在testDeclareTransaction測試方法內將:
```
classpath:chapter9/service/applicationContext-service.xml"
```
替換為:
```
classpath:chapter9/service/applicationContext-service-declare.xml"
```
**4、執行測試,測試正常通過,說明該方式能正常工作,**當調用save方法時將匹配到事務通知中定義的“<tx:method name="save*">”中指定的事務屬性,而調用countAll方法時將匹配到事務通知中定義的“<tx:method name="*">”中指定的事務屬性。
聲明式事務是如何實現事務管理的呢?還記不記得TransactionProxyFactoryBean實現配置式事務管理,配置式事務管理是通過代理方式實現,而聲明式事務管理同樣是通過AOP代理方式實現。
聲明式事務通過AOP代理方式實現事務管理,利用環繞通知TransactionInterceptor實現事務的開啟及關閉,而TransactionProxyFactoryBean內部也是通過該環繞通知實現的,因此可以認為是<tx:tags/>幫你定義了TransactionProxyFactoryBean,從而簡化事務管理。
了解了實現方式后,接下來詳細學習一下配置吧:
### 9.4.4? <tx:advice/>配置詳解
聲明式事務管理通過配置<tx:advice/>來定義事務屬性,配置方式如下所示:
```
<tx:advice id="……" transaction-manager="……">
<tx:attributes>
<tx:method name="……"
propagation=" REQUIRED"
isolation="READ_COMMITTED"
timeout="-1"
read-only="false"
no-rollback-for=""
rollback-for=""/>
……
</tx:attributes>
</tx:advice>
```
* **<tx:advice>:**id用于指定此通知的名字, transaction-manager用于指定事務管理器,默認的事務管理器名字為“transactionManager”;
* <tx:method>:用于定義事務屬性即相關聯的方法名;
**name:**定義與事務屬性相關聯的方法名,將對匹配的方法應用定義的事務屬性,可以使用“*”通配符來匹配一組或所有方法,如“save*”將匹配以save開頭的方法,而“*”將匹配所有方法;
**pro**pagation:事務傳播行為定義,默認為“REQUIRED”,表示Required,其值可以通過TransactionDefinition的靜態傳播行為變量的“PROPAGATION_”后邊部分指定,如“TransactionDefinition.PROPAGATION_REQUIRED”可以使用“REQUIRED”指定;
isolation:事務隔離級別定義;默認為“DEFAULT”,其值可以通過TransactionDefinition的靜態隔離級別變量的“ISOLATION_”后邊部分指定,如“TransactionDefinition. ISOLATION_DEFAULT”可以使用“DEFAULT”指定:
**timeout:**事務超時時間設置,單位為秒,默認-1,表示事務超時將依賴于底層事務系統;
**read-only:**事務只讀設置,默認為false,表示不是只讀;
**rollback-for:**需要觸發回滾的異常定義,以“,”分割,默認任何RuntimeException 將導致事務回滾,而任何Checked Exception 將不導致事務回滾;異常名字定義和TransactionProxyFactoryBean中含義一樣
**no-rollback-for:**不被觸發進行回滾的 Exception(s);以“,”分割;異常名字定義和TransactionProxyFactoryBean中含義一樣;
記不記得在配置方式中為了解決“自我調用”而導致的不能設置正確的事務屬性問題,使用“**((IUserService)AopContext.currentProxy()).otherTransactionMethod()”**方式解決,在聲明式事務要得到支持需要使用<aop:config expose-proxy="true">來開啟。
### 9.4.5? 多事務語義配置及最佳實踐
什么是多事務語義?說白了就是為不同的Bean配置不同的事務屬性,因為我們項目中不可能就幾個Bean,而可能很多,這可能需要為Bean分組,為不同組的Bean配置不同的事務語義。在Spring中,可以通過配置多切入點和多事務通知并通過不同方式組合使用即可。
**?????? 1、首先看下聲明式事務配置的最佳實踐吧:**
```
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="save*" propagation="REQUIRED" />
<tx:method name="add*" propagation="REQUIRED" />
<tx:method name="create*" propagation="REQUIRED" />
<tx:method name="insert*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="merge*" propagation="REQUIRED" />
<tx:method name="del*" propagation="REQUIRED" />
<tx:method name="remove*" propagation="REQUIRED" />
<tx:method name="put*" propagation="REQUIRED" />
<tx:method name="get*" propagation="SUPPORTS" read-only="true" />
<tx:method name="count*" propagation="SUPPORTS" read-only="true" />
<tx:method name="find*" propagation="SUPPORTS" read-only="true" />
<tx:method name="list*" propagation="SUPPORTS" read-only="true" />
<tx:method name="*" propagation="SUPPORTS" read-only="true" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="txPointcut" expression="execution(* cn.javass..service.*.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut" />
</aop:config>
```
該聲明式事務配置可以應付常見的CRUD接口定義,并實現事務管理,我們只需修改切入點表達式來攔截我們的業務實現從而對其應用事務屬性就可以了,如果還有更復雜的事務屬性直接添加即可,即
如果我們有一個batchSaveOrUpdate方法需要“REQUIRES_NEW”事務傳播行為,則直接添加如下配置即可:
```
<tx:method name="batchSaveOrUpdate" propagation="REQUIRES_NEW" />
```
**2、接下來看一下多事務語義配置吧,**聲明式事務最佳實踐中已經配置了通用事務屬性,因此可以針對需要其他事務屬性的業務方法進行特例化配置:
```
<tx:advice id="noTxAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="*" propagation="NEVER" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="noTxPointcut" expression="execution(* cn.javass..util.*.*())" />
<aop:advisor advice-ref="noTxPointcut" pointcut-ref="noTxAdvice" />
</aop:config>
```
該聲明將對切入點匹配的方法所在事務應用“Never”傳播行為。
多事務語義配置時,切入點一定不要疊加,否則將應用兩次事務屬性,造成不必要的錯誤及麻煩。
### 9.4.6? @Transactional實現事務管理
對聲明式事務管理,Spring提供基于@Transactional注解方式來實現,但需要Java 5+。
注解方式是最簡單的事務配置方式,可以直接在Java源代碼中聲明事務屬性,且對于每一個業務類或方法如果需要事務都必須使用此注解。
接下來學習一下注解事務的使用吧:
**1、定義業務邏輯實現:**
```
package cn.javass.spring.chapter9.service.impl;
//省略import
public class AnnotationUserServiceImpl implements IUserService {
private IUserDao userDao;
private IAddressService addressService;
public void setUserDao(IUserDao userDao) {
this.userDao = userDao;
}
public void setAddressService(IAddressService addressService) {
this.addressService = addressService;
}
@Transactional(propagation=Propagation.REQUIRED, isolation=Isolation.READ_COMMITTED)
@Override
public void save(final UserModel user) {
userDao.save(user);
user.getAddress().setUserId(user.getId());
addressService.save(user.getAddress());
}
@Transactional(propagation=Propagation.REQUIRED, isolation=Isolation.READ_COMMITTED, readOnly=true)
@Override
public int countAll() {
return userDao.countAll();
}
}
```
**2、定義配置文件(chapter9/service/ applicationContext-service-annotation.xml):**
**2.1、XML命名空間定義,定義用于事務支持的tx命名空間和AOP支持的aop命名空間:**
```
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
```
**2.2、業務實現配置,非常簡單,使用以前定義的非侵入式業務實現:**
```
<bean id="userService" class="cn.javass.spring.chapter9.service.impl.ConfigUserServiceImpl">
<property name="userDao" ref="userDao"/>
<property name="addressService" ref="addressService"/>
</bean>
<bean id="addressService" class="cn.javass.spring.chapter9.service.impl.ConfigAddressServiceImpl">
<property name="addressDao" ref="addressDao"/>
</bean>
```
**2.3、事務相關配置:**
```
<tx:annotation-driven transaction-manager="txManager"/>
```
使用如上配置已支持聲明式事務。
**3、修改測試方法并測試該配置方式是否好用:**
將TransactionTest 類的testServiceTransaction測試方法拷貝一份命名為testAnntationTransactionTest:
將測試代碼片段:
```
classpath:chapter9/service/applicationContext-service.xml"
```
替換為:
```
classpath:chapter9/service/applicationContext-service-annotation.xml"
```
將測試代碼段
```
userService.save(user);
```
**替換為:**
```
try {
userService.save(user);
Assert.fail();
} catch (RuntimeException e) {
}
Assert.assertEquals(0, userService.countAll());
Assert.assertEquals(0, addressService.countAll());
```
**4、執行測試,測試正常通過,說明該方式能正常工作,**因為在AnnotationAddressServiceImpl類的save方法中拋出異常,因此事務需要回滾,所以兩個countAll操作都返回0。
### 9.4.7? @Transactional配置詳解
Spring提供的<tx:annotation-driven/>用于開啟對注解事務管理的支持,從而能識別Bean類上的@Transactional注解元數據,其具有以下屬性:
* transaction-manager:指定事務管理器名字,默認為transactionManager,當使用其他名字時需要明確指定;
* proxy-target-class:表示將使用的代碼機制,默認false表示使用JDK代理,如果為true將使用CGLIB代理
* order:定義事務通知順序,默認Ordered.LOWEST_PRECEDENCE,表示將順序決定權交給AOP來處理。
Spring使用@Transaction來指定事務屬性,可以在接口、類或方法上指定,如果類和方法上都指定了@Transaction,則方法上的事務屬性被優先使用,具體屬性如下:
* value:指定事務管理器名字,默認使用<tx:annotation-driven/>指定的事務管理器,用于支持多事務管理器環境;
* **propagation**:指定事務傳播行為,默認為Required,使用Propagation.REQUIRED指定;
* **isolation**:指定事務隔離級別,默認為“DEFAULT”,使用Isolation.DEFAULT指定;
* **readOnly**:指定事務是否只讀,默認false表示事務非只讀;
* **timeout**:指定事務超時時間,以秒為單位,默認-1表示事務超時將依賴于底層事務系統;
* **rollbackFor**:指定一組異常類,遇到該類異常將回滾事務;
* **rollbackForClassname**:指定一組異常類名字,其含義與<tx:method>中的rollback-for屬性語義完全一樣;
* **noRollbackFor**:指定一組異常類,即使遇到該類異常也將提交事務,即不回滾事務;
* **noRollbackForClassname**:指定一組異常類名字,其含義與<tx:method>中的no-rollback-for屬性語義完全一樣;
Spring提供的@Transaction注解事務管理內部同樣利用環繞通知TransactionInterceptor實現事務的開啟及關閉。
使用@Transactional注解事務管理需要特別注意以下幾點:
* 如果在接口、實現類或方法上都指定了@Transactional 注解,則優先級順序為方法>實現類>接口;
* 建議只在實現類或實現類的方法上使用@Transactional,而不要在接口上使用,這是因為如果使用JDK代理機制是沒問題,因為其使用基于接口的代理;而使用使用CGLIB代理機制時就會遇到問題,因為其使用基于類的代理而不是接口,這是**因為接口上的@Transactional注解是“不能繼承的”**;
具體請參考[基于JDK動態代理和CGLIB動態代理的實現Spring注解管理事務(@Trasactional)到底有什么區別。](http://www.iteye.com/topic/1121357)
* 在Spring代理機制下(不管是JDK動態代理還是CGLIB代理),“自我調用”同樣不會應用相應的事務屬性,其語義和<tx:tags>中一樣;
* 默認只對RuntimeException異常回滾;
* 在使用Spring代理時,默認只有在public可見度的方法的@Transactional 注解才是有效的,其它可見度(protected、private、包可見)的方法上即使有@Transactional 注解也不會應用這些事務屬性的,Spring也不會報錯,如果你非要使用非公共方法注解事務管理的話,可考慮使用AspectJ。
### 9.4.9? 與其他AOP通知協作
Spring聲明式事務實現其實就是Spring AOP+線程綁定實現,利用AOP實現開啟和關閉事務,利用線程綁定(ThreadLocal)實現跨越多個方法實現事務傳播。
由于我們不可能只使用一個事務通知,可能還有其他類型事務通知,而且如果這些通知中需要事務支持怎么辦?這就牽扯到通知執行順序的問題上了,因此如果可能與其他AOP通知協作的話,而且這些通知中需要使用聲明式事務管理支持,事務通知應該具有最高優先級。
### 9.4.10? 聲明式or編程式
編程式事務時不推薦的,即使有很少事務操作,Spring發展到現在,沒有理由使用編程式事務,只有在為了深入理解Spring事務管理才需要學習編程式事務使用。
推薦使用聲明式事務,而且強烈推薦使用<tx:tags>方式的聲明式事務,因為其是無侵入代碼的,可以配置模板化的事務屬性并運用到多個項目中。
而@Transaction注解事務,可以使用,不過作者更傾向于使用<tx:tags>聲明式事務。
能保證項目正常工作的事務配置就是最好的。
### 9.4.11? 混合事務管理
所謂混合事務管理就是混合多種數據訪問技術使用,如混合使用Spring JDBC + Hibernate,接下來讓我們學習一下常見混合事務管理:
1、? Hibernate + Spring JDBC/iBATIS:使用HibernateTransactionManager即可支持;
2、? JPA + Spring JDBC/iBATIS:使用JpaTransactionManager即可支持;
3、? JDO + Spring JDBC/iBATIS:使用JtaTransactionManager即可支持;
混合事務管理最大問題在于如果我們使用第三方ORM框架,如Hibernate,會遇到一級及二級緩存問題,尤其是二級緩存可能造成如使用Spring JDBC和Hibernate查詢出來的數據不一致等。
因此不建議使用這種混合使用和混合事務管理。
原創內容,轉載請注明出處【[http://sishuok.com/forum/blogPost/list/0/2508.html](http://sishuok.com/forum/blogPost/list/0/2508.html#7228)】
- 跟我學 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