(轉)ActionContext和ServletActionContext

來源:互聯網
上載者:User

標籤:

前面已經瞭解到ActionContext是Action執行時的上下文,裡面存放著Action在執行時需要用到的對象,我們也稱之為廣義值棧。

       Struts2在每次執行Action之前都會建立新的ActionContext,在同一個線程裡ActionContext裡面的屬性是唯一的,這樣Action就可以在多線程中使用。

1:ActionContext的執行緒安全性

       那麼Struts2是如何保證ActionContext的執行緒安全性呢?

       看看ActionContext對象的代碼,樣本如下:

?
1234 public class ActionContext implements Serializable {  static ThreadLocal actionContext = new ThreadLocal();  ……  }



ThreadLocal又稱為“線程局部變數”,它為每一個使用該變數的線程都提供一個變數值的副本,使每一個線程都可以獨立地改變自己的副本,而不會和其它線程的副本衝突。

存放在ActionContext裡的資料都存放在這個ThreadLocal的屬性中,而這個屬性只會在對應的當前請求線程中可見,從而保證資料是安全執行緒的。

2:訪問的是Map

回顧前面在使用ActionContext來訪問Session中資料的程式,你會發現,其實在程式裡面訪問的是一個Map,而非HttpSession對象,這是為什麼呢?

       原來,Struts2架構將與Web相關的很多個物件重新進行了封裝,比如將HttpSession對象重新封裝成了一個Map對象,裡面存放著Session中的資料,提供這個Map給Action使用,而不用Action直接和底層的HttpSession打交道。也正是因為架構的封裝,讓Action可以完全的和Web層解耦。

       但是要注意一點,ActionContext不能在普通的Java應用程式中使用。

在以前的學習中,介紹了Action和Servlet API是解耦的,因此可以在Java應用程式中調用Action的execute方法來進行測試。但是如果使用了ActionContext來擷取session資料,那麼就不能這樣運行了。因為ActionContext封裝的都是Web的資料,在Java應用程式中啟動並執行時候,沒有Web的環境和響應的資料,因而會拋出null 指標的異常。

訪問其它的Web對象的值也是與此類似的,你通過ActionContext去訪問的都是封裝後的Map。

3:使用SessionAware介面

Struts2還提供另外一種簡單的方式,使用SessionAware介面來訪問儲存於ActionContext中的資料,該介面通過使用IoC/DI來為Action注入Session Map,就可以在程式裡面直接使用這個Map來操作資料了。

 (1)在Action中不再需要訪問ActionContext了,取而代之,Action實現SessionAware介面,該介面告知Struts2在Action執行之前要設定Session Map,是通過servletConfig 攔截器來實現的,這個攔截器在defaultStack裡面就有。範例程式碼如下:

?
123456789101112 public class OgnlAction extends ActionSupport implements SessionAware{      private Map<String, Object> session;      @Resource    public void setSession(Map<String, Object> session) {          this.session = session;                 public String execute(){          session.put("sessionTestKey", "測試SessionAware");          return this.SUCCESS;      }



在上面的代碼中:

  • Action類實現SessionAware介面
  • 這個介面要求Action類實現一個方法setSession(Map<String, Object> session),通過這個方法注入Session的資料
  • 在execute方法中,通過這個私人屬性就可以操作會話中的資料,注意一點,這個Map中的值也是與HttpSession聯動的。


為了能夠在普通的Java應用中運行並測試Action,推薦大家使用SessionAware的方式來訪問HttpSession。因為這樣一來,在通過main方法運行或測試的時候,可以直接調用setSession方法,傳入類比的會話資料,就不會出現execute方法中拋出null 指標的異常了。

       因此,推薦大家使用SessionAware的方式來訪問HttpSession。

4:使用其它封裝介面

跟SessionAware類似,你可以使用RequestAware來擷取封裝請求對象的attribute中的值的Map;使用ApplicationAware來擷取封裝ServletContext對象的attribute中的值的Map;使用ParameterAware來擷取封裝請求對象的參數中的值的Map,等等,這裡只羅列這幾個常見和常用的,還有更多的請參見Struts2的API文檔。



在實際應用開發中,光是擷取資料就夠了嗎?答案顯然是否定的,有些時候,根據功能需要,在Action中必須要能擷取到Servlet相關的API,比如要操作Cookie。這個時候,就需要用ServletActionContext了。

1:ServletActionContext概述

這個類直接繼承了ActionContext,當然也繼承了它父類的很多功能,比如:對OgnlValueStack、Action名字等的訪問。更重要的是,它還提供了直接存取Servlet的相關對象的功能,它可以取得的對象有:

  • HttpServletRequest:請求對象
  • HttpServletResponse:響應對象
  • ServletContext:Servlet上下文資訊
  • PageContext:Http頁面上下文


2:基本使用

       直接使用ServletActionContext的靜態方法就可以擷取到相應的對象。樣本如下:

 

java代碼:?
12345 HttpServletRequest request = ServletActionContext.getRequest();  HttpServletResponse response = ServletActionContext.getResponse();  ServletContext servletContext = ServletActionContext.getServletContext();  PageContext pageContext = ServletActionContext.getPageContext();  HttpSession session = ServletActionContext.getRequest().getSession();


這裡要注意的是HttpSession對象的擷取,是在取得HttpRequest對象過後,通過HttpRequest對象來擷取會話對象。當然,取得相應的對象後,就直接使用這些對象的方法來進行開發,這裡就不去贅述了。

3:通過IoC/DI的方式來擷取相應的Servlet對象

       還可以通過IoC/DI的方式來擷取相應的Servlet對象,對應關係是:

  • ServletRequestAware:通過這個介面來擷取HttpServletRequest對象
  • ServletResponseAware:通過這個介面來擷取HttpServletResponse對象

用ServletRequestAware來樣本一下。

(1)修改Action,讓其實現ServletRequestAware介面,範例程式碼如下:

 java代碼:

?
12345678910111213 public class OgnlAction extends ActionSupport implements ServletRequestAware{      private HttpServletRequest request = null    @Resource    public void setServletRequest(HttpServletRequest request) {          this.request = request;                 public String execute(){                  request.setAttribute("request", "Request的屬性值");          request.getSession().setAttribute("sessionTestKey", "測試SessionAware");          return this.SUCCESS;      }     }



 


ActionContext和ServletActionContext

根據前面的講述,你會發現,ActionContext和ServletActionContext有著一些重複的功能,都能夠擷取到Web對象的資料,但是又有些不同。

       通常情況下,可以這麼認為:ActionContext主要負責值的操作;ServletActionContext主要負責擷取Servlet對象。

那麼在Action中,該如何去抉擇呢?建議的原則是:

  • 優先使用ActionContext
  • 只有ActionContext不能滿足功能要求的時候,才使用ServletActionContext

總之,要盡量讓Action與Web無關,這對於Action的測試和複用都是極其有好處的。

       另外還有一點需要注意:在使用ActionContext時,不要在Action的建構函式裡使用ActionContext.getContext(),因為這個時候ActionContext裡的一些值也許還沒有設定,這時通過ActionContext取得的值也許是null。

(轉)ActionContext和ServletActionContext

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.