# 【第十三章】 測試 之 13.3 集成測試 ——跟我學spring3
## 13.3? 集成測試
### 13.3.1? 概述
集成測試是在單元測試之上,通常是將一個或多個已進行過單元測試的組件組合起來完成的,即集成測試中一般不會出現Mock對象,都是實實在在的真實實現。
對于單元測試,如前邊在進行數據訪問層單元測試時,通過Mock HibernateTemplate對象然后將其注入到相應的DAO實現,此時單元測試只測試某層的某個功能是否正確,對其他層如何提供服務采用Mock方式提供。
對于集成測試,如要進行數據訪問層集成測試時,需要實實在在的HibernateTemplate對象然后將其注入到相應的DAO實現,此時集成測試將不僅測試該層功能是否正確,還將測試服務提供者提供的服務是否正確執行。
使用Spring的一個好處是能非常簡單的進行集成測試,無需依賴web服務器或應用服務器即可完成測試。Spring通過提供一套TestContext框架來簡化集成測試,使用TestContext測試框架能獲得許多好處,如Spring IoC容器緩存、事務管理、依賴注入、Spring測試支持類等等。
### 13.3.2 Spring TestContext框架支持
Spring TestContext框架提供了一些通用的集成測試支持,主要提供如下支持:
一、**上下文管理及緩存:**
對于每一個測試用例(測試類)應該只有一個上下文,而不是每個測試方法都創建新的上下文,這樣有助于減少啟動容器的開銷,提供測試效率。可通過如下方式指定要加載的上下文:
```
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
locations={"classpath:applicationContext-resources-test.xml",
"classpath:cn/javass/point/dao/applicationContext-hibernate.xml"})
public class GoodsHibernateDaoIntegrationTest {
}
```
* **locations:**指定Spring配置文件位置;
* **inheritLocations:**如果設置為false,將屏蔽掉父類中使用該注解指定的配置文件位置,默認為true表示繼承父類中使用該注解指定的配置文件位置。
二、**Test Fixture(測試固件)的依賴注入:**
Test Fixture可以指運行測試時需要的任何東西,一般通過@Before定義的初始化Fixture方法準備這些資源,而通過@After定義的銷毀Fixture方法銷毀或還原這些資源。
Test Fixture的依賴注入就是使用Spring IoC容器的注入功能準備和銷毀這些資源。可通過如下方式注入Test Fixture:
```
@Autowired
private IGoodsDao goodsDao;
@Autowired
private ApplicationContext ctx;
```
即可以通過Spring提供的注解實現Bean的依賴注入來完成Test Fixture的依賴注入。
**三、事務管理:?**
開啟測試類的事務管理支持,即使用Spring 容器的事務管理功能,從而可以獨立于應用服務器完成事務相關功能的測試。為了使測試中的事務管理起作用需要通過如下方式開啟測試類事務的支持:
```
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
locations={"classpath:applicationContext-resources-test.xml",
"classpath:cn/javass/point/dao/applicationContext-hibernate.xml"})
@TransactionConfiguration(
transactionManager = "txManager", defaultRollback=true)
public class GoodsHibernateDaoIntegrationTest {
}
```
Spring提供如下事務相關注解來支持事務管理:
* @Transactional:使用@Transactional注解的類或方法將得到事務支持?
* **transactionManager:**指定事務管理器;
* **defaultRollback:**是否回滾事務,默認為true表示回滾事務。
Spring還通過提供如下注解來簡化事務測試:
* **@Transactional:**使用@Transactional注解的類或方法表示需要事務支持;
* **@NotTransactional:**只能注解方法,使用@NotTransactional注解的方法表示不需要事務支持,即不運行在事務中,Spring 3開始已不推薦使用;
* **@BeforeTransaction和@AfterTransaction:**使用這兩個注解注解的方法定義了在一個事務性測試方法之前或之后執行的行為,且被注解的方法將運行在該事務性方法的事務之外。
* **@Rollback(true)**:默認為true,用于替換@TransactionConfiguration中定義的defaultRollback指定的回滾行為。
**四、常用注解支持:**Spring框架提供如下注解來簡化集成測試:
* **@DirtiesContext:**表示每個測試方法執行完畢需關閉當前上下文并重建一個全新的上下文,即不緩存上下文。可應用到類或方法級別,但在JUnit 3.8中只能應用到方法級別。
* **@ExpectedException:**表示被注解的方法預期將拋出一個異常,使用如@ExpectedException(NotCodeException.class)來指定異常,定義方式類似于Junit 4中的@Test(expected = NotCodeException.class),@ExpectedException注解和@Test(expected =……)應該兩者選一。
* @Repeat:**表示被注解的方法應被重復執行多少次,使用如@Repeat(2)方式指定。**
* **@Timed:**表示被注解的方法必須在多長時間內運行完畢,超時將拋出異常,使用如@Timed(millis=10)方式指定,單位為毫秒。注意此處指定的時間是如下方法執行時間之和:測試方法執行時間(或者任何測試方法重復執行時間之和)、@Before和@After注解的測試方法之前和之后執行的方法執行時間。而Junit 4中的@Test(timeout=2)指定的超時時間只是測試方法執行時間,不包括任何重復等。
* **除了支持如上注解外,還支持【第十二章?零配置】中依賴注入等注解。**
**五、TestContext框架支持類:**提供對測試框架的支持,如Junit、TestNG測試框架,用于集成Spring TestContext和測試框架來簡化測試,TestContext框架提供如下支持類:
* **JUnit 3.8支持類:**提供對Spring TestContext框架與Junit3.8測試框架的集成:
**AbstractJUnit38SpringContextTests:**我們的測試類繼承該類后將獲取到Test Fixture的依賴注入好處。
**AbstractTransactionalJUnit38SpringContextTests:**我們的測試類繼承該類后除了能得到Test Fixture的依賴注入好處,還額外獲取到事務管理支持。
* **JUnit 4.5+支持類:**提供對Spring TestContext框架與Junit4.5+測試框架的集成:
**AbstractJUnit4SpringContextTests:**我們的測試類繼承該類后將獲取到Test Fixture的依賴注入好處。
**AbstractTransactionalJUnit4SpringContextTests:**我們的測試類繼承該類后除了能得到Test Fixture的依賴注入好處,還額外獲取到事務管理支持。
* **定制 Junit4.5+運行器:**通過定制自己的Junit4.5+運行器從而無需繼承JUnit 4.5+支持類即可完成需要的功能,如Test Fixture的依賴注入、事務管理支持,
**@RunWith(SpringJUnit4ClassRunner.class):**使用該注解注解到測試類上表示將集成Spring TestContext和Junit 4.5+測試框架。
**@TestExecutionListeners:**該注解用于指定TestContext框架的監聽器用于與TestContext框架管理器發布的測試執行事件進行交互,TestContext框架提供如下三個默認的監聽器:DependencyInjectionTestExecutionListener、DirtiesContextTestExecutionListener、TransactionalTestExecutionListener分別完成對Test Fixture的依賴注入、@DirtiesContext支持和事務管理支持,即在默認情況下將自動注冊這三個監聽器,另外還可以使用如下方式指定監聽器:
```
@RunWith(SpringJUnit4ClassRunner.class)
@TestExecutionListeners({})
public class GoodsHibernateDaoIntegrationTest {
}
```
如上配置將通過定制的Junit4.5+運行器運行,但不會完成Test Fixture的依賴注入、事務管理等等,如果只需要Test Fixture的依賴注入,可以使用@TestExecutionListeners({DependencyInjectionTestExecutionListener.class})指定。
* **TestNG支持類:**提供對Spring TestContext框架與TestNG測試框架的集成:
**AbstractTestNGSpringContextTests:**我們的測試類繼承該類后將獲取到Test Fixture的依賴注入好處。
**AbstractTransactionalTestNGSpringContextTests:**我們的測試類繼承該類后除了能得到Test Fixture的依賴注入好處,還額外獲取到事務管理支持。
到此Spring TestContext測試框架減少完畢了,接下來讓我們學習一下如何進行集成測試吧。
### 13.3.3??????? 準備集成測試環境
對于集成測試環境各種配置應該和開發環境或實際生產環境配置相分離,即集成測試時應該使用單獨搭建一套獨立的測試環境,不應使用開發環境或實際生產環境的配置,從而保證測試環境、開發、生產環境相分離。
1、拷貝一份Spring資源配置文件applicationContext-resources.xml,并命名為applicationContext-resources-test.xml表示用于集成測試使用,并修改如下內容:
```
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:resources-test.properties</value>
</list>
</property>
</bean>
```
**2、拷貝一份替換配置元數據的資源文件(resources/resources.properties),并命名為resources-test.properties表示用于集成測試使用,并修改為以下內容:**
```
db.driver.class=org.hsqldb.jdbcDriver
db.url=jdbc:hsqldb:mem:point_shop
db.username=sa
db.password=
#Hibernate屬性
hibernate.dialect=org.hibernate.dialect.HSQLDialect
hibernate.hbm2ddl.auto=create-drop
hibernate.show_sql=false
hibernate.format_sql=true
```
* **jdbc:hsqldb:mem:point_shop:**我們在集成測試時將使用HSQLDB,并采用內存數據庫模式運行;
* **hibernate.hbm2ddl.auto=create-drop**:表示在創建SessionFactory時根據Hibernate映射配置創建相應Model的表結構,并在SessionFactory關閉時刪除這些表結構。
到此我們測試環境修改完畢,在進行集成測試時一定要保證測試環境、開發環境、實際生產環境相分離,即對于不同的環境使用不同的配置文件。
### 13.3.4? 數據訪問層
數據訪問層集成測試,同單元測試一樣目的不僅測試該層定義的接口實現方法的行為是否正確,而且還要測試是否正確與數據庫交互,是否發送并執行了正確的SQL,SQL執行成功后是否正確的組裝了業務邏輯層需要的數據。
數據訪問層集成測試不再通過Mock對象與數據庫交互的API來完成測試,而是使用實實在在存在的與數據庫交互的對象來完成測試。
接下來讓我們學習一下如何進行數據訪問層集成測試:
**1、在test文件夾下創建如下測試類:**
```
package cn.javass.point.dao.hibernate;
//省略import
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
locations={"classpath:applicationContext-resources-test.xml",
"classpath:cn/javass/point/dao/applicationContext-hibernate.xml"})
@TransactionConfiguration(transactionManager = "txManager", defaultRollback=false)
public class GoodsHibernateDaoIntegrationTest {
@Autowired
private ApplicationContext ctx;
@Autowired
private IGoodsCodeDao goodsCodeDao;
}
```
* **@RunWith(SpringJUnit4ClassRunner.class):**表示使用自己定制的Junit4.5+運行器來運行測試,即完成Spring TestContext框架與Junit集成;
* **@ContextConfiguration:**指定要加載的Spring配置文件,此處注意我們的Spring資源配置文件為“applicationContext-resources-test.xml”;
* **@TransactionConfiguration:**開啟測試類的事務管理支持配置,并指定事務管理器和默認回滾行為;
* **@Autowired:**完成Test Fixture(測試固件)的依賴注入。
**2、測試支持寫完后,接下來測試一下分頁查詢所有已發布的商品是否滿足需求:**
```
@Transactional
@Rollback
@Test
public void testListAllPublishedSuccess() {
GoodsModel goods = new GoodsModel();
goods.setDeleted(false);
goods.setDescription("");
goods.setName("測試商品");
goods.setPublished(true);
goodsDao.save(goods);
Assert.assertTrue(goodsDao.listAllPublished(1).size() == 1);
Assert.assertTrue(goodsDao.listAllPublished(2).size() == 0);
}
```
* **@Transactional:**表示測試方法將允許在事務環境;
* **@Rollback:**表示替換@ContextConfiguration指定的默認事務回滾行為,即將在測試方法執行完畢時回滾事務。
數據訪問層的集成測試也是非常簡單,與數據訪問層的單元測試類似,也應該只對復雜的數據訪問層代碼進行測試。
### 13.3.5? 業務邏輯層
業務邏輯層集成測試,目的同樣是測試該層的業務邏輯是否正確,對于數據訪問層實現通過Spring IoC容器完成裝配,即使用真實的數據訪問層實現來獲取相應的底層數據。
接下來讓我們學習一下如何進行業務邏輯層集成測試:
**1、在test文件夾下創建如下測試類:**
```
@ContextConfiguration(
locations={"classpath:applicationContext-resources-test.xml",
"classpath:cn/javass/point/dao/applicationContext-hibernate.xml",
"classpath:cn/javass/point/service/applicationContext-service.xml"})
@TransactionConfiguration(transactionManager = "txManager", defaultRollback=false)
public class GoodsCodeServiceImplIntegrationTest extends AbstractJUnit4SpringContextTests {
@Autowired
private IGoodsCodeService goodsCodeService;
@Autowired
private IGoodsService goodsService;
}
```
* **AbstractJUnit4SpringContextTests:**表示將Spring TestContext框架與Junit4.5+測試框架集成;
* **@ContextConfiguration:**指定要加載的Spring配置文件,此處注意我們的Spring資源配置文件為“applicationContext-resources-test.xml”;
* **@TransactionConfiguration:**開啟測試類的事務管理支持配置,并指定事務管理器和默認回滾行為;
* **@Autowired:**完成Test Fixture(測試固件)的依賴注入。
**2、測試支持寫完后,接下來測試一下購買商品Code碼是否滿足需求:**
**2.1、測試購買失敗的場景:**
```
@Transactional
@Rollback
@ExpectedException(NotCodeException.class)
@Test
public void testBuyFail() {
goodsCodeService.buy("test", 1);
}
```
由于我們數據庫中沒有相應商品的Code碼,因此將拋出NotCodeException異常。
**2.2、測試購買成功的場景:**
```
@Transactional
@Rollback
@Test
public void testBuySuccess() {
//1.添加商品
GoodsModel goods = new GoodsModel();
goods.setDeleted(false);
goods.setDescription("");
goods.setName("測試商品");
goods.setPublished(true);
goodsService.save(goods);
//2.添加商品Code碼
GoodsCodeModel goodsCode = new GoodsCodeModel();
goodsCode.setGoods(goods);
goodsCode.setCode("test");
goodsCodeService.save(goodsCode);
//3.測試購買商品Code碼
GoodsCodeModel resultGoodsCode = goodsCodeService.buy("test", 1);
Assert.assertEquals(goodsCode.getId(), resultGoodsCode.getId());
}
```
由于我們添加了指定商品的Code碼因此購買將成功,如果失敗說明業務寫錯了,應該重寫。
業務邏輯層的集成測試也是非常簡單,與業務邏輯層的單元測試類似,也應該只對復雜的業務邏輯層代碼進行測試。
### 13.3.5? 表現層
對于表現層集成測試,同樣類似于單元測試,但對于業務邏輯層都將使用真實的實現,而不再是通過Mock對象來測試,這也是集成測試和單元測試的區別。
接下來讓我們學習一下如何進行表現層Action集成測試:
**1、準備Struts提供的junit插件,?到struts-2.2.1.1.zip中拷貝如下jar包到類路徑:**
```
lib\struts2-junit-plugin-2.2.1.1.jar
```
**2、測試支持類:**Struts2提供StrutsSpringTestCase測試支持類,我們所有的Action測試類都需要繼承該類;
**3、準備Spring配置文件:**由于我們的測試類繼承StrutsSpringTestCase且將通過覆蓋該類的getContextLocations方法來指定Spring配置文件,但由于getContextLocations方法只能返回一個配置文件,因此我們需要新建一個用于導入其他Spring配置文件的配置文件applicationContext-test.xml,具體內容如下:
```
<import resource="classpath:applicationContext-resources-test.xml"/>
<import resource="classpath:cn/javass/point/dao/applicationContext-hibernate.xml"/>
<import resource="classpath:cn/javass/point/service/applicationContext-service.xml"/>
<import resource="classpath:cn/javass/point/web/pointShop-admin-servlet.xml"/>
<import resource="classpath:cn/javass/point/web/pointShop-front-servlet.xml"/>
```
**3、在test文件夾下創建如下測試類:**
```
package cn.javass.point.web.front;
//省略import
@RunWith(SpringJUnit4ClassRunner.class)
@TestExecutionListeners({})
public class GoodsActionIntegrationTest extends StrutsSpringTestCase {
@Override
protected String getContextLocations() {
return "classpath:applicationContext-test.xml";
}
@Before
public void setUp() throws Exception {
//1 指定Struts2配置文件
//該方式等價于通過web.xml中的<init-param>方式指定參數
Map<String, String> dispatcherInitParams = new HashMap<String, String>();
ReflectionTestUtils.setField(this, "dispatcherInitParams", dispatcherInitParams);
//1.1 指定Struts配置文件位置
dispatcherInitParams.put("config", "struts-default.xml,struts-plugin.xml,struts.xml");
super.setUp();
}
@After
public void tearDown() throws Exception {
super.tearDown();
}
}
```
* **@RunWith(SpringJUnit4ClassRunner.class):**表示使用自己定制的Junit4.5+運行器來運行測試,即完成Spring TestContext框架與Junit集成;
* **@TestExecutionListeners({}):**沒有指定任何監聽器,即不會自動完成對Test Fixture的依賴注入、@DirtiesContext支持和事務管理支持;
* **StrutsSpringTestCase:**集成測試Struts2+Spring時所有集成測試類必須繼承該類;
* **setUp方法:**在每個測試方法之前都執行的初始化方法,其中dispatcherInitParams用于指定等價于在web.xml中的<init-param>方式指定的參數;必須調用super.setUp()用于初始化Struts2和Spring環境。
* **tearDown():**在每個測試方法之前都執行的銷毀方法,必須調用super.tearDown()來銷毀Spring容器等。
**4、測試支持寫完后,接下來測試一下前臺購買商品Code碼是否滿足需求:**
**4.1、測試購買失敗的場景:**
```
@Test
public void testBuyFail() throws UnsupportedEncodingException, ServletException {
//2 前臺購買商品失敗
//2.1 首先重置hhtp相關對象,并準備準備請求參數
initServletMockObjects();
request.setParameter("goodsId", String.valueOf(Integer.MIN_VALUE));
//2.2 調用前臺GoodsAction的buy方法完成購買相應商品的Code碼
executeAction("/goods/buy.action");
GoodsAction frontGoodsAction = (GoodsAction) ActionContext.getContext().getActionInvocation().getAction();
//2.3 驗證前臺GoodsAction的buy方法有錯誤
Assert.assertTrue(frontGoodsAction.getActionErrors().size() > 0);
}
```
* **initServletMockObjects()**:用于重置所有http相關對象,如request等;
* **request.setParameter("goodsId", String.valueOf(Integer.MIN_VALUE))**:用于準備請求參數;
* **executeAction("/goods/buy.action"):**通過模擬http請求來調用前臺GoodsAction的buy方法完成商品購買
* **Assert.assertTrue(frontGoodsAction.getActionErrors().size() > 0)**:表示執行Action時有錯誤,即Action動作錯誤。如果條件不成立,說明我們Action功能是錯誤的,需要修改。
**4.2、測試購買成功的場景:**
```
@Test
public void testBuySuccess() throws UnsupportedEncodingException, ServletException {
//3 后臺新增商品
//3.1 準備請求參數
request.setParameter("goods.name", "測試商品");
request.setParameter("goods.description", "測試商品描述");
request.setParameter("goods.originalPoint", "1");
request.setParameter("goods.nowPoint", "2");
request.setParameter("goods.published", "true");
//3.2 調用后臺GoodsAction的add方法完成新增
executeAction("/admin/goods/add.action");
//2.3 獲取GoodsAction的goods屬性
GoodsModel goods = (GoodsModel) findValueAfterExecute("goods");
//4 后臺新增商品Code碼
//4.1 首先重置hhtp相關對象,并準備準備請求參數
initServletMockObjects();
request.setParameter("goodsId", String.valueOf(goods.getId()));
request.setParameter("codes", "a\rb");
//4.2 調用后臺GoodsCodeAction的add方法完成新增商品Code碼
executeAction("/admin/goodsCode/add.action");
//5 前臺購買商品成功
//5.1 首先重置hhtp相關對象,并準備準備請求參數
initServletMockObjects();
request.setParameter("goodsId", String.valueOf(goods.getId()));
//5.2 調用前臺GoodsAction的buy方法完成購買相應商品的Code碼
executeAction("/goods/buy.action");
GoodsAction frontGoodsAction = (GoodsAction) ActionContext.getContext().getActionInvocation().getAction();
//5.3 驗證前臺GoodsAction的buy方法沒有錯誤
Assert.assertTrue(frontGoodsAction.getActionErrors().size() == 0);
}
```
* **executeAction("/admin/goods/add.action"):**調用后臺GoodsAction的add方法,用于新增商品;
* **executeAction("/admin/goodsCode/add.action"):**調用后臺GoodCodeAction的add方法用于新增商品Code碼;
* **executeAction("/goods/buy.action"):**調用前臺GoodsAction的buy方法,用于購買相應商品,其中Assert.assertTrue(frontGoodsAction.getActionErrors().size() == 0)表示購買成功,即Action動作正確。
表現層Action集成測試介紹就到此為止,如何深入StrutsSpringTestCase來完成集成測試已超出本書范圍,如果讀者對這部分感興趣可以到Struts2官網學習最新的測試技巧。
原創內容,轉載請注明私塾在線【[http://sishuok.com/forum/blogPost/list/0/2557.html](http://sishuok.com/forum/blogPost/list/0/2557.html#7333)】
- 跟我學 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