国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
在Struts2中使用OGNL
OGNL是XWork引入的一個非常有效的數(shù)據(jù)處理的工具。我們已經(jīng)了解了OGNL的基本操作和OGNL的內(nèi)部結(jié)構(gòu),接下來,我們來看看XWork對OGNL做了什么樣的加強(qiáng),以及OGNL的體系在Struts2中如何運(yùn)轉(zhuǎn)。
目 錄 [ - ]
從例子開始
ValueStack —— 對OGNL的加強(qiáng)
Struts2中的OGNL上下文環(huán)境
Struts2中使用OGNL進(jìn)行計算
從例子開始 
我們先從一個例子開始,看看數(shù)據(jù)在Struts2中是如何運(yùn)轉(zhuǎn)的。
Java代碼 
/**
* @author Downpour
*/
public class User {
private Integer id;
private String name;
private Department department = new Department();
// setter and getters
}
//=========================================================================
/**
* @author Downpour
*/
public class Department {
private Integer id;
private String name;
// setter and getters
}
//=========================================================================
<form method="post" action="/struts-example/ognl.action">
user name: <input type="text" name="user.name" value="downpour" />
department name: <input type="text" name="department.name" value="dev" />
<input type="submit" value="submit" />
</form>
//=========================================================================
/**
* @author Downpour
*/
public class OgnlAction extends ActionSupport {
private static final Log logger = LogFactory.getLog(OgnlAction.class);
private User user;
private Department department;
/* (non-Javadoc)
* @see com.opensymphony.xwork2.ActionSupport#execute()
*/
@Override
public String execute() throws Exception {
logger.info("user name:" + user.getName());   // -> downpour
logger.info("department name:" + department.getName());   // -> dev
return super.execute();
}
// setter and getters
}
//=========================================================================
user name: <s:property value="user.name" />
department name: <s:property value="department.name" />
//=========================================================================
我們可以看到在JSP中,form中的元素input等,都使用OGNL的表達(dá)式作為name的值。而在form提交時,這些值都會被設(shè)置到Action中的Java對象中。而當(dāng)Action轉(zhuǎn)向到JSP時,Struts2的Tag又可以從Action的Java對象中,通過OGNL進(jìn)行取值。
在這里,你看不到任何的OGNL的代碼級別操作,因為這些都在Struts2內(nèi)部進(jìn)行了封裝。而這些封裝,都是建立在OGNL的基本概念,也就是根對象和上下文環(huán)境之上。下面就分別就這兩個方面分別進(jìn)行講解。
ValueStack —— 對OGNL的加強(qiáng) 
細(xì)心的讀者可能會發(fā)現(xiàn),在上面的例子中,我們使用了不同的表達(dá)式,針對Action中的不同的Java對象進(jìn)行設(shè)值。再結(jié)合上一講我們所例舉的OGNL的代碼操作示例,我們有強(qiáng)烈的理由懷疑,Struts2在內(nèi)部有可能執(zhí)行了這樣的操作,才使得頁面到Action的設(shè)值工作順利完成:
Java代碼 
// "user.name" as OGNL expression, action as OGNL Root object
Ognl.setValue("user.name", action, "downpour");
Ognl.setValue("department.name", action, "dev");
如果這個懷疑是正確的,那么我們就能得出這樣一個結(jié)論:Struts2的Action是OGNL操作的根對象。
這個結(jié)論是我們從現(xiàn)象上推出來的,至于它到底正確與否,我們之后可以通過源碼分析來進(jìn)行驗證,在這里先賣一個關(guān)子,姑且認(rèn)為它是正確的。不過這個結(jié)論對我們來說非常重要,因為這個結(jié)論Struts2的Tag,JSTL和Freemarker等表示層元素獲取Action中變量的值打下了堅實的基礎(chǔ)。
在Struts2(XWork)中,不僅把Action作為OGNL操作的根對象,作為對OGNL的擴(kuò)展,它還引入了一個ValueStack的概念。這個概念代表了什么呢?還是讓我們看看Struts2的Reference怎么說:
Struts2 Reference 寫道
The biggest addition that XWork provides on top of OGNL is the support for the ValueStack. While OGNL operates under the assumption there is only one "root", XWork's ValueStack concept requires there be many "roots".
很明顯,ValueStack依照它的結(jié)構(gòu)和作用,至少為我們提供兩大特性:
1. ValueStack是一個堆棧結(jié)構(gòu),堆棧中的每個元素對于OGNL操作來說,都被看作是根對象。
2. 由于ValueStack是一個堆棧結(jié)構(gòu),所以其中的元素都是有序的,對于某個OGNL表達(dá)式來說,OGNL將自堆棧頂部開始查找,并返回第一個符合條件的對象元素。
這里我們有必要對第二點啰嗦幾句,舉個具體的例子來說(這個例子同樣摘自Struts2的Reference):如果在ValueStack中有2個對象,分別是“動物”和“人”,這兩個對象都具備一個屬性,叫做name,而“動物”還有一個屬性叫species,“人”還有個屬性叫salary。其中,“動物”對象在ValueStack的棧頂,而“人”這個對象在棧底。那么看看下面的OGNL表達(dá)式將返回什么?
Java代碼 
species    // call to animal.getSpecies()
salary     // call to person.getSalary()
name       // call to animal.getName() because animal is on the top
對于name這個屬性,返回的將是“動物”的name,因為“動物”在棧頂,會被先匹配到OGNL的表達(dá)式。但是有的時候,你可能需要訪問“人”的name屬性,怎么辦呢?你可以通過下面的方法:
Java代碼 
[0].name   // call to animal.getName()
[1].name   // call to person.getName()
Struts2中的OGNL上下文環(huán)境 
有了ValueStack,我們再來仔細(xì)研究一下Struts2中OGNL的上下文環(huán)境。
Struts2 Reference 寫道
The framework sets the OGNL context to be our ActionContext, and the value stack to be the OGNL root object. (The value stack is a set of several objects, but to OGNL it appears to be a single object.) Along with the value stack, the framework places other objects in the ActionContext, including Maps representing the application, session, and request contexts. These objects coexist in the ActionContext, alongside the value stack (our OGNL root)
也就是說,ActionContext是Struts2中OGNL的上下文環(huán)境。它維護(hù)著一個Map的結(jié)構(gòu),下面是這個結(jié)構(gòu)的圖示:
其中,ValueStack是這個上下文環(huán)境中的根對象,而除了這個根對象以外,Struts2還在這個上下文環(huán)境中放了許多額外的變量,而這些變量多數(shù)都是被XWork封裝過的Servlet對象,例如request,session,servletContext(application)等,這些對象都被封裝成Map對象,隨著ActionContext作用于整個Action執(zhí)行的生命周期中。
在這里,或許有些讀者會提出問題來,為什么好好的Servlet對象要在這里被封裝成Map對象呢?我想原因可能有以下兩個:
1. 對Struts2的Action徹底屏蔽Servlet容器,從而無需再使用底層Servlet API進(jìn)行編程。你所面對的,將永遠(yuǎn)是一個又一個的Java對象。
2. 便于各種View技術(shù),例如JSP,F(xiàn)reemarker,Velocity等對ValueStack中上下文環(huán)境,尤其是Servlet對象中的數(shù)據(jù)進(jìn)行讀取。試想,如果在這里不將HttpServletRequest,HttpSession等Servlet對象轉(zhuǎn)化成Map,那么我們將很難通過OGNL表達(dá)式,對這些Servlet對象中的值進(jìn)行讀取。
Struts2中使用OGNL進(jìn)行計算 
取值計算
有了上面的這些知識,我們就能非常容易的理解在Struts2中如何使用OGNL進(jìn)行取值計算。
提問:在Struts2中,如何使用自身的Tag讀取Action中的變量?
Struts2自身的Tag會根據(jù)value中的OGNL表達(dá)式,在ValueStack中尋找相應(yīng)的對象。因為action在ValueStack的頂部,所以默認(rèn)情況下,Struts2的Tag中的OGNL表達(dá)式將查找action中的變量。請注意,value中的內(nèi)容直接是OGNL表達(dá)式,無需任何el的標(biāo)簽包裝。
例如:<s:property value="user.name" />
提問:在Struts2中,如何使用自身的Tag讀取HttpServletRequest,HttpSession中的變量?
在上面的知識中,我們知道,Struts2中OGNL的上下文環(huán)境中,包含request,session,application等servlet對象的Map封裝。既然這些對象都在OGNL的上下文中,那么根據(jù)OGNL的基本知識,我們可以通過在表達(dá)式前面加上#符號來對這些變量的值進(jìn)行訪問。
例如:<s:property value="%{#application.myApplicationAttribute}" />
<s:property value="%{#session.mySessionAttribute}" />
<s:property value="%{#request.myRequestAttribute}" />
<s:property value="%{#parameters.myParameter}" />
在這里啰嗦一句,在Tag的value中包括%{開頭和}結(jié)尾的字符串,不知道Struts2為什么要做出這樣的設(shè)置,從源碼上看,它似乎沒有什么特別額外的作用:
Java代碼 
if (value == null) {
value = "top";
}
else if (altSyntax()) {
// the same logic as with findValue(String)
// if value start with %{ and end with }, just cut it off!
if (value.startsWith("%{") && value.endsWith("}")) {
value = value.substring(2, value.length() - 1);
}
}
// exception: don't call findString(), since we don't want the
//            expression parsed in this one case. it really
//            doesn't make sense, in fact.
actualValue = (String) getStack().findValue(value, String.class);
......
}
有興趣的朋友可以研究一下,這一對符號的原理究竟是什么。
提問:在Struts2中,如何使用JSTL來讀取Action中的變量?
這是一個歷史悠久的問題。因為事實上,很多朋友(包括我在內(nèi))是不使用Struts2自身的標(biāo)簽庫,而是使用JSTL的,可能因為JSTL標(biāo)簽庫比較少,簡單易用的原因吧。
我們知道,JSTL默認(rèn)是從page,request,session,application這四個Scope逐次查找相應(yīng)的EL表達(dá)式所對應(yīng)的對象的值。那么如果要使用JSTL來讀取Action中的變量,就需要把Action中的變量,放到request域中才行。所以,早在Webwork2.1.X的年代,我們會編寫一個攔截器來做這個事情的。大致的原理是:在Action執(zhí)行完返回之前,依次讀取Action中的所有的變量,并依次調(diào)用request.setAttribute()來進(jìn)行設(shè)置。具體的整合方式,請參考以下這篇文檔:http://wiki.opensymphony.com/display/WW/Using+WebWork+and+XWork+with+JSP+2.0+and+JSTL+1.1
不過隨著時代的發(fā)展,上面的這種方式,已經(jīng)不再被推薦使用了。(雖然如此,我們依然可以學(xué)習(xí)它的一個解決問題的思路)目前來說,自從Webwork2.2以后,包括Struts2,都使用另外一種整合方式:對HttpServletRequest進(jìn)行裝飾。讓我們來看一下源碼:
Java代碼 
public class StrutsRequestWrapper extends HttpServletRequestWrapper {
/**
* The constructor
* @param req The request
*/
public StrutsRequestWrapper(HttpServletRequest req) {
super(req);
}
/**
* Gets the object, looking in the value stack if not found
*
* @param s The attribute key
*/
public Object getAttribute(String s) {
if (s != null && s.startsWith("javax.servlet")) {
// don't bother with the standard javax.servlet attributes, we can short-circuit this
// see WW-953 and the forums post linked in that issue for more info
return super.getAttribute(s);
}
ActionContext ctx = ActionContext.getContext();
Object attribute = super.getAttribute(s);
boolean alreadyIn = false;
Boolean b = (Boolean) ctx.get("__requestWrapper.getAttribute");
if (b != null) {
alreadyIn = b.booleanValue();
}
// note: we don't let # come through or else a request for
// #attr.foo or #request.foo could cause an endless loop
if (!alreadyIn && attribute == null && s.indexOf("#") == -1) {
try {
// If not found, then try the ValueStack
ctx.put("__requestWrapper.getAttribute", Boolean.TRUE);
ValueStack stack = ctx.getValueStack();
if (stack != null) {
attribute = stack.findValue(s);
}
} finally {
ctx.put("__requestWrapper.getAttribute", Boolean.FALSE);
}
}
return attribute;
}
}
看到了嘛?這個類會在Struts2初始化的時候,替換HttpServletRequest,運(yùn)行于整個Struts2的運(yùn)行過程中,當(dāng)我們試圖調(diào)用request.getAttribute()的時候,就會執(zhí)行上面的這個方法。(這是一個典型的裝飾器模式)在執(zhí)行上面的方法時,會首先調(diào)用HttpServletRequest中原本的request.getAttribute(),如果沒有找到,它會繼續(xù)到ValueStack中去查找,而action在ValueStack中,所以action中的變量通過OGNL表達(dá)式,就能找到對應(yīng)的值了。
在這里,在el表達(dá)式廣泛使用的今天,JSTL1.1以后,也支持直接使用el表達(dá)式。注意與直接使用struts2的tag的區(qū)別,這里需要使用el的表示符號:${}
例如:${user.name}, <c:out value="${department.name}" />
提問:在Struts2中,如何使用Freemarker等模板來讀取Action中的變量以及HttpServletRequest和HttpSession中的變量?
Freemarker等模板在Struts2中有對應(yīng)的Result,而在這些Result中,F(xiàn)reemarker等模板會根據(jù)ValueStack和ActionContext中的內(nèi)容,構(gòu)造這些模板可識別的Model,從而使得模板可以以他們各自的語法對ValueStack和ActionContext中的內(nèi)容進(jìn)行讀取。
有關(guān)Freemarker對于變量的讀取,可以參考Struts2的官方文檔,非常詳細(xì):http://struts.apache.org/2.0.14/docs/freemarker.html
設(shè)值計算
Struts2中使用OGNL進(jìn)行設(shè)值計算,就是指View層傳遞數(shù)據(jù)到Control層,并且能夠設(shè)置到相應(yīng)的Java對象中。這個過程從邏輯上說需要分成兩步來完成:
1. 對于每個請求,都建立一個與相應(yīng)Action對應(yīng)的ActionContext作為OGNL的上下文環(huán)境和ValueStack,并且把Action壓入ValueStack
2. 在請求進(jìn)入Action代碼前,通過某種通用的機(jī)制,搜集頁面上傳遞過來的參數(shù),并調(diào)用OGNL相關(guān)的代碼,對Action進(jìn)行設(shè)值。
上面的第一個步驟,在處理URL請求時完成,而第二個步驟,則涉及到另外一個XWork的核心知識:攔截器。所以有關(guān)Struts2使用OGNL進(jìn)行設(shè)值計算的詳細(xì)分析,將會在攔截器章節(jié)具體給出。
本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
struts2.x的ActionContext,ValueStack和常用標(biāo)簽介紹
STRUTS2中的OGNL
Struts2技術(shù)詳解
Struts2 面試題分析
Struts2 中的值棧是什么?
Ognl表達(dá)式基本原理和使用方法
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服