国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Java > 正文

Struts2 ActionContext 中的數(shù)據(jù)詳解

2019-11-26 14:02:52
字體:
供稿:網(wǎng)友

ActionContext

    ActionContext是Action的上下文,Struts2自動(dòng)在其中保存了一些在Action執(zhí)行過程中所需的對(duì)象,比如session, parameters, locale等。Struts2會(huì)根據(jù)每個(gè)執(zhí)行HTTP請(qǐng)求的線程來創(chuàng)建對(duì)應(yīng)的ActionContext,即一個(gè)線程有一個(gè)唯一的ActionContext。因此,使用者可以使用靜態(tài)方法ActionContext.getContext()來獲取當(dāng)前線程的ActionContext,也正是由于這個(gè)原因,使用者不用去操心讓Action是線程安全的。

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

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

    由于ActionContext的線程唯一和靜態(tài)方法就能獲得的特性,使得在非Action類中可以直接獲得它,而不需要等待Action傳入或注入。需要注意的是,它僅在由于request而創(chuàng)建的線程中有效(因?yàn)閞equest時(shí)才創(chuàng)建對(duì)應(yīng)的ActionContext),而在服務(wù)器啟動(dòng)的線程中(比如fliter的init方法)無效。由于在非Action類中訪問其的方便性,ActionContext也可以用來在非Action類中向JSP傳遞數(shù)據(jù)(因?yàn)镴SP也能很方便的訪問它)。

   ValueStack與ActionContext的聯(lián)系和區(qū)別:

相同點(diǎn):它們都是在一次HTTP請(qǐng)求的范圍內(nèi)使用的,即它們的生命周期都是一次請(qǐng)求。
不同點(diǎn):值棧是棧的結(jié)構(gòu),ActionContext是映射(Map)的結(jié)構(gòu)。
聯(lián)系:ValueStack.getContext()方法得到的Map其實(shí)就是ActionContext的Map。查看Struts2的源代碼可知(Struts2.3.1.2的org.apache.struts2.dispatcher.ng.PrepareOperations的第79行,createActionContext方法),在創(chuàng)建ActionContext時(shí),就是把ValueStack.getContext()作為ActionContext的構(gòu)造函數(shù)的參數(shù)。所以,ValueStack和ActionContext本質(zhì)上可以互相獲得。
注意:在一些文檔中,會(huì)出現(xiàn)把對(duì)象存入“stack's context”的字樣,其實(shí)就是把值存入了ActionContext。所以在閱讀這些文檔時(shí),要看清楚,到底是放入了棧結(jié)構(gòu)(即值棧),還是映射結(jié)構(gòu)(值棧的context,即ActionContext)。

如何獲得ActionContext:

在自定義的攔截器中:使用ActionInvocation.getInvocationContext()或者使用ActionContext.getContext()。
在Action類中:讓攔截器注入或者使用ActionContext.getContext()。
在非Action類中:讓Action類傳遞參數(shù)、使用注入機(jī)制注入或者使用ActionContext.getContext()。注意:只有運(yùn)行在request線程中的代碼才能調(diào)用ActionContext.getContext(),否則返回的是null。
在JSP中:一般不需要獲得ActionContext本身。

    如何向ActionContext中存入值:

在攔截器、Action類、非Action類等Java類中:使用ActionContext.put(Object key, Object value)方法。
在JSP中:標(biāo)簽<s:set value="..."/>默認(rèn)將值存入ActionContext中(當(dāng)然,<s:set>標(biāo)簽還可以把值存到其他地方)。另外,許多標(biāo)簽都有var屬性(以前用的是id屬性,現(xiàn)在id屬性已被棄用),這個(gè)屬性能向ActionContext存入值,key為var屬性的值,value為標(biāo)簽的value屬性的值。(有些文檔寫的是向ValueStack的context存入值,其實(shí)是一樣的)

    如何從ActionContext中讀取值:

在攔截器、Action類、非Action類等Java類中:使用ActionContext.get(Object key)方法。
在JSP中:使用#開頭的Ognl表達(dá)式,比如<s:property value="#name"/>會(huì)調(diào)用ActionContext.get("name")方法。注意:如果某標(biāo)簽的屬性默認(rèn)不作為Ognl表達(dá)式解析,則需要使用%{}把表達(dá)式括起來,于是就會(huì)出現(xiàn)類似“%{#name}的表達(dá)式”。(“#”的更多用途參見這里)

    總之,在JSP中使用ActionContext一方面是由于它是映射結(jié)構(gòu),另一方面是能讀取Action的一些配置。當(dāng)你需要為許多Action提供通用的值的話,可以讓每個(gè)Action都提供getXXX()方法,但更好的方法是在攔截器或JSP模板中把這些通用的值存放到ActionContext中(因?yàn)閿r截器或JSP模板往往通用于多個(gè)Action)。
 
    一些例子:

Java代碼

// 本類將演示攔截器中對(duì)ActionContext的操作  publicclass MyInterceptor extends AbstractInterceptor {     public String intercept(ActionInvocation invocation) throws Exception {      // 獲得ActionContext      ActionContext actionContext = invocation.getInvocationContext();      // 存入值      Person person = new Person();      actionContext.put("person", person);      // 獲取值      Object value = actionContext.get("person");      // 獲取HttpServletRequest      HttpServletRequest request = (HttpServletRequest) actionContext.get(StrutsStatics.HTTP_REQUEST);      // 獲取request的Map,即HttpServletRequest.getAttribute(...)和HttpServletRequest.setAttribute(...)所操作的值     Map requestMap = (Map) actionContext.get("request");      // 其他代碼      // ......      return invocation.invoke();    }  } 

Java代碼

// 本類將演示在Action中對(duì)ActionContext進(jìn)行操作  publicclass MyAction extends ActionSupport {     @Override   public String execute() throws Exception {      // 獲得值棧      ActionContext actionContext = ActionContext.getContext();      // 存入值      Person person = new Person();// 這是之前例子中定義的類     actionContext.put("person", person);      // 獲取值      Object object = actionContext.get("person");      // 其他代碼      // ......      return SUCCESS;    }  } 

Html代碼

<!DOCTYPE html> <html>   <head>     <metahttp-equiv="Content-Type"content="text/html; charset=UTF-8">     <title>JSP Page</title>   </head>   <body>     <!-- 本JSP將演示在JSP中對(duì)ActionContext的使用 -->     <!-- 本JSP為MyAction對(duì)應(yīng)的JSP -->      <!-- 由于Action中已經(jīng)向ActionContext存入了key為"person"的值,所以可以使用“#person”來獲取它,如下 -->     <s:propertyvalue="#person"/>     <!-- 獲得person的name屬性,如下 -->     <s:propertyvalue="#person.name"/>     <!-- 獲得Struts2在ActionContext中存入的值,比如request的Map,如下 -->     <s:propertyvalue="#request"/>     <!-- 獲得Struts2在ActionContext中存入的值,比如session的Map,如下 -->     <s:propertyvalue="#session"/>     <!-- 獲得Struts2在ActionContext中存入的值,request請(qǐng)求傳遞的GET參數(shù)或POST參數(shù)的Map,如下 -->     <s:propertyvalue="#parameters"/>           <!-- 以下演示在JSP中把值存入ActionContext中 -->     <!-- 存入一個(gè)字符串"myName",key為"myKey",如下 -->     <s:setvalue="%{'myName'}"var="myKey"/>     <!-- 使用s:bean標(biāo)簽來創(chuàng)建一個(gè)對(duì)象,并把它存入ActionContext中,key為myObject,如下 -->     <s:beanname="com.example.Person"var="myObject"/>     <!-- 之后就可以用“#”來讀取它們,如下 -->     <s:propertyvalue="#myKey"/>     <s:propertyvalue="#myObject"/>   </body> </html> 

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

使用HttpServletRequest類還是request的Map

雖然兩者是互通的,但就讀取request的attributes而言,使用request的Map要方便許多,并且不會(huì)暴露不必要的接口。當(dāng)然,HttpServletRequest有一些request的Map沒有的方法,使用這些方法時(shí)當(dāng)然還是要用前者。

使用request的Map還是ActionContext:

兩者都是Map,兩者的生命周期都是一個(gè)請(qǐng)求。
傳統(tǒng)的Java Web項(xiàng)目中,往往是通過request的attributes來向JSP傳遞值的:先在Servlet里setAttribute(),然后在JSP里getAttribute()。當(dāng)然在Struts2的項(xiàng)目中,你仍然可以使用這個(gè)方法,然而拋棄了Struts2提供的傳遞功能是得不償失的。雖然筆者沒有找到官方文檔說一定要用ActionContext替換request的Map,也沒有發(fā)現(xiàn)程序中有能獲得ActionContext卻獲得不了request的Map的地方,但在Struts2框架下,操作ActionContext要比操作request的Map更加方便。因此,筆者建議:盡量使用ActionContext而不是request的Map來傳遞值。
request的Map有時(shí)候會(huì)包含其他框架設(shè)置的值,比如Spring框架。獲取這些值的時(shí)候就需要用request的Map了,因?yàn)锳ctionContext里沒有。
通過ActionContext可以獲得HttpServletRequest類:“HttpServletRequest request = (HttpServletRequest) actionContext.get(StrutsStatics.HTTP_REQUEST);”。
通過ActionContext也可以獲得request的Map:“Map requestMap = (Map) actionContext.get("request");”。因此,在JSP標(biāo)簽中,使用表達(dá)式“#request”就可以獲得request的Map的數(shù)據(jù)。

如何獲得HttpServletRequest:

如果已經(jīng)有ActionContext,則使用“actionContext.get(StrutsStatics.HTTP_REQUEST)”來獲得HttpServletRequest。
在自定義的攔截器中,先獲得ActionContext,再通過ActionContext來獲得。
在Action中,先獲得ActionContext,再通過ActionContext來獲得。或者讓Action實(shí)現(xiàn)ServletRequestAware接口,并使用ServletConfigInterceptor攔截器,這樣這個(gè)攔截器就會(huì)注入HttpServletRequest。
在JSP中,一般不需要獲得HttpServletRequest。

如何獲得request的Map:

如果已經(jīng)有ActionContext,則使用“actionContext.get("request")”來獲得。
在自定義的攔截器中,先獲得 ActionContext,再通過ActionContext來獲得。
在Action中,先獲得ActionContext,再通過ActionContext來獲得。或者讓Action實(shí)現(xiàn)RequestAware接口,并使用ServletConfigInterceptor攔截器,這樣這個(gè)攔截器就會(huì)注入Map request。
在JSP中,用“#request”來獲得request的Map,用“#request.key”或者“#request['key']”來讀取Map中的值。

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

一些例子:

// 本類將演示攔截器中對(duì)HttpServletRequest和request的Map的操作  publicclass MyInterceptor extends AbstractInterceptor {     public String intercept(ActionInvocation invocation) throws Exception {      // 獲得ActionContext      ActionContext actionContext = invocation.getInvocationContext();      // 獲得HttpServletRequest      HttpServletRequest httpServletRequest=(HttpServletRequest)actionContext.get(StrutsStatics.HTTP_REQUEST);      // 獲得request的Map      Map requestMap = (Map) actionContext.get("request");      // 創(chuàng)建一個(gè)類作為實(shí)例      Person person = new Person();      // 以下兩行的語句作用相同      httpServletRequest.setAttribute("person", person);      requestMap.put("person", person);      // 其他代碼      // ......      return invocation.invoke();    }  } 
// 本類將演示在Action中對(duì)HttpServletRequest和request的Map進(jìn)行操作(靜態(tài)方法獲得ActionContext) publicclass MyAction extends ActionSupport {     @Override   public String execute() throws Exception {      // 獲得ActionContext      ActionContext actionContext = ActionContext.getContext();      // 獲得HttpServletRequest      HttpServletRequest httpServletRequest=(HttpServletRequest)actionContext.get(StrutsStatics.HTTP_REQUEST);      // 獲得request的Map      Map requestMap = (Map) actionContext.get("request");      // 創(chuàng)建一個(gè)類作為實(shí)例      Person person = new Person();      // 以下兩行的語句作用相同      httpServletRequest.setAttribute("person", person);      requestMap.put("person", person);      // 其他代碼      // ......      return SUCCESS;    }  } 
// 本類將演示在Action中使用ServletRequestAware獲得HttpServletRequest(注意:要使用ServletConfigInterceptor攔截器) publicclass MyAction extends ActionSupport implements ServletRequestAware {     private HttpServletRequest request;        //此方法是接口ServletRequestAware的方法    publicvoid setServletRequest(HttpServletRequest request) {      this.request = request;    }     @Override   public String execute() throws Exception {      // HttpServletRequest已在該類的字段中準(zhǔn)備好,可直接使用     // ......      return SUCCESS;    }  } 
// 本類將演示在Action中使用ServletRequestAware獲得request的Map(注意:要使用ServletConfigInterceptor攔截器) publicclass MyAction extends ActionSupport implements RequestAware {     Map<String, Object> request;     // 該方法是接口RequestAware的方法    publicvoid setRequest(Map<String, Object> request) {      this.request = request;    }     @Override   public String execute() throws Exception {      // request的Map已在該類的字段中準(zhǔn)備好,可直接使用      // ......      return SUCCESS;    }  } 
<!DOCTYPE html>  <html>    <head>      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">      <title>JSP Page</title>    </head>    <body>      <!-- 本JSP將演示在JSP中對(duì)request的Map的使用 -->      <!-- 本JSP為MyAction對(duì)應(yīng)的JSP -->       <!-- request的Map是Struts2自動(dòng)在ActionContext中存入的值(key為request),所以使用“#”來訪問ActionContext,從中讀取request -->      <s:property value="#request"/>      <!-- 以下兩行均是訪問request的Map中key為“name”的值 -->      <s:property value="#request.name"/>      <s:property value="#request['name']"/>    </body>  </html> 

3. Parameters,即GET請(qǐng)求或POST請(qǐng)求的參數(shù)

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

4. HttpServletSession類和session的Map

傳統(tǒng)Java Web項(xiàng)目中的session是我們都熟悉的,我們用它來記錄一個(gè)用戶的會(huì)話狀態(tài)。Struts2把HttpServletSession封裝到了一個(gè)Map中,即“session的Map”,這類似對(duì)request的處理。然而為了節(jié)省系統(tǒng)資源,我們?cè)诓恍枰猻ession的時(shí)候不會(huì)創(chuàng)建session。可能正是因?yàn)檫@個(gè)緣故,Struts2中沒有把HttpServletSession放入ActionContext中,如果你的程序需要使用HttpServletSession,應(yīng)該先獲得HttpServletRequest,然后使用getSession()或getSession(boolean b)來獲得它,同時(shí)決定是否需要?jiǎng)?chuàng)建session。對(duì)于session的Map,Struts2仍然把它放入了ActionContext中(key為"session"),但是不要擔(dān)心,這個(gè)Map的機(jī)制使得只有put新值時(shí)才會(huì)創(chuàng)建session。總之,Struts2中對(duì)HttpServletSession的操作要先通過HttpServletRequest來獲得它,而對(duì)session的Map的操作與對(duì)request的Map的操作如出一轍,本段不再詳述。

5. ServletContext和application的Map

傳統(tǒng)的Java Web項(xiàng)目中,ServletContext用來存放全局變量,每個(gè)Java虛擬機(jī)每個(gè)Web項(xiàng)目只有一個(gè)ServletContext。這個(gè)ServletContext是由Web服務(wù)器創(chuàng)建的,來保證它的唯一性。ServletContext有一些方法能操作它的attributes,這些操作方法和操作一個(gè)Map類似。于是,Struts2又來封裝了:它把ServletContext的attributes封裝到了一個(gè)Map中,即“application的Map”,并且也放入的ActionContext中(key為application),因此,對(duì)application的Map的操作就如果對(duì)request的Map操作,本段不再詳述。
至于對(duì)ServletContext的操作,與HttpServletRequest的操作類似:Struts2將ServletContext放到了 ActionContext中,并且ServletConfigInterceptor提供了對(duì)ServletContext的注入接口ServletContextAware。因此,本段不再詳述。
注意:在Ognl表達(dá)式中使用“#application”可以得到application的Map,而不是ServletContext。然而在JSP嵌入的Java代碼中(比如“<% application.getAttribute(""); %>”),application為ServletContext,而不是Map。

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 定安县| 同江市| 汤阴县| 阿尔山市| 昆山市| 四子王旗| 攀枝花市| 古田县| 淮滨县| 云龙县| 江源县| 青冈县| 鄂托克前旗| 五常市| 如皋市| 扎赉特旗| 潞城市| 株洲市| 余庆县| 乌兰察布市| 屏东县| 喜德县| 五常市| 隆安县| 葫芦岛市| 鄂托克前旗| 汤原县| 资兴市| 景东| 赣州市| 高雄县| 民和| 吴忠市| 沁源县| 青龙| 武胜县| 柘城县| 呼图壁县| 施秉县| 元氏县| 老河口市|