日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

在Struts2中使用ValueStack、ActionContext、ServletContext、request、session等

發布時間:2024/9/27 编程问答 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 在Struts2中使用ValueStack、ActionContext、ServletContext、request、session等 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
目錄(?) [-]
  • ValueStack
  • 如何得到值棧:
  • 如何將對象存入值棧:
  • 讓值棧執行表達式來獲得值:
  • 在JSP中跳過棧頂元素直接訪問第二層:
  • 在JSP中訪問值棧對象本身(而不是它們的屬性)
  • ActionContext
  • ValueStack與ActionContext的聯系和區別:
  • 如何獲得ActionContext:
  • 如何向ActionContext中存入值:
  • 如何從ActionContext中讀取值:
  • HttpServletRequest類或request的Map
  • 使用HttpServletRequest類還是request的Map
  • 使用request的Map還是ActionContext:
  • 如何獲得HttpServletRequest:
  • 如何獲得request的Map:
  • Parameters,即GET請求或POST請求的參數
  • HttpServletSession類和session的Map
  • ServletContext和application的Map
  • 附錄1 ActionContext中到底有哪些數據
  • 附錄2 Struts2標簽中value屬性直接對ActionContext訪問的問題
  • ?

    ?

    筆者不知道該用哪個詞來形容ValueStack、ActionContext等可以在Struts2中用來存放數據的類。這些類使用的范圍不同,得到的方法也不同,下面就來一一介紹。

    聲明:本文參考Struts2版本為2.3.1.2,內容僅供參考,限于筆者水平有限,難免有所疏漏,望您能友善指出。本文發表于ITEYE,謝絕轉載。

    1. ValueStack

    ValueStack在中文版的《Struts2深入淺出》一書中譯作“值棧”。其本身數據結構是一個棧,使用者可以把一些對象(又稱作bean)存入值棧中,然后使用動態的表達式來讀取bean的屬性,或者對bean進行一些其他操作。由于值棧中可能有多個bean,值棧會按bean出棧的順序依次嘗試使用動態的表達式來讀取值,直到成功讀取值為止。在Struts2中,默認的值棧實現是OgnlValueStack,即默認使用Ognl這個動態表達式語言來讀取值。

    在Struts2執行一次請求的過程中,Struts2會把當前的Action對象自動放入值棧。這樣,在渲染JSP時,JSP里的代碼使用<s:property value="..."/>之類標簽中的Ognl表達式會直接作用于Action對象,從而方便的讀取Action的屬性。

    如何得到值棧:
    • 在自定義的攔截器中,使用ActionInvocation.getStack()方法( ActionInvocation 是攔截器的方法參數)。
    • 在Action類中,讓攔截器注入ValueStack或者使用ActionContext.getContext().getValueStack()來值棧(ActionContext.getContext()為靜態方法)。注意:ActionContext分配context的方式是基于線程的,如果使用這種方法,請確保它不會出錯。
    • 在JSP中,直接使用標簽即可獲得值棧里的數據,而一般不用獲取值棧本身。
    如何將對象存入值棧:
    • Struts2自動存入Action:之前已經提到,Struts2在執行一次請求的過程中會把當前的Action對象自動存入值棧中。
    • ModelDrivenInterceptor會存入Action的model屬性:如果你使用了Struts2提供的 ModelDrivenInterceptor,則它會把Action對象的getModel()方法得到的對象存入值棧中。此時,值棧最底層為Action類,其次為這個model。
    • 在自定義的攔截器中存入值棧:得到值棧對象后調用ValueStack.put(Object object)方法。
    • 在Action類中存入值棧:得到值棧對象后調用ValueStack.put(Object object)方法。
    • 在JSP中存入值棧:標簽<s:push value="..."></s:push>是專門用來在JSP中把指定的value放入值棧的,但value被放入值棧的時間僅在s:push標簽內,即程序運行到</s:push>標簽處會把value從值棧中移出。另外,還有一些標簽比如<s:iterator/>由于其功能的需要也會把一些對象放到值棧中。
    讓值棧執行表達式來獲得值:
    • 在自定義的攔截器中,獲得值棧后,使用ValueStack.findValue(...)等方法。
    • 在Action類中,獲得值棧后,使用ValueStack.findVlaue(...)等方法。
    • 在JSP中,一些標簽的屬性是直接在值棧上執行Ognl表達式的,比如<s:property/>的value屬性。如果標簽的屬性不是直接執行Ognl表達式的,則需要使用“%{}”將表達式括起來,這樣Struts2就會以Ognl表達式來執行了。至于到底哪些標簽是直接執行Ognl而哪些不是,請參考完整的官方文檔。
    在JSP中跳過棧頂元素直接訪問第二層:
    • 在JSP中,使用[0]、[1]等表達式來指定從棧的第幾層開始執行表達式。[0]表示從棧頂開始,[1]表示從棧的第二層開始。比如表達式“name”等價于“[0].name”。參見此處。
    在JSP中訪問值棧對象本身(而不是它們的屬性)
    • 在表示式中使用top關鍵字來訪問對象本身。比如,表達式“name”等價于“top.name”,表達式“[0].top”等價于“top”,表達式“[1].top.name”等價于“[1].name”。

    總之,值棧主要目的是為了讓JSP內能方便的訪問Action的屬性。


    一些例子: View Code ?1?//?此類為一個封裝數據的簡單類,在下面的例子會用到
    ?2?public?class?Person?{
    ?3?
    ?4?????private?String?name;
    ?5?
    ?6?????public?String?getName()?{
    ?7?????????return?name;
    ?8?????}
    ?9?
    10?????public?void?setName(String?name)?{
    11?????????this.name?=?name;
    12?????}
    13?}

    ?

    View Code ?1?//?本類將演示攔截器中對值棧的操作???
    ?2?public?class?MyInterceptor?extends?AbstractInterceptor?{???
    ?3???
    ?4?????public?String?intercept(ActionInvocation?invocation)?throws?Exception?{???
    ?5?????????//?獲得值棧???
    ?6?????????ValueStack?valueStack?=?invocation.getStack();???
    ?7?????????//?存入值???
    ?8?????????Person?person?=?new?Person();???
    ?9?????????valueStack.push(person);???
    10?????????//?執行表達式獲取值???
    11?????????String?name?=?(String)?valueStack.findValue("name");???
    12?????????//?其他代碼???
    13?????????return?invocation.invoke();???
    14?????}???
    15?}??

    ?

    ?

    View Code ?1?//?本類將演示在Action中對值棧進行操作???
    ?2?public?class?MyAction?extends?ActionSupport?{???
    ?3???
    ?4?????@Override??
    ?5?????public?String?execute()?throws?Exception?{???
    ?6?????????//?獲得值棧???
    ?7?????????ValueStack?valueStack?=?ActionContext.getContext().getValueStack();???
    ?8?????????//?存入值???
    ?9?????????Person?person?=?new?Person();//?這是之前例子中定義的類??
    10?????????valueStack.push(person);???
    11?????????//?執行表達式獲取值???
    12?????????String?name?=?(String)?valueStack.findValue("name");???
    13?????????//?其他代碼???
    14?????????//?......???
    15?????????return?SUCCESS;???
    16?????}???
    17?????//?以下定義的屬性供接下來的JSP例子使用???
    18?????private?String?message;???
    19?????private?Person?person;???
    20?????private?List<Person>?personList;???
    21???
    22?????public?String?getMessage()?{???
    23?????????return?message;???
    24?????}???
    25???
    26?????public?Person?getPerson()?{???
    27?????????return?person;???
    28?????}???
    29???
    30?????public?List<Person>?getPersonList()?{???
    31?????????return?personList;???
    32?????}???
    33?}??

    ?

    ?

    View Code ?1?<%@page?contentType="text/html"?pageEncoding="UTF-8"%>??
    ?2?<%@taglib?uri="/struts-tags"?prefix="s"?%>??
    ?3?<!DOCTYPE?html>??
    ?4?<html>??
    ?5?????<head>??
    ?6?????????<meta?http-equiv="Content-Type"?content="text/html;?charset=UTF-8">??
    ?7?????????<title>JSP?Page</title>??
    ?8?????</head>??
    ?9?????<body>??
    10?????????<!--?本JSP將演示在JSP中對值棧的使用?-->??
    11?????????<!--?本JSP為MyAction對應的JSP?-->??
    12???
    13?????????<!--?由于Action已經被存入的值棧,所以可以調用Action的屬性??-->??
    14?????????<!--?使用下面的標簽和表達式來顯示MyAction的message屬性?-->??
    15?????????<s:property?value="message"/>??
    16?????????<!--?使用下面的標簽和表達式來調用Action的getText(...)方法,參數為MyAction的message屬性??-->??
    17?????????<s:property?value="getText(message)"/>??
    18?????????<!--?默認情況下傳遞給cssClass的是字符串常量。可以使用“%{}”來啟用Ognl,這樣,傳遞給cssClass的就不是字符串常量"message",而是上面所說的message的值??-->??
    19?????????<s:div?cssClass="%{message}"/>??
    20?????????<!--?使用s:push標簽來將對象放入值棧,如下?-->??
    21?????????<s:push?value="person">??
    22?????????????<!--?在此s:push標簽內,值棧的棧頂元素為person,棧頂第二層為action???
    23?????????????<!--?在標簽內直接調用person的屬性(而不是Action的屬性),如下?-->??
    24?????????????<s:property?value="name"/>??
    25?????????????<!--?在標簽內也可以使用MyAction的屬性,值棧會依次先查找Person是否有該屬性,由于沒找到,會再MyAction中再查找,如下??-->??
    26?????????????<s:property?value="message"/>??
    27?????????????<!--?可以使用“[0]”、“[1]”等指定從值棧的哪一層開始查找??-->??
    28?????????????<!--?此時,使用“[0]”表示從Person開始查找,當然還是找不到,值棧就接著到MyAction中查找,如下??-->??
    29?????????????<s:property?value="[0].message"/>??
    30?????????????<!--?此時,使用“[1]”將從MyAction開始查找,而跳過了person,如下??-->??
    31?????????????<s:property?value="[1].message"/>??
    32?????????????<!--?想要訪問棧頂元素本身使用關鍵字“top”,比如,下面的top就代表棧頂的person,如下?-->??
    33?????????????<s:property?value="top"/>??
    34?????????????<!--?或者如下??-->??
    35?????????????<s:property?value="[0].top"/>??
    36?????????????<!--?想要訪問MyAction本身的話使用如下寫法??-->??
    37?????????????<s:property?value="[1].top"/>??
    38?????????</s:push>??
    39?????????<!--?此時person已被移出值棧,再使用如下標簽和表達式將無法得到值?-->??
    40?????????<!--<s:property?value="name"/>-->??
    41?????????<!--?iterator標簽會把list的每個元素依次存入棧頂,如下?-->??
    42?????????<s:iterator?value="personList">??
    43?????????????<!--?獲得List每個元素中的name屬性??-->??
    44?????????????<s:property?value="name"/>??
    45?????????</s:iterator>??
    46?????</body>??
    47?</html>??

    ?

    2.ActionContext

    ActionContext是Action的上下文,Struts2自動在其中保存了一些在Action執行過程中所需的對象,比如session, parameters, locale等。Struts2會根據每個執行HTTP請求的線程來創建對應的ActionContext,即一個線程有一個唯一的ActionContext。因此,使用者可以使用靜態方法ActionContext.getContext()來獲取當前線程的ActionContext,也正是由于這個原因,使用者不用去操心讓Action是線程安全的。

    無論如何,ActionContext都是用來存放數據的。Struts2本身會在其中放入不少數據,而使用者也可以放入自己想要的數據。ActionContext本身的數據結構是映射結構,即一個Map,用key來映射value。所以使用者完全可以像使用Map一樣來使用它,或者直接使用Action.getContextMap()方法來對Map進行操作。

    Struts2本身在其中放入的數據有ActionInvocation、application(即ServletContext)、conversionErrors、Locale、action的name、request的參數、HTTP的Session以及值棧等。完整的列表請參考它的Javadoc(本文附錄有對它包含內容的討論)。

    由于ActionContext的線程唯一和靜態方法就能獲得的特性,使得在非Action類中可以直接獲得它,而不需要等待Action傳入或注入。需要注意的是,它僅在由于request而創建的線程中有效(因為request時才創建對應的ActionContext),而在服務器啟動的線程中(比如fliter的init方法)無效。由于在非Action類中訪問其的方便性,ActionContext也可以用來在非Action類中向JSP傳遞數據(因為JSP也能很方便的訪問它)。

    ?

    ValueStack與ActionContext的聯系和區別:
    • 相同點:它們都是在一次HTTP請求的范圍內使用的,即它們的生命周期都是一次請求。
    • 不同點:值棧是棧的結構,ActionContext是映射(Map)的結構。
    • 聯系:ValueStack.getContext()方法得到的Map其實就是ActionContext的Map。查看Struts2的源代碼可知(Struts2.3.1.2的org.apache.struts2.dispatcher.ng.PrepareOperations的第79行,createActionContext方法),在創建ActionContext時,就是把ValueStack.getContext()作為ActionContext的構造函數的參數。所以,ValueStack和ActionContext本質上可以互相獲得。
    • 注意:在一些文檔中,會出現把對象存入“stack's context”的字樣,其實就是把值存入了ActionContext。所以在閱讀這些文檔時,要看清楚,到底是放入了棧結構(即值棧),還是映射結構(值棧的context,即ActionContext)。
    如何獲得ActionContext:
    • 在自定義的攔截器中:使用ActionInvocation.getInvocationContext()或者使用ActionContext.getContext()。
    • 在Action類中:讓攔截器注入或者使用ActionContext.getContext()。
    • 在非Action類中:讓Action類傳遞參數、使用注入機制注入或者使用ActionContext.getContext()。注意:只有運行在request線程中的代碼才能調用ActionContext.getContext(),否則返回的是null。
    • 在JSP中:一般不需要獲得ActionContext本身。
    如何向ActionContext中存入值:
    • 在攔截器、Action類、非Action類等Java類中:使用ActionContext.put(Object key, Object value)方法。
    • 在JSP中:標簽<s:set value="..."/>默認將值存入ActionContext中(當然,<s:set>標簽還可以把值存到其他地方)。另外,許多標簽都有var屬性(以前用的是id屬性,現在id屬性已被棄用),這個屬性能向ActionContext存入值,key為var屬性的值,value為標簽的value屬性的值。(有些文檔寫的是向ValueStack的context存入值,其實是一樣的)
    如何從ActionContext中讀取值:
    • 在攔截器、Action類、非Action類等Java類中:使用ActionContext.get(Object key)方法。
    • 在JSP中:使用#開頭的Ognl表達式,比如<s:property value="#name"/>會調用ActionContext.get("name")方法。注意:如果某標簽的屬性默認不作為Ognl表達式解析,則需要使用%{}把表達式括起來,于是就會出現類似“%{#name}的表達式”。(“#”的更多用途參見這里)
    總之,在JSP中使用ActionContext一方面是由于它是映射結構,另一方面是能讀取Action的一些配置。當你需要為許多Action提供通用的值的話,可以讓每個Action都提供getXXX()方法,但更好的方法是在攔截器或JSP模板中把這些通用的值存放到ActionContext中(因為攔截器或JSP模板往往通用于多個Action)。
    一些例子: View Code ?1?//?本類將演示攔截器中對ActionContext的操作???
    ?2?public?class?MyInterceptor?extends?AbstractInterceptor?{???
    ?3???
    ?4?????public?String?intercept(ActionInvocation?invocation)?throws?Exception?{???
    ?5?????????//?獲得ActionContext???
    ?6?????????ActionContext?actionContext?=?invocation.getInvocationContext();???
    ?7?????????//?存入值???
    ?8?????????Person?person?=?new?Person();???
    ?9?????????actionContext.put("person",?person);???
    10?????????//?獲取值???
    11?????????Object?value?=?actionContext.get("person");???
    12?????????//?獲取HttpServletRequest???
    13?????????HttpServletRequest?request?=?(HttpServletRequest)?actionContext.get(StrutsStatics.HTTP_REQUEST);???
    14?????????//?獲取request的Map,即HttpServletRequest.getAttribute(...)和HttpServletRequest.setAttribute(...)所操作的值??
    15?????????Map?requestMap?=?(Map)?actionContext.get("request");???
    16?????????//?其他代碼???
    17?????????//?......???
    18?????????return?invocation.invoke();???
    19?????}???
    20?}??

    ?

    ?

    View Code ?1?//?本類將演示在Action中對ActionContext進行操作???
    ?2?public?class?MyAction?extends?ActionSupport?{???
    ?3???
    ?4?????@Override??
    ?5?????public?String?execute()?throws?Exception?{???
    ?6?????????//?獲得值棧???
    ?7?????????ActionContext?actionContext?=?ActionContext.getContext();???
    ?8?????????//?存入值???
    ?9?????????Person?person?=?new?Person();//?這是之前例子中定義的類??
    10?????????actionContext.put("person",?person);???
    11?????????//?獲取值???
    12?????????Object?object?=?actionContext.get("person");???
    13?????????//?其他代碼???
    14?????????//?......???
    15?????????return?SUCCESS;???
    16?????}???
    17?}??

    ?

    ?

    View Code ?1?<!DOCTYPE?html>??
    ?2?<html>??
    ?3?????<head>??
    ?4?????????<meta?http-equiv="Content-Type"?content="text/html;?charset=UTF-8">??
    ?5?????????<title>JSP?Page</title>??
    ?6?????</head>??
    ?7?????<body>??
    ?8?????????<!--?本JSP將演示在JSP中對ActionContext的使用?-->??
    ?9?????????<!--?本JSP為MyAction對應的JSP?-->??
    10???
    11?????????<!--?由于Action中已經向ActionContext存入了key為"person"的值,所以可以使用“#person”來獲取它,如下??-->??
    12?????????<s:property?value="#person"/>??
    13?????????<!--?獲得person的name屬性,如下??-->??
    14?????????<s:property?value="#person.name"/>??
    15?????????<!--?獲得Struts2在ActionContext中存入的值,比如request的Map,如下??-->??
    16?????????<s:property?value="#request"/>??
    17?????????<!--?獲得Struts2在ActionContext中存入的值,比如session的Map,如下??-->??
    18?????????<s:property?value="#session"/>??
    19?????????<!--?獲得Struts2在ActionContext中存入的值,request請求傳遞的GET參數或POST參數的Map,如下??-->??
    20?????????<s:property?value="#parameters"/>??
    21????????????
    22?????????<!--?以下演示在JSP中把值存入ActionContext中??-->??
    23?????????<!--?存入一個字符串"myName",key為"myKey",如下?-->??
    24?????????<s:set?value="%{'myName'}"?var="myKey"/>??
    25?????????<!--?使用s:bean標簽來創建一個對象,并把它存入ActionContext中,key為myObject,如下??-->??
    26?????????<s:bean?name="com.example.Person"?var="myObject"/>??
    27?????????<!--?之后就可以用“#”來讀取它們,如下??-->??
    28?????????<s:property?value="#myKey"/>??
    29?????????<s:property?value="#myObject"/>??
    30?????</body>??
    31?</html>??

    ?

    3. HttpServletRequest類或request的Map

    Struts2中提供了兩種對request的操作:一種是Web服務器提供的HttpServletRequest類,這和傳統Java Web項目中的操作request的方式相同;另一種是一個“request的Map”,即封裝了HttpServletRequest的attributes的映射類,操作該Map相當于操作HttpServletRequest的attributes。之所以提供了Map的操作方式,一是方便操作,二是能方便使用Ognl在JSP標簽中讀取request。無論如何,這兩個request是互通的。至于request的生命周期等概念,與其他的Java Web項目沒有區別,本文不再詳述。

    ?

    使用HttpServletRequest類還是request的Map
    • 雖然兩者是互通的,但就讀取request的attributes而言,使用request的Map要方便許多,并且不會暴露不必要的接口。當然,HttpServletRequest有一些request的Map沒有的方法,使用這些方法時當然還是要用前者。
    使用request的Map還是ActionContext:
    • 兩者都是Map,兩者的生命周期都是一個請求。
    • 傳統的Java Web項目中,往往是通過request的attributes來向JSP傳遞值的:先在Servlet里setAttribute(),然后在JSP里getAttribute()。當然在Struts2的項目中,你仍然可以使用這個方法,然而拋棄了Struts2提供的傳遞功能是得不償失的。雖然筆者沒有找到官方文檔說一定要用ActionContext替換request的Map,也沒有發現程序中有能獲得ActionContext卻獲得不了request的Map的地方,但在Struts2框架下,操作ActionContext要比操作request的Map更加方便。因此,筆者建議:盡量使用ActionContext而不是request的Map來傳遞值。
    • request的Map有時候會包含其他框架設置的值,比如Spring框架。獲取這些值的時候就需要用request的Map了,因為ActionContext里沒有。
    • 通過ActionContext可以獲得HttpServletRequest類:“HttpServletRequest request = (HttpServletRequest) actionContext.get(StrutsStatics.HTTP_REQUEST);”。
    • 通過ActionContext也可以獲得request的Map:“Map requestMap = (Map) actionContext.get("request");”。因此,在JSP標簽中,使用表達式“#request”就可以獲得request的Map的數據。
    如何獲得HttpServletRequest:
    • 如果已經有ActionContext,則使用“actionContext.get(StrutsStatics.HTTP_REQUEST)”來獲得HttpServletRequest。
    • 在自定義的攔截器中,先獲得ActionContext,再通過ActionContext來獲得。
    • 在Action中,先獲得ActionContext,再通過ActionContext來獲得。或者讓Action實現ServletRequestAware接口,并使用ServletConfigInterceptor攔截器,這樣這個攔截器就會注入HttpServletRequest。
    • 在JSP中,一般不需要獲得HttpServletRequest。
    如何獲得request的Map:
    • 如果已經有ActionContext,則使用“actionContext.get("request")”來獲得。
    • 在自定義的攔截器中,先獲得 ActionContext,再通過ActionContext來獲得。
    • 在Action中,先獲得ActionContext,再通過ActionContext來獲得。或者讓Action實現RequestAware接口,并使用ServletConfigInterceptor攔截器,這樣這個攔截器就會注入Map request。
    • 在JSP中,用“#request”來獲得request的Map,用“#request.key”或者“#request['key']”來讀取Map中的值。

    總之,request仍然符合Java Web網站的一般規律。不過筆者建議使用者應盡量避免用request傳值。

    ?

    一些例子:

    ?

    View Code ?1?//?本類將演示攔截器中對HttpServletRequest和request的Map的操作???
    ?2?public?class?MyInterceptor?extends?AbstractInterceptor?{???
    ?3???
    ?4?????public?String?intercept(ActionInvocation?invocation)?throws?Exception?{???
    ?5?????????//?獲得ActionContext???
    ?6?????????ActionContext?actionContext?=?invocation.getInvocationContext();???
    ?7?????????//?獲得HttpServletRequest???
    ?8?????????HttpServletRequest?httpServletRequest=(HttpServletRequest)actionContext.get(StrutsStatics.HTTP_REQUEST);???
    ?9?????????//?獲得request的Map???
    10?????????Map?requestMap?=?(Map)?actionContext.get("request");???
    11?????????//?創建一個類作為實例???
    12?????????Person?person?=?new?Person();???
    13?????????//?以下兩行的語句作用相同???
    14?????????httpServletRequest.setAttribute("person",?person);???
    15?????????requestMap.put("person",?person);???
    16?????????//?其他代碼???
    17?????????//?......???
    18?????????return?invocation.invoke();???
    19?????}???
    20?}??

    ?

    ?

    View Code ?1?//?本類將演示在Action中對HttpServletRequest和request的Map進行操作(靜態方法獲得ActionContext)??
    ?2?public?class?MyAction?extends?ActionSupport?{???
    ?3???
    ?4?????@Override??
    ?5?????public?String?execute()?throws?Exception?{???
    ?6?????????//?獲得ActionContext???
    ?7?????????ActionContext?actionContext?=?ActionContext.getContext();???
    ?8?????????//?獲得HttpServletRequest???
    ?9?????????HttpServletRequest?httpServletRequest=(HttpServletRequest)actionContext.get(StrutsStatics.HTTP_REQUEST);???
    10?????????//?獲得request的Map???
    11?????????Map?requestMap?=?(Map)?actionContext.get("request");???
    12?????????//?創建一個類作為實例???
    13?????????Person?person?=?new?Person();???
    14?????????//?以下兩行的語句作用相同???
    15?????????httpServletRequest.setAttribute("person",?person);???
    16?????????requestMap.put("person",?person);???
    17?????????//?其他代碼???
    18?????????//?......???
    19?????????return?SUCCESS;???
    20?????}???
    21?}??

    ?

    ?

    ?

    View Code ?1?//?本類將演示在Action中使用ServletRequestAware獲得HttpServletRequest(注意:要使用ServletConfigInterceptor攔截器)??
    ?2?public?class?MyAction?extends?ActionSupport?implements?ServletRequestAware?{???
    ?3???
    ?4?????private?HttpServletRequest?request;???
    ?5????????
    ?6?????//此方法是接口ServletRequestAware的方法???
    ?7?????public?void?setServletRequest(HttpServletRequest?request)?{???
    ?8?????????this.request?=?request;???
    ?9?????}???
    10???
    11?????@Override??
    12?????public?String?execute()?throws?Exception?{???
    13?????????//?HttpServletRequest已在該類的字段中準備好,可直接使用??
    14?????????//?......???
    15?????????return?SUCCESS;???
    16?????}???
    17?}??

    ?

    ?

    View Code ?1?<!DOCTYPE?html>???
    ?2?<html>???
    ?3?????<head>???
    ?4?????????<meta?http-equiv="Content-Type"?content="text/html;?charset=UTF-8">???
    ?5?????????<title>JSP?Page</title>???
    ?6?????</head>???
    ?7?????<body>???
    ?8?????????<!--?本JSP將演示在JSP中對request的Map的使用?-->???
    ?9?????????<!--?本JSP為MyAction對應的JSP?-->???
    10???
    11?????????<!--?request的Map是Struts2自動在ActionContext中存入的值(key為request),所以使用“#”來訪問ActionContext,從中讀取request??-->???
    12?????????<s:property?value="#request"/>???
    13?????????<!--?以下兩行均是訪問request的Map中key為“name”的值??-->???
    14?????????<s:property?value="#request.name"/>???
    15?????????<s:property?value="#request['name']"/>???
    16?????</body>???
    17?</html>??

    ?

    View Code ?1?//?本類將演示在Action中使用ServletRequestAware獲得request的Map(注意:要使用ServletConfigInterceptor攔截器)??
    ?2?public?class?MyAction?extends?ActionSupport?implements?RequestAware?{???
    ?3???
    ?4?????Map<String,?Object>?request;???
    ?5???
    ?6?????//?該方法是接口RequestAware的方法???
    ?7?????public?void?setRequest(Map<String,?Object>?request)?{???
    ?8?????????this.request?=?request;???
    ?9?????}???
    10???
    11?????@Override??
    12?????public?String?execute()?throws?Exception?{???
    13?????????//?request的Map已在該類的字段中準備好,可直接使用???
    14?????????//?......???
    15?????????return?SUCCESS;???
    16?????}???
    17?}??

    ?

    ?

    3. Parameters,即GET請求或POST請求的參數

    Parameters為GET或POST等請求時瀏覽器向服務器傳遞而來的參數。在傳統的Java Web項目中,使用HttpServletRequest.getParameter()等方法來獲取參數,并且可以直接使用HttpServletRequest.getParameterMap()來獲得一個封裝了參數的Map。而在Struts2中,Struts2直接把上述Map存放到了ActionContext中,key為“parameters”。另外,ActionContext還直接提供了ActionContext.getParameters()方法來獲得這個Map。因此,在Struts2的各個部件中操作parameters的方法和操作request的Map的方法十分相似,本段不再詳述。

    ?

    4. HttpServletSession類和session的Map

    傳統Java Web項目中的session是我們都熟悉的,我們用它來記錄一個用戶的會話狀態。Struts2把HttpServletSession封裝到了一個Map中,即“session的Map”,這類似對request的處理。然而為了節省系統資源,我們在不需要session的時候不會創建session。可能正是因為這個緣故,Struts2中沒有把HttpServletSession放入ActionContext中,如果你的程序需要使用HttpServletSession,應該先獲得HttpServletRequest,然后使用getSession()或getSession(boolean b)來獲得它,同時決定是否需要創建session。對于session的Map,Struts2仍然把它放入了ActionContext中(key為"session"),但是不要擔心,這個Map的機制使得只有put新值時才會創建session。總之,Struts2中對HttpServletSession的操作要先通過HttpServletRequest來獲得它,而對session的Map的操作與對request的Map的操作如出一轍,本段不再詳述。

    ?

    5. ServletContext和application的Map

    傳統的Java Web項目中,ServletContext用來存放全局變量,每個Java虛擬機每個Web項目只有一個ServletContext。這個ServletContext是由Web服務器創建的,來保證它的唯一性。ServletContext有一些方法能操作它的attributes,這些操作方法和操作一個Map類似。于是,Struts2又來封裝了:它把ServletContext的attributes封裝到了一個Map中,即“application的Map”,并且也放入的ActionContext中(key為application),因此,對application的Map的操作就如果對request的Map操作,本段不再詳述。

    至于對ServletContext的操作,與HttpServletRequest的操作類似:Struts2將ServletContext放到了 ActionContext中,并且ServletConfigInterceptor提供了對ServletContext的注入接口ServletContextAware。因此,本段不再詳述。

    注意:在Ognl表達式中使用“#application”可以得到application的Map,而不是ServletContext。然而在JSP嵌入的Java代碼中(比如“<% application.getAttribute(""); %>”),application為ServletContext,而不是Map。

    ?

    用一張表格來總結:

    ?

    ?

    變量從ActionContext中獲得生命周期用Ongl來讀取值使用ServletConfigInterceptor來注入
    ActionContext類靜態方法ActionContext. getContext()一次Http請求使用“#”加上key,如“#name”無法注入
    ValueStack類ActionContext. getValueStack()一次Http請求直接填寫來訪問棧中對象的方法,或者使用top來直接獲得棧中對象無法注入
    HttpServletRequest類ActionContext. get( StrutsStatics. HTTP_REQUEST)一次Http請求無方便的方法實現ServletRequestAware接口
    request的MapActionContext. get("request")一次Http請求使用“#request”再加上key,如“#request.name”或者“#request['name']”實現RequestAware接口
    parameters的MapActionContext. get( "parameters")一次Http請求使用“# parameters”再加上key,如“#parameters .name”或者“#parameters ['name']”實現ParameterAware接口
    HttpServletSession類無(需通過HttpServletRequest來獲得)一次Http Session會話無方便的方法無法注入
    session的MapActionContext. get("session")每次請求創建,但在一次Http Session會話中數據都是一樣的使用“#session”再加上key,如“# session.name”或者“#session ['name']”實現SessionAware接口
    ServletContext類ActionContext. get( StrutsStatics. SERVLET_CONTEXT)網站項目啟動后一直存在且唯一無方便的方法使用ServletContextAware接口
    application的MapActionContext.get( "application")每次請求時創建,但其中的數據是網站項目啟動后一直存在且共享使用“# application”再加上key,如“#application .name”或者“#application ['name']”使用ApplicationAware接口

    ?

    附錄1 ActionContext中到底有哪些數據

    ?

    keykey的聲明處value的類型value.toString()

    com. opensymphony. xwork2. dispatcher.

    HttpServletRequest

    StrutsStatics. HTTP_REQUESTorg. apache. struts2. dispatcher. StrutsRequestWrapperorg. apache. struts2. dispatcher. StrutsRequestWrapper @10984e0
    applicationorg. apache. struts2. dispatcher. ApplicationMap
    com. opensymphony. xwork2. ActionContext. localeActionContext. LOCALEjava. util. Localezh_CN
    com. opensymphony. xwork2. dispatcher. HttpServletResponseStrutsStatics. HTTP_RESPONSEorg. apache. catalina. connector. ResponseFacadeorg. apache. catalina. connector. ResponseFacade @14ecfe8

    xwork. NullHandler.

    createNullObjects

    ?Booleanfalse
    com. opensymphony. xwork2. ActionContext. nameActionContext. ACTION_NAMEStringindex

    com.opensymphony. xwork2.ActionContext.

    conversionErrors

    ActionContext.

    CONVERSION_ERRORS

    java. util. HashMap{}
    com. opensymphony. xwork2. ActionContext. applicationActionContext. APPLICATIONorg. apache. struts2. dispatcher. ApplicationMap
    attrorg. apache. struts2. util. AttributeMaporg. apache. struts2. util. AttributeMap @133a2a8
    com. opensymphony. xwork2. ActionContext. containerActionContext. CONTAINERcom. opensymphony. xwork2. inject. ContainerImplcom. opensymphony. xwork2. inject. ContainerImpl @fc02c8
    com. opensymphony. xwork2. dispatcher. ServletContextStrutsStatics. SERVLET_CONTEXTorg. apache. catalina. core. ApplicationContextFacadeorg. apache. catalina. core. ApplicationContextFacade @11ad78c
    com. opensymphony. xwork2. ActionContext. sessionActionContext. SESSIONorg.apache.struts2. dispatcher.SessionMap{}

    com.opensymphony. xwork2.ActionContext.

    actionInvocation

    ActionContext. ACTION_INVOCATIONcom. opensymphony. xwork2. DefaultActionInvocationcom. opensymphony. xwork2. DefaultActionInvocation @13d4497
    xwork. MethodAccessor. denyMethodExecution筆者很懶,沒有找Booleanfalse
    report. conversion. errors筆者很懶,沒有找Booleanfalse
    sessionorg. apache. struts2. dispatcher. SessionMap{}
    com. opensymphony. xwork2. util. ValueStack. ValueStackValueStack.VALUE_STACKcom. opensymphony. xwork2. ognl. OgnlValueStackcom. opensymphony. xwork2. ognl. OgnlValueStack @16237fd
    requestorg. apache. struts2. dispatcher. RequestMap
    action筆者很懶,沒有找com. example. MyAction
    struts. actionMapping筆者很懶,沒有找org. apache. struts2. dispatcher. mapper. ActionMappingorg. apache. struts2. dispatcher. mapper. ActionMapping @892cc5
    parametersjava. util. HashMap{}
    com. opensymphony. xwork2. ActionContext. parametersActionContext.PARAMETERSjava. util. TreeMap{}

    ?

    注意:該表格為了排版在某些地方加了空格。

    ?

    可以看出,有些相同的對象被以不同的key多次設置到ActionContext中。如果想看看創建ActionContext的源代碼,請看org.apache.struts2.dispatcher.Dispatcher的serviceAction方法和兩個createContextMap方法。


    附錄2 Struts2標簽中value屬性直接對ActionContext訪問的問題

    經試驗并查看相關源代碼后發現,在使用<s:property value="..."/>時,該標簽的執行類會先根據value中表達式到值棧中執行表達式來查找值。如果在值棧中找到值,就返回該值;如果沒有找到,則把該表達式作為ActionContext的key,到ActionContext中去找值。比如<s:property value="request"/>也會得到ActionContext中的request,等價于<s:property value="#request"/>。但是,由于標簽的執行類會認為該值時String類型的,并且會直接進行類型轉換。于是,如果直接使用<s:property value="request"/>的話其實會讓頁面拋出異常:Request類型不能轉換成String類型。所以,只能用如果不帶#的話只能成功讀取ActionContext中String類型的值。這種機制使得某些時候棧頂的屬性可以覆蓋ActionContext中的key,或許你正需要它。然而,鑒于這種機制的不確定性,筆者建議訪問ActionContext中的數據一定要帶上“#”,可以免去一些麻煩。

    關于這種轉型異常,筆者認為是Struts2的bug,源代碼如下,當“value = getValue(expr, asType);”時,是考慮了asType的,但從context中讀取時“value = findInContext(expr);”,就沒有考慮asType,并且沒有在其他地方看到類型檢查操作:

    ?

    ?

    View Code ?1?//?本代碼截取Struts2.3.1.2版本com.opensymphony.xwork2.ognl.OgnlValueStack類的第340行-352行???
    ?2?????private?Object?tryFindValue(String?expr,?Class?asType)?throws?OgnlException?{??
    ?3?????????Object?value?=?null;??
    ?4?????????try?{??
    ?5?????????????expr?=?lookupForOverrides(expr);??
    ?6?????????????value?=?getValue(expr,?asType);??
    ?7?????????????if?(value?==?null)?{??
    ?8?????????????????value?=?findInContext(expr);??
    ?9?????????????}??
    10?????????}?finally?{??
    11?????????????context.remove(THROW_EXCEPTION_ON_FAILURE);??
    12?????????}??
    13?????????return?value;??
    14?????}??

    ?

    總結

    以上是生活随笔為你收集整理的在Struts2中使用ValueStack、ActionContext、ServletContext、request、session等的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。