iBatis的JpetStore示例中MVC機制實現原理

JpetStore中的Action與普通StrutsAction處理方式不一樣。遍歷JpetStoresrc文件夾,並無一個具體的Action,那麼它是如何來完成普通StrutsAction工作了?
查看JpetStoreStruts.xml可以發現,它的Action只有一個,即“org.apache.stuts.beanaction.Beanaction”。通過Eclipse查看beanaction.jar的源代碼,可以發現Beanaction繼承與普通Action,即具備普通的action的功能。那麼它無具體Action的奧妙在哪,繼續研究BeanAction的代碼,截取BeanActionexcute方法中核心部分代碼如下: 

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對象的哪個方法來處理。
1parameter=”*’直接跳轉;(2Parameter中含具體的方法名;(3Path中最後一個/後的方法名
以這個請求連接爲例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>
 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章