對Struts2的機制的研究已略略有了小的成果,分享給大家。
我們只負責Action和jsp頁面的編寫,數據的準備及其他工作都是由Struts2內部給我們做好了處理。
頁面一個請求發送過來,依次經過一系列攔截器(處理公共部分,如:往數據中心(值棧)填充數據,所處理工作與業務無關),Action,Result。
1,經過一系列攔截器
介紹其中的兩個攔截器:ModelDriven、Params;
——一個請求過來,首先創建一個值棧對象,初始化,然後在Map和對象棧中放入一些數據:
(1)值棧的結構:
(2)在Map和對象棧中分別存入什麼數據:
Map中:request=…,session=…,application=…,attr=…,
parameters=…;
對象棧中:action對象,…
——初始化完之後,還會經過很多攔截器,其中一個攔截器ModelDriven(封裝model,把model放入對象棧的棧頂),一個攔截器Params(參數封裝,放入參數);
(1)經過…攔截器
(2)再經過ModelDriven攔截器:
Action中實現ModelDriven<>,並實現它的方法:
Public class RoleActionextends ActionSupport implements ModelDriven<Role>{
private Role model = new Role();
private Role getModel(){ //獲取棧頂的model對象
return model;
}
}
ModelDriven的作用:把model對象放入對象棧棧頂(原來棧頂是action,現在棧頂是model了)
(3)經過…攔截器
(4)再經過Params攔截器
Params攔截器的作用:封裝參數。
如何封裝?——做了兩件事:第一,先到對象棧中封裝;第二,再到Map中封裝;
例子:假如,現在對象棧中有model對象在(含有id、name屬性)在棧頂,action對象(含有id、age屬性);頁面訪問地址:xx.action?id=3&name=ab&age=20&xx=00;
經過Params攔截器時,它如何將參數封裝?
——先從棧頂開始找,依次找到id、name、age屬性,通過各自的Set方法依次設值id=3,name=ab,age=20(注:雖然對象棧中有兩個id屬性,但是由於model對象的id屬性在棧頂,所以找到此id屬性就設值,不會繼續往下找),但是對象棧中沒有xx屬性,於是戰中就沒有這個參數了,通過對象棧就無法得到xx參數,但是Map中有parameters,可以把所有參數放入parameters中,無論在對象棧中有沒有寫屬性,在parameters中都能得到;
——經過一系列攔截器之後,此時數據中心就有了數據,那我們就可以從中獲取數據(Action、Jsp中均可從中獲取並使用);
2,思考:值棧對象作用範圍是什麼?
——一個請求。因爲每發送一個請求過來,都要經過這樣一系列過程:攔截器(往值棧中壓入數據)——>Action——>Request
3,細節擴充:
(1)有值棧對象,如何操作Map?
——ActionContext.getContext()
.put(k,v);//Map中放入數據
.get(k);//Map中獲取數據
或:ActionContext.getContext.getValueStack()
.put(k,v);//Map中放入數據
.get(k);//Map中獲取數據
(2)有了值棧對象,如何操作對象棧?
——ActionContext.getContext().getValueStack()
.push(obj);//對象棧中放入數據
.pop();Map中獲取數據
(3)所以,值棧中有了對象,Action中如何使用棧中的數據:
——通過ActionContext()操作Map,操作對象棧
(4)所以,值棧中有了對象,jsp中如何使用棧中的數據:
——通過OGNL表達式獲取
OGNL表達式的格式和語法:
格式:
(1)在Struts.xml中的格式爲:${ongl};
(2)在Jsp中的格式爲:%{ongl};
(注:只能寫在Struts2的自定義標籤的屬性中)
語法:
user =findValue("user");//從棧中獲取user屬性
#user = map.get("user"); //從Map中獲取user對象
#user.name=map.get("user").getName();//從Map中獲取user對象的name屬性
(findvalue(expr))的查找順序:
(1),從對象棧中查找指定名稱的屬性,從棧頂開始向下找,找到後就返回;
(2)如果從對象棧中沒有找到屬性,則從Map中查找對應的key值,找到後就返回。
例子: