摘要: JpetStore提供了一個整套的測試代碼對于想進行單元測試卻不知道如何進行單元測試的人(me)來說,是一個很好的學習機會。
JpetStore的單元測試代碼與它的系統源文件是獨立分離的,在test文件夾中。打開文件夾可以很清楚的發現該文件夾的內容組成結構與源文件基本一致。
JpetStore分為領域層(domain),持久層(peristence),服務層(service),表現層(presentation),它的測試也分這幾個層來進行。
閱讀全文
posted @
2007-01-22 15:18 滌生 閱讀(3334) |
評論 (0) |
編輯 收藏
摘要: 本文是在參閱了http://ivanl.javaeye.com/blog/24739基礎上完成的
在看JPetStore的代碼時,發現它的分頁處理主要是通過返回PaginatedList對象來完成的。如:在CatalogService類中
public PaginatedList getProductListByCategory(String categoryId) {
return productDao.getProductListByCategory(categoryId);
}
分頁是操作數據庫型系統常遇到的問題。分頁實現方法很多,但效率的差異就很大了。iBatis是通過什么方式來實現這個分頁的了。查看它的實現部分:
閱讀全文
posted @
2007-01-18 16:27 滌生 閱讀(8460) |
評論 (6) |
編輯 收藏
關鍵字: OO ? UML,泛化,依賴,關聯,聚合????
類與類之間的關系對于理解面向對象具有很重要的作用,以前在面試的時候也經常被問到這個問題,在這里我就介紹一下。 類與類之間存在以下關系: (1)泛化(Generalization) (2)關聯(Association) (3)依賴(Dependency) (4)聚合(Aggregation)
UML圖與應用代碼例子:
1.泛化(Generalization)
[泛化]
表示類與類之間的繼承關系,接口與接口之間的繼承關系,或類對接口的實現關系。一般化的關系是從子類指向父類的,與繼承或實現的方法相反。 [具體表現] 父類 父類實例=new 子類() [UML圖](圖1.1)
 圖1.1Animal類與Tiger類,Dog類的泛化關系
[代碼表現]
-
class
?Animal{} ??
-
class
?Tiger?
extends
?Animal{} ??
-
public
?
class
?Test ??
-
{ ??
-
????
public
?
void
?test() ??
-
????{ ??
-
????????Animal?a=
new
?Tiger(); ??
-
????} ??
-
}??
2.依賴(Dependency)
[依賴]
對于兩個相對獨立的對象,當一個對象負責構造另一個對象的實例,或者依賴另一個對象的服務時,這兩個對象之間主要體現為依賴關系。 [具體表現] 依賴關系表現在局部變量,方法的參數,以及對靜態方法的調用 [現實例子] 比如說你要去擰螺絲,你是不是要借助(也就是依賴)螺絲刀(Screwdriver)來幫助你完成擰螺絲(screw)的工作 [UML表現](圖1.2)

圖1.2 Person類與Screwdriver類的依賴關系
[代碼表現]
- public?class?Person{ ??
- ??????
- ????public?void?screw(Screwdriver?screwdriver){ ??
- ????????screwdriver.screw(); ??
- ????} ??
- }??
3.關聯(Association) [關聯] 對于兩個相對獨立的對象,當一個對象的實例與另一個對象的一些特定實例存在固定的對應關系時,這兩個對象之間為關聯關系。 [具體表現] 關聯關系是使用實例變量來實現 [現實例子] 比如客戶和訂單,每個訂單對應特定的客戶,每個客戶對應一些特定的訂單;再例如公司和員工,每個公司對應一些特定的員工,每個員工對應一特定的公司 [UML圖] (圖1.3)
 圖1.3 公司和員工的關聯關系
[代碼表現]
- public?class?Company{ ??
- ????private?Employee?employee; ??
- ????public?Employee?getEmployee(){ ??
- ????????return?employee; ??
- ????} ??
- ????public?void?setEmployee(Employee?employee){ ??
- ????????this.employee=employee; ??
- ????} ??
- ??????
- ????public?void?run(){ ??
- ????????employee.startWorking(); ??
- ????} ??
- }??
(4)聚合(Aggregation)
[聚合]
當對象A被加入到對象B中,成為對象B的組成部分時,對象B和對象A之間為聚集關系。聚合是關聯關系的一種,是較強的關聯關系,強調的是整體與部分之間的關系。 [具體表現] 與關聯關系一樣,聚合關系也是通過實例變量來實現這樣關系的。關聯關系和聚合關系來語法上是沒辦法區分的,從語義上才能更好的區分兩者的區別。 [關聯與聚合的區別] (1)關聯關系所涉及的兩個對象是處在同一個層次上的。比如人和自行車就是一種關聯關系,而不是聚合關系,因為人不是由自行車組成的。 聚合關系涉及的兩個對象處于不平等的層次上,一個代表整體,一個代表部分。比如電腦和它的顯示器、鍵盤、主板以及內存就是聚集關系,因為主板是電腦的組成部分。 (2)對于具有聚集關系(尤其是強聚集關系)的兩個對象,整體對象會制約它的組成對象的生命周期。部分類的對象不能單獨存在,它的生命周期依賴于整體類的對象的生命周期,當整體消失,部分也就隨之消失。比如張三的電腦被偷了,那么電腦的所有組件也不存在了,除非張三事先把一些電腦的組件(比如硬盤和內存)拆了下來。 [UML圖](圖1.4)
 圖1.3 電腦和組件的聚合關系
[代碼表現]
- public?class?Computer{ ??
- ????private?CPU?cpu; ??
- ????public?CPU?getCPU(){ ??
- ????????return?cpu; ??
- ????} ??
- ????public?void?setCPU(CPU?cpu){ ??
- ????????this.cpu=cpu; ??
- ????} ??
- ??????
- ????public?void?start(){ ??
- ??????????
- ????????cpu.run(); ??
- ????} ??
- }??
|
posted @
2007-01-17 10:07 滌生 閱讀(577) |
評論 (0) |
編輯 收藏
摘要: 本文參考了
iBatis DAO入門與進階(http://www.matrix.org.cn/resource/article/44/44058_iBatis+DAO.html)
iBatis DAO事務探索(http://m.tkk7.com/RongHao/archive/2006/01/20/28817.html)
今天繼續研究了JPetStore的持久層,其中由于看了一篇文章的誤導,導致我對其中的事務處理深表懷疑。通過閱讀源代碼與看上面兩篇文章,對這個問題才認識清楚。和我當初預想的一致。
閱讀全文
posted @
2007-01-16 21:15 滌生 閱讀(2806) |
評論 (2) |
編輯 收藏
摘要: 問題就出現在這,Item類中包含了Product類,出現NestedSqlException錯誤。
查閱了ibatis幫助,此處sql_map的嵌套類寫法是正確的。我又將這個sql語句拷貝到MsSqlServer中執行,結果也是正確的。陷入困惑。
閱讀全文
posted @
2007-01-16 13:38 滌生 閱讀(3366) |
評論 (6) |
編輯 收藏
今天在看JPetStore代碼時,對他的鏈接中的請求參數感到疑惑,最后發現是自己的對Struts框架不熟悉導致的。
我是從Net陣營中剛轉入Java里的,在Net中對請求參數的名稱無特殊限制,只要在頁面中取參數的值即可。當然這個功能在Java中也具備。即request.Getparameter()
今天我在看JpetStore代碼時,在點擊
http://127.0.0.1:8083/JPetStore/shop/viewCategory.shtml?categoryId=BIRDS時,當跟蹤函數viewCategory時發現此時categoryID已經賦值了,我卻找不到在什么地方賦值的,好是花費了一番周執。
查看此段鏈接對應的struts.xml

????<action?path="/shop/viewCategory"?type="org.apache.struts.beanaction.BeanAction"
????????????name="catalogBean"?scope="session"
????????????validate="false">
??????<forward?name="success"?path="/catalog/Category.jsp"/>我首先跟蹤BeanAction的excute函數發現在此之前就已經賦值,說明和BeanAction無關,是Struts系統本身的結構。我故意將鏈接修改,修改成
http://127.0.0.1:8083/JPetStore/shop/viewCategory.shtml?category=BIRDS此時出現錯誤,錯誤如下:
java.lang.IllegalArgumentException:?Cannot?invoke?com.ibatis.jpetstore.presentation.CatalogBean.setCategory?-?argument?type?mismatch
????org.apache.commons.beanutils.PropertyUtilsBean.invokeMethod(PropertyUtilsBean.java:1778)
????org.apache.commons.beanutils.PropertyUtilsBean.setSimpleProperty(PropertyUtilsBean.java:1759)
????org.apache.commons.beanutils.PropertyUtilsBean.setNestedProperty(PropertyUtilsBean.java:1648)
????org.apache.commons.beanutils.PropertyUtilsBean.setProperty(PropertyUtilsBean.java:1677)
????org.apache.commons.beanutils.BeanUtilsBean.setProperty(BeanUtilsBean.java:1022)
????org.apache.commons.beanutils.BeanUtilsBean.populate(BeanUtilsBean.java:811)
????org.apache.commons.beanutils.BeanUtils.populate(BeanUtils.java:298)
????org.apache.struts.util.RequestUtils.populate(RequestUtils.java:493)
????org.apache.struts.action.RequestProcessor.processPopulate(RequestProcessor.java:805)
????org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:203)
????org.apache.struts.action.ActionServlet.process(ActionServlet.java:1194)
????org.apache.struts.action.ActionServlet.doGet(ActionServlet.java:414)
????javax.servlet.http.HttpServlet.service(HttpServlet.java:689)
????javax.servlet.http.HttpServlet.service(HttpServlet.java:802)

根據這個錯誤堆棧可知,它實際上采用的是反射,setProperty,此時找不到category的Setter函數報錯。然后我查看了一下RequestProcessor的默認實現代碼
//?Process?any?ActionForm?bean?related?to?this?request
ActionForm?form?=?processActionForm(request,?response,?mapping);
processPopulate(request,?response,?form,?mapping);這段函數功能為:
1)調用processActionForm( )方法檢查是否存在為ActionMapping配置的ActionForm 。如果存在,則在有效區
域內查找是否存在該ActionForm 的實例,存在,則復用,不存在,則創建一個實例。然后將實例保存與再配置
文件中配置好的有效區域(request,session,application)內,并用Action元素的name屬性作為該實例的關鍵字。
2)調用processPopulate( )方法,如果存來存在為ActionMapping配置的ActionForm,則封裝請求對象中的數據
到ActionForm 中,在進行封裝之前,先調用ActionForm 的reset( )方法進行屬性值的默認化。
根據以上的分析,可得知,在調用鏈接前struts框架會自動的將所有的請求參數封裝入指定的formbean中。所以請求參數的名稱應該是對應formbean的一個屬性。
這就是struts中請求參數的處理過程。主要是我對struts還沒有完全掌握,加上Net的影響,才花費了一圈發現這個原因。
posted @
2007-01-15 20:56 滌生 閱讀(971) |
評論 (0) |
編輯 收藏
JpetStore中的Action與普通Struts的Action處理方式不一樣。遍歷JpetStore的src文件夾,并無一個具體的Action,那么它是如何來完成普通Struts的Action工作了?
查看JpetStore的Struts.xml可以發現,它的Action只有一個,即“org.apache.stuts.beanaction.Beanaction”。通過Eclipse查看beanaction.jar的源代碼,可以發現Beanaction繼承與普通Action,即具備普通的action的功能。那么它無具體Action的奧妙在哪,繼續研究BeanAction的代碼,截取BeanAction的excute方法中核心部分代碼如下:?

/**//*遍歷此方法的業務邏輯可知,*的優先級最高,如果是*,則不調用任何方法直接Forward,類似于ForwardAction*/?
private?static?final?String?NO_METHOD_CALL?=?"*";?
…….?

/**//*所有的FormBean都繼承于BaseBean*/?
BaseBean?bean?=?(BaseBean)?form;?
??????ActionContext.initCurrentContext(request,?response);?

??????if?(bean?!=?null)?
{?
????????//?Explicit?Method?Mapping?

/**//*下面是檢查struts.xml配置中是否有parameter屬性*/?
????????Method?method?=?null;?
????????String?methodName?=?mapping.getParameter();?

????????if?(methodName?!=?null?&&?!NO_METHOD_CALL.equals(methodName))?
{?

??????????try?
{?

/**//*通過反射,根據得到的方法名稱取得方法的句柄*/?
????????????method?=?bean.getClass().getMethod(methodName,?null);?

????????????synchronized?(bean)?
{?

/**//*下面是關鍵一句,調用basebean擁有的接口ActionInterceptor的實現DefaultActionInterceptor,來完成具體方法的調用*/?
??????????????forward?=?bean.getInterceptor().intercept(new?ActionInvoker(bean,?method));?
????????????}?
?????????……..?

/**//*無Parameter屬性,檢查path路徑的最后一個/后的名稱,即為調用的方法名*/?
????????//?Path?Based?Method?Mapping?

????????if?(method?==?null?&&?!NO_METHOD_CALL.equals(methodName))?
{?
??????????methodName?=?mapping.getPath();?

??????????if?(methodName.length()?>?1)?
{?
????????????int?slash?=?methodName.lastIndexOf("/")?+?1;?
????????????methodName?=?methodName.substring(slash);?

????????????if?(methodName.length()?>?0)?
{?

??????????????try?
{?
????????????????method?=?bean.getClass().getMethod(methodName,?null);?

????????????????synchronized?(bean)?
{?
??????????????????forward?=?bean.getInterceptor().intercept(new?ActionInvoker(bean,?method));?
????????????????}?
?????????????……..?

/**//*根據調用方法返回的String,得到頁面的轉移路徑*/?
return?mapping.findForward(forward);?

?
通過研究上面這段代碼,我們可知,JpetStore中沒有具體Action實現的關鍵原因即在于下面這幾句

/**//*通過反射,根據得到的方法名稱取得方法的句柄*/?
????????????method?=?bean.getClass().getMethod(methodName,?null);?

????????????synchronized?(bean)?
{?

/**//*下面是關鍵一句,調用basebean擁有的接口ActionInterceptor的實現DefaultActionInterceptor,來完成具體方法的調用*/?
??????????????forward?=?bean.getInterceptor().intercept(new?ActionInvoker(bean,?method));?
????????????}?

即將原來Action中的excute方法的實現轉移到FormBean中,這樣實現顯得更為簡捷,方便。研究ActionInvoke,它的核心代碼如下:

public?String?invoke()?
{?

????try?
{?
??????return?(String)?method.invoke(bean,?null);?

????}?catch?(Exception?e)?
{?
??????throw?new?BeanActionException("Error?invoking?Action.??Cause:?"?+?e,?e);?
????}?
??}?

至此可知,它調用的是formbean中的函數。且從這段代碼可知,formbean的這類特殊函數,此處稱為action方法,要符合兩個特征:1)無參數;2)返回值為string,此返回string即是Struts-config.xml的全局或局部的forward。
以上是整個beanaction的實現機制。個人感覺此種實現方法對于開發者而言已經類似于ASP.NET的.aspx與.cs開發模式了。下面是通過實例來說明一下BeanAction如何控制formbean的
?
Struts-config.xml的配置里有3種映射方式,來告訴BeanAction把控制轉到哪個form bean對象的哪個方法來處理。
(1)parameter=”*’直接跳轉;(2)Parameter中含具體的方法名;(3)Path中最后一個/后的方法名
以這個請求連接為例http://localhost/jpetstore4/shop/viewOrder.shtml
1. URL Pattern
<action?path="/shop/viewOrder"?type="com.ibatis.struts.BeanAction"
????name="orderBean"?scope="session"
????validate="false">
????<forward?name="success"?path="/order/ViewOrder.jsp"/>
??</action>

?
此種方式表示,控制將被轉發到"orderBean"這個form bean對象 的"viewOrder"方法(行為)來處理。方法名取"path"參數的以"/"分隔的最后一部分。
2. Method Parameter?
<action?path="/shop/viewOrder"?type="com.ibatis.struts.BeanAction"
????name="orderBean"?parameter="viewOrder"?scope="session"
????validate="false">
????<forward?name="success"?path="/order/ViewOrder.jsp"/>
??</action>

?
此種方式表示,控制將被轉發到"orderBean"這個form bean對象的"viewOrder"方法(行為)來處理。配置中的"parameter"參數表示form bean類上的方法。"parameter"參數優先于"path"參數。
3. No Method call
?<action?path="/shop/viewOrder"?type="com.ibatis.struts.BeanAction"
????name="orderBean"?parameter="*"?scope="session"
????validate="false">
????<forward?name="success"?path="/order/ViewOrder.jsp"/>
??</action>

此種方式表示,form bean上沒有任何方法被調用。如果存在"name"屬性,則struts把表單參數等數據填充到form bean對象后,把控制轉發到"success"。否則,如果name為空,則直接轉發控制到"success"。
這就相當于struts內置的org.apache.struts.actions.ForwardAction的功能
<action?path="/shop/viewOrder"?type="org.apache.struts.actions.ForwardAction"
????parameter="/order/ViewOrder.jsp?"?scope="session"?validate="false">
?</action>
?
 |
?
posted @
2007-01-12 16:34 滌生 閱讀(3885) |
評論 (8) |
編輯 收藏