上午寫了<<淺談struts2之chain[1]>>,現在接着寫下半部分:從源碼的角度談chain的機制
因爲我的源碼全是通過反編譯jar包得來,不能保證100%的正確性,若遇到不對的地方,請大家指出.也請大家先諒解
在<<淺談struts2之chain[1]>>最後,用了一個簡略圖來表示chain機制:
但實際上,如果考慮valuestack的話,這幅圖應該這樣畫:
對於此圖中,關鍵性兩個步驟:5和6, 實際上涉及到兩個攔截器:
1)chain
2)params
也就說,說chain方式的action之間共享valuestack是沒有錯的,說它們共享parameters也沒有錯
關鍵是它們的先後順序及相互影響 我們來看一下struts-core-2.0.11.jar中struts-default.xml中對這兩個攔截器的使用:
<interceptor-stack name="defaultStack">
......省略..........
<interceptor-ref name="chain"/>
..................省略...........................
<interceptor-ref name="params">
</interceptor-stack>
記注意這兩個攔截器的先後順序:先是chain,然後纔是params
這也就決定了上圖中的執行順序是:先執行5的動作後執行6的動作.
嚴格說來,上圖中5,6,7,8的動作順序描述,也不是很嚴謹,
真要說完全正確的執行順序,實際上是先5,7然後再執行6,7,8.
關於這一點,只需要在調試狀態上跟蹤下action2中的set方法的調用堆棧就能理解.
好了,接下來我們說說chain和params的定義.還是在struts-default.xml中
<interceptor name="chain" class="com.opensymphony.xwork2.interceptor.ChainingInterceptor"/>
<interceptor name="params" class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>
要說chain類型的result,實際上就是構建一條鏈接,把訪問路徑上的action對象全放在這個鏈條上,
先看下com.opensymphony.xwork2.interceptor.ChainingInterceptor.intercept(ActionInvocation invocation)
找到關鍵代碼: OgnlUtil.copy(o, invocation.getAction(), ctxMap, excludes, includes);
這就是把action鏈條上,上一個action還有上上個action.....總之把action鏈條上前面訪問的所有action對象
都執行OgnlUtil.copy(.......),也就是把它們的valuestack中的值都賦給當前action的valuestack
舉個簡單例子,有三個action
action1,action2,action3
當執行action2時,會把action1中valuestack的值賦給action2的valuestack
當執行action3時,會把先後把action1和action2中valuestack的值賦給action3的valuestack
依次類推.......
再來看下:com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ActionInvocation invocation)
其中關鍵方法調用: setParameters(action, stack, parameters);
把parameters中的內容賦給valuestack
但是,在實際使用過程,不推薦濫用chain
因爲正如之前舉的例子一樣,當chain上有兩個action的時候,
賦值過程實際上執行了3次=1+2:parameters到action1,action1到action2,parameters到action2
以此類推:有3個action時,賦值過程=6次=1+2+3
........
所以當鏈條上的action太多時,其實很費油的啦...
具體過程,空了畫個圖來表示下,大家就更容易明白了