Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> struts2的Action(四)

struts2的Action(四)

編輯:關於Android編程

實現Action

Action是struts2應用的核心,開發中需要大量的Action類,並在struts.xml中配置Action。Action中包含了對用戶請求的處理邏輯,Action類也被稱為業務控制邏輯器。

struts2采用低侵入式設計,它不要求Action類繼承任何的struts的基類或者實現任何struts接口。struts2的Action類是普通的POJO類(通常應該帶一個無參的方法),從而有很好的代碼復用性。

struts2通常直接使用Action來封裝HTTP參數,因此,Action類還應該包含於請求參數對應的實例變量,並且為這些實例變量提供相應的setter和getter方法。

比如用戶請求包含productName和productDesc兩個請求參數,Action類應該提供productName和productDesc兩個實例變量來封裝用戶請求參數,並且為productName和productDesc提供對應的setter和getter方法。下面是處理該請求的Action類的代碼片段:

//處理用戶請求的Action類,只是一個POJO,無需繼承任何基類,或實現任何接口
public class Product {
    //提供實例變量來封裝HTTP請求參數
    private Integer productId;
    private String productName;
    private String productDesc;
    private double productPrice;
    //相應的setter和getter方法
    public Integer getProductId() {
        return productId;
    }

    public void setProductId(Integer productId) {
        this.productId = productId;
    }

    public String getProductName() {
        return productName;
    }

    public void setProductName(String productName) {
        this.productName = productName;
    }

    public String getProductDesc() {
        return productDesc;
    }

    public void setProductDesc(String productDesc) {
        this.productDesc = productDesc;
    }

    public double getProductPrice() {
        return productPrice;
    }

    public void setProductPrice(double productPrice) {
        this.productPrice = productPrice;
    }
    //Action類默認處理用戶請求的方法:execute方法
    public String execute(){
       ...
       //返回處理結果字符串
       return resultStr;
    }


雖然Action需要處理的請求包含productName和productDesc等HTTP請求參數,Action類也可以不包含它們對應的實例變量。因為系統是通過對應的setter和getter方法來處理請求參數的,而不是通過實例變量來處理請求參數的。即Action類裡包含對應實例變量與否不重要,重要的是需要包含void setProductName(String productName)和String getProductName()方法。

Action類裡的實例變量不僅可以用來封裝請求參數,還可以用來封裝處理結果。如果希望將服務器提示的“注冊成功”或其他信息在下一個頁面輸出,就可以在Action類中增加一個tip實例變量,並為之提供對應setter和getter方法,

//封裝服務提示的tip實例變量
private String tip;
//tip對應的setter和getter方法
public String getTip(){
   return tip;
}
pubic void setTip(String tip){
   this.tip = tip;
}
//Action包含的注冊控制邏輯
public String register() throws Exception{
   ActionContext.getContext().getSession().put("user",getUsername());
   setTip("歡迎你!" + getUsername() + "你已經注冊成功!");
   return SUCCESS;
}

可以在下一個頁面中使用struts2標簽來輸出該實例變量的值。加載JSP頁面中輸出tip實例變量值得代碼片段如下:


系統不嚴格區分Action裡哪個實例變量用於封裝請求參數,哪個實例變量用於封裝處理結果。如果用戶的HTTP請求包含名為tip的請求參數,則系統會調用void setTip(String tip)方法,通過這種方式,名為tip的請求參數就可以傳給Action實例;如果Action類裡沒有包含對應的方法,則名為tip的請求參數將無法傳入該Action。

在JSP頁面中輸出Action的實例變量值時,也不區分該實例變量是用於封裝請你參數還是處理結果。因此,struts2標簽既可以輸出Action的處理結果也可以輸出HTTP請求參數值。

Action接口和Action基類

為規范Action類開發,struts2提供了一個Action接口,給接口定義了struts2的Action處理類應該實現的規范:

public interface Action {
    //定義Action接口裡包含的一些結果字符串
    public static final String SUCCESS = "success";

    public static final String NONE = "none";

    public static final String ERROR = "error";

    public static final String INPUT = "input";

    public static final String LOGIN = "login";
    //定義處理用戶請求的execute方法
    public String execute() throws Exception;

}


Action接口裡定義了一個execute方法,該接口的規范定義了Action類應該包含一個execute方法,該方法返回一個字符串。該接口還定義了5個字符串常量,用於統一execute方法的返回值。一般Action類處理用戶請求後,有人喜歡返回welcome字符串,有人喜歡返回success字符竄… …這樣不利於統一關聯,故Action接口定義了這5個字符串常量:ERROR、
INPUT、LOGIN和SUCCESS,分別代表特定含義。但是,如果開發者希望用自己的字符串作為邏輯視圖名,還是可以被允許的,但這並不利用後期維護。

struts2還為Action接口提供一個實現類ActionSupport,其包含相關方法等見圖

這裡寫圖片描述這裡寫圖片描述

AcitonSupport是個默認的Action實現類,該類裡有很多默認方法,包括獲取國際化信息的方法、數據校驗的方法、默認的處理用戶請求的方法等。它是struts2默認的Action處理類,如果讓開發者的Action處理類繼承ActionSuppZ喎?/kf/ware/vc/" target="_blank" class="keylink">vcnTA4KOsu+G087TzvPK7r0FjdGlvbrXEv6q3oqGjPGJyIC8+DQo8YnIgLz4NCkFjdGlvbrfDzspTZXJ2bGV0IEFQSTxiciAvPg0KPGJyIC8+DQpzdHJ1dHMytcRBY3Rpb27Du9PQ0+vIzrrOU2VydmxldCBBUEnx7rrPo6y007b4xNzH4cvJtdiy4srUuMNBY3Rpb26ho7WrysdXZWLTptPDtcS/2NbGxve+rbOjtrzKx9Kqx/O3w87KU2VydmxldCBBUEm1xKOswP3I57j619lIVFRQU2Vzc2lvbte0zKy1yKOszaizo1dlYtOm08PSqrfDzsq1xFNlcnZsZXQgQVBJ09BIdHRwU2VydmxldFJlcXVlc3Shokh0dHBTZXNzaW9uoaJTZXJ2bGV0Q29udGV4dLXIo6zV4sj9uPa907/at9ax8LT6se1KU1DE2tbDttTP89bQtcRyZXF1ZXN0oaJzZXNzaW9uus1hcHBsaWNhdGlvbqGjPGJyIC8+DQo8YnIgLz4NCjxzdHJvbmc+0+tTZXJ2bGV0IEFQSb3i8e61xLfDzsq3vcq9PC9zdHJvbmc+IDo8YnIgLz4NCjxiciAvPg0KzqrBy7Hcw+LT6yBTZXJ2bGV0IEFQSSDx7rrP1NrSu8bwLCC3vbHjIEFjdGlvbiDX9rWl1Kqy4srULCBTdHJ1dHMyILbUIEh0dHBTZXJ2bGV0UmVxdWVzdCwgSHR0cFNlc3Npb24gus0gU2VydmxldENvbnRleHQgvfjQ0MHLt+LXsCwgubnU7MHLIDMguPYgTWFwILbUz/PAtMzmtPrV4iAzILj2ttTP8ywg1NogQWN0aW9uINbQv8nS1NaxvdPKudPDIEh0dHBTZXJ2bGV0UmVxdWVzdCwgSHR0cFNlcnZsZXRTZXNzaW9uLCBTZXJ2bGV0Q29udGV4dCC21NOmtcQgTWFwILbUz/PAtLGjtOa6zbbByKHK/b7dLjxiciAvPg0KPGJyIC8+DQpzdHJ1dHMyzOG5qcHLPHN0cm9uZz5BY3Rpb25Db250ZXh0wOA8L3N0cm9uZz6jrEFjdGlvbkNvbnRleHQgyscgQWN0aW9uINa00NC1xMnPz8LOxLbUz/MsINTaIEFjdGlvbkNvbnRleHQg1tCxo7TmwcsgQWN0aW9uINa00NDL+dDo0qq1xMv509C21M/zLCCw/MCoIHBhcmFtZXRlcnMsIHJlcXVlc3QsIHNlc3Npb24sIGFwcGxpY2F0aW9uILXILjxiciAvPg0KPGJyIC8+DQq78cihIEh0dHBTZXNzaW9uILbU06a1xCBNYXAgttTP8zo8YnIgLz4NCnB1YmxpYyBNYXAgZ2V0U2Vzc2lvbigpPGJyIC8+DQq78cihIFNlcnZsZXRDb250ZXh0ILbU06a1xCBNYXAgttTP8zo8YnIgLz4NCnB1YmxpYyBNYXAgZ2V0QXBwbGljYXRpb24oKTxiciAvPg0Ku/HIocfrx/Oyzsr9ttTTprXEIE1hcCC21M/zOjxiciAvPg0KcHVibGljIE1hcCBnZXRQYXJhbWV0ZXJzKCk8YnIgLz4NCrvxyKEgSHR0cFNlcnZsZXRSZXF1ZXN0ILbU06a1xCBNYXAgttTP8zo8YnIgLz4NCnB1YmxpYyBPYmplY3QgZ2V0KE9iamVjdCBrZXkpOiBBY3Rpb25Db250ZXh0IMDg1tDDu9PQzOG5qcDgy8YgZ2V0UmVxdWVzdCgpINXi0fm1xLe9t6jAtLvxyKEgSHR0cFNlcnZsZXRSZXF1ZXN0ILbU06a1xCBNYXAgttTP8y4g0qq1w7W9IEh0dHBTZXJ2bGV0UmVxdWVzdCC21NOmtcQgTWFwILbUz/MsIL/J0tTNqLn9zqogZ2V0KCkgt723qLSrtd0gJmxkcXVvO3JlcXVlc3QmcmRxdW87ILLOyv3Ktc/WoaM8YnIgLz4NCjxiciAvPg0KzerV+7e9t6jI58/Co7o8YnIgLz4NCjxiciAvPg0KPGltZyBhbHQ9"這裡寫圖片描述" src="/uploadfile/Collfiles/20160427/201604270934291090.png" title="\" />

與 Servlet 耦合的訪問方式:

用ActionContext訪問Servlet API不是直接獲得Servlet API的實例。為在Action中直接訪問Servlet API,struts2提供如下接口:

">ServletContextAware:實現該接口的Action可以直接訪問Web應用的ServletContext實例。
|>ServletRequestAware:實現該接口的Action可以直接訪問用戶請求的HttpServletRquest實例。
|>ServletResponseAwre:實現該接口的Action可以直接訪問服務器響應的HttpServletResponse實例。

另外,struts2還提供一個ServletActionContext工具類直接訪問Servlet API,

這裡寫圖片描述

借助ServletActionContext類可以在Action中訪問Serlevt API,並可以避免Action類需要實現XxxAware接口,但該Action依然與Servlet API直接耦合,測試時需要有 Servlet 容器, 不便於對 Action 的單元測試,一樣不利於高層次的解耦。

Action的動態方法調用

這篇寫Action相關,本來應該還涉及到Action的基本配置,但前面一篇講開發流程時基本介紹到,這裡不再贅言,直接看Action的動態方法調用。

很多時候要求一個Action內包含多個控制處理邏輯。比如對同一個表單,用戶可能要通過登錄或注冊兩個不同提交按鈕來提交同一個表單系統需要使用Action不同方法來處理用戶請求,這就需要讓同一個Action裡包含多個控制處理邏輯。

”登錄”按鈕使用登錄邏輯處理請求,“注冊”按鈕使用注冊邏輯處理請求。可采用DMI(Dynamic Method Invocaton,動態方法調用)來處理請求。動態方法調用中表單元素的action並不是直接等於某個Action的名字,而是按如下形式來指定表單的action屬性。

fun(){
<!--action屬性為actionName!methodName的形式-->
target.action="action!methodName";
}


如我們可以將JSP頁面“注冊”按鈕的代碼寫成:



regist函數JavaScript代碼:

function regist(){
   //獲取頁面的第一個表單
   targetForm = document.forms[0];
   targetForm.action = "login!regist";
}


最後一行代碼就是說將該表單提交給login Action的regist方法處理。LoginRegistAction類的代碼如下:

public class LoginRegistAction extends ActionSupport{
   //封裝用戶請求參數的兩個成員變量
   private String username;
   private String password;
   //封裝處理結果的tip成員變量
   private String tip;
   //省略setter和getter方法
   ...
   //Action包含的注冊控制邏輯
   public String register() throws Exception{
      ActionContext.getContext().getSession().put("user",getUsername());
   setTip("歡迎你!" + getUsername() + "你已經注冊成功!");
   return SUCCESS;
   }
   //Action默認包含的控制邏輯
   public String execute() throws Exception{
      if(getUsername().equals("Jujiu")&&getPassword().equals("1357afy"))
      {
         ActionContext.getContext().getSession().put("user",getUsername());
         setTip("歡迎你!" + getUsername()+"你已經注冊成功!");
         return SUCCESS;
       }              
   }
}

默認調用execute方法,當用戶單擊登錄,系統將表單提交給LoginActionAction默認方法,當用戶單擊“注冊”按鈕,該表單的action會被修改為:login!regist,系統將提交給login Action(即LoginRegistAction)的regist方法處理。這種方式可以使一個Action包含多個邏輯處理,並通過為表單元素指定不同action屬性來提交給action的不同方法。

使用動態方法調用,其中的方法如regist方法的聲明和系統默認的execute方法除了方法名不一樣外,其他如形參列表、返回值類型都應完全相同。

使用動態方法調用前需要設置struts2運行動態方法調用,即設置struts.enable.DynamicMethodInvocation常量的值為true。DMI方式存在安全缺陷。不建議常用。

method屬性指定方法和通配符使用

可以使用中的method屬性將一個Action類配置成多個邏輯Action,讓Action調用指定方法。


  

     
        
          /WEB-INF/pages/welcome.jsp
        
     

    
      
         /WEB-INF/pages/welcome.jsp
      
     

 

這裡定義login和regist兩個邏輯Action,處理類都是LoginRegist,處理邏輯由method方法指定,login的Action對應的處理邏輯是默認的execute方法,而regist的Action對應的處理邏輯是指定的regist方法。相應的JavaScript代碼改為:

function regist(){
   //獲取頁面的第一個表單
   targetForm = document.forms[0];
   targetForm.action = "regist";
}

我們發現多個< action…/>中的定義大部分相同,造成冗余,此時可以考慮使用通配符方式。在配置< action…/>,指定name屬性時使用模式字符串(用“*”代表一個或多個任意字符),可以在class、method屬性及< result…/>子元素中使用表達式{N}的形式代替前面第N個星號所匹配的子串。


  

     
        
          /WEB-INF/pages/welcome.jsp
        
     

 

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved