Struts2中OGNL、ActionContext和值棧及線程安全淺析

 值棧(ValueStack)    安全

Struts2將OGNL上下文設置爲Struts2中的ActionContext(內部使用的仍然是OgnlContext),並將值棧設爲OGNL的根對象。     
OGNL上下文中的根對象能夠用ONGL表達式以對象名直接訪問的,不須要使用任何特殊的「標記」,而引用上下文中的其餘對象則須要使用「#」來標記。因爲值棧是OGNL上下文中的根對象,所以能夠直接訪問。那麼對於值棧中的對象該如何訪問呢?Struts2提供了一個特殊的OGNLPropertyAccessor,它能夠自動查找棧內的全部對象(從棧頂到棧底),直接找到一個具備你所查找的屬性的對象。也就是說,對於值棧中的任何對象均可以直接訪問,而不須要使用「#」。     
值棧中的對象都是OGNL上下文中的根對象。這就是Struts2在OGNL基礎上作出的改進。 
 
ActionContext 
ActionContext是Action的環境,一次Action調用都會建立一個ActionContext 
調用:ActionContext context = ActionContext.getContext() 
 
Struts2對OGNL上下文的概念又作了進一步擴充,在struts2中,OGNL上下文一般以下所示: 
 
                        |--request  
 
                        |  
 
                        |--application  
 
                        |  
 
context map---|--OgnlValueStack(root) [ user, action, OgnlUtil, ... ]  
 
                        |  
 
                        |--session  
 
                        |  
 
                        |--attr  
 
                        |  
 
                        |--parameters  
 
在Struts2中,採用標準命名的上下文(Context)來處理OGNL表達式。處理OGNL的頂級對象是一個Map(也叫context map),而OGNL在這個context中就是一個頂級對象(root)。在用法上,頂級對象的屬性訪問,是不須要任何標記前綴的。而其它非頂級的對象訪問,須要使用#標記。 
 
例如: 
Html代碼  
<s:property value="%{#application.myApplicationKey}" />  
<s:property value="%{#session.mySessionKey}" />  
<s:property value="%{#request.myRequestKey}" />  
<s:property value="%{#parameters.myParameterKey}" />   
 
 
Struts2框架把OGNL Context設置爲ActionContext。而且ValueStack做爲OGNL的根對象。除value stack以外,Struts2框架還把表明application、session、request這些對象的Map對象也放到ActionContext中去。(這也就是Struts2建議在Action類中不要直接訪問Servlet API的緣由,他能夠經過ActionContext對象來部分代替這些(Servlet API)功能。) 
 
 
 
Struts2把頁面上的值傳到Action裏面,這個過程從邏輯上說須要分紅兩步來完成: 
 
1. 對於每一個請求,都創建一個與相應Action對應的ActionContext做爲OGNL的上下文環境和ValueStack,而且把Action裏面的屬性值壓入ValueStack,這時的屬性值都是初始化值。 
 
2. 在請求進入Action代碼前,經過某種通用的機制(就是Struts2的interceptor攔截器機制),蒐集頁面上傳遞過來的參數,這裏調用的是params攔截器,準確來講是這個攔截器會找Action裏面的全部屬性的set方法,把頁面的Struts2標籤的對應名稱的屬性值set進去,這樣Action裏面的屬性就成功賦值。 
 
 
 
設計Struts2的團隊初衷就是爲了避免用和那些Servlet API複雜的請求(Request)、響應(Response)關聯在一塊兒。 
 
 
 
 
Struts2的線程安全 
通常狀況,咱們的ActionContext都是經過:ActionContext context = (ActionContext) actionContext.get();來獲取的。咱們再來看看這裏的actionContext對象的建立:static ThreadLocal actionContext = new ActionContextThreadLocal();,ActionContextThreadLocal是實現ThreadLocal的一個內部類。ThreadLocal能夠命名爲「線程局部變量」,它爲每個使用該變量的線程都提供一個變量值的副本,使每個線程均可以獨立地改變本身的副本,而不會和其它線程的副本衝突。這樣,咱們ActionContext裏的屬性只會在對應的當前請求線程中可見,從而保證它是線程安全的。 
 
Struts2的action中就像一個POJO同樣,定義了不少的類變量。此時,就使用scope=prototype來指定是個原型模式,而不是單例,這樣就解決了線程安全問題。每一個線程都是一個新的實例。 
相關文章
相關標籤/搜索