下午臨時(shí)有點(diǎn)時(shí)間,一直以來有個(gè)想法,那就是sstruts2要深入熟悉一下。于是趁這個(gè)時(shí)間,找來源碼,重點(diǎn)看了action的初始化及調(diào)用執(zhí)行。
怕看過后就忘掉,特此記下來。有的地方可能理解的不對(duì),待哪一天有機(jī)會(huì)真正理解透徹了,再過來看過,更正。
struts2中,通過web容器請(qǐng)求一個(gè)action,經(jīng)過系統(tǒng)的Fileter,Struts2的ActionMapping及FilterDispatcher后,來到ActionProxy(一般執(zhí)行struts2默認(rèn)的ActionProxy,即DefaultActionProxy):
1 . ActionProxy首先執(zhí)行其prepare方法,做一些準(zhǔn)備工作。
讀取action的配置(配置文件已被初始化到內(nèi)存,此時(shí)到內(nèi)存中讀?)
從action配置中獲取要訪問的action的方法名
調(diào)用ActionInvocation(如無例外,一般是默認(rèn)的ActionInvocation,即DefaultActionInvocation)的init方法,init方法使用action名稱,利用類加載器新建一個(gè)action實(shí)例(從這里可以看出struts2 中的action是多例的),action可以事先通過spring容器加載到內(nèi)存。然后通過配置讀取所有的攔截器存儲(chǔ)到此ActionInvocation攔截器List當(dāng)中,DefaultActionInvocation#init, 410~411行:
f.jpg
2 . 執(zhí)行ActionInvocation的invoke方法,從ActionInvocation的攔截器列表判斷有沒有攔截器要執(zhí)行,如果有,則執(zhí)行攔截器的intercept方法,由于攔截器的intercept方法會(huì)繼續(xù)調(diào)用ActionInvocation的invoke方法,然后invoke繼續(xù)從攔截器列表中讀取并調(diào)用下一個(gè)攔截器的intercept,因此此邏輯是一個(gè)攔截器的遞歸調(diào)用,等最后一個(gè)攔截器執(zhí)行invoke時(shí),action才得的真正執(zhí)行,執(zhí)行后根據(jù)執(zhí)行結(jié)果的配置,返回結(jié)果代碼(error,success,或其他在result節(jié)點(diǎn)中配置的結(jié)果),action執(zhí)行完后,最后一個(gè)攔截器的intercept方法在調(diào)用invoke后繼續(xù)執(zhí)行完,然后是倒數(shù)第二個(gè)攔截器在intercept方法的invoke后執(zhí)行完,即遞歸的執(zhí)行邏輯:執(zhí)行流依次出棧繼續(xù)執(zhí)行。
這里附上ActionInvocation的invoke方法執(zhí)行攔截器的主體代碼:
DefaultActionInvocation#invoke, 243~255行
f2.jpg
3 . 寫了一個(gè)模擬struts2中action及攔截器執(zhí)行的例子 ,點(diǎn)這里查看