1. 程式人生 > >struts2建立action幾種方式有什麼區別?

struts2建立action幾種方式有什麼區別?

 當我們在寫action的時候,可以實現Action介面,也可以繼承Actionsupport這個類.到底這兩個有什麼區別呢?
Action介面有:
public static final java.lang.String SUCCESS = "success";
public static final java.lang.String NONE = "none";
public static final java.lang.String ERROR = "error";
public static final java.lang.String INPUT = "input";
public static final java.lang.String LOGIN = "login";

public abstract java.lang.String execute() throws java.lang.Exception;

而Actionsupport這個工具類在實現了Action介面的基礎上還定義了一個validate()方法,重寫該方法,它會在execute()方法之前執行,如校驗失敗,會轉入input處,必須在配置該Action時配置input屬性。

另外,Actionsupport還提供了一個getText(String key)方法還實現國際化,該方法從資原始檔上獲取國際化資訊.

這樣在自定義標籤時可以定義一個變數為new actionsupport物件實現國際化。 

ActionSupport類的作用

 struts2不要求我們自己設計的action類繼承任何的struts基類或struts介面,但是我們為了方便實現我們自己的action,大多數情況下都會繼承com.opensymphony.xwork2.ActionSupport類,並重寫此類裡的public String execute() throws Exception方法。因為此類中實現了很多的實用藉口,提供了很多預設方法,這些預設方法包括國際化資訊的方法、預設的處理使用者請求的方法等,這樣可以大大的簡化Acion的開發。
 
 Struts2中通常直接使用Action來封裝HTTP請求引數,因此,Action類裡還應該包含與請求引數對應的屬性,並且為屬性提供對應的getter和setter方法。

1.1 增加資料校驗

在上面應用中,即使瀏覽者輸入任何使用者名稱、密碼,系統也會處理使用者請求。在我們整個HelloWorld應用中,這種空使用者名稱、空密碼的情況不會引起太大的問題。但如果資料需要儲存到資料庫,或者需要根據使用者輸入的使用者名稱、密碼查詢資料,這些空輸入可能引起異常。
為了避免使用者的輸入引起底層異常,通常我們會在進行業務邏輯操作之前,先執行基本的資料校驗。

1.1 .1  繼承ActionSupport

ActionSupport類是一個工具類,它已經實現了Action介面。除此之外,它還實現了Validateable介面,提供了資料校驗功能。通過繼承該ActionSupport類,可以簡化Struts 2的Action開發。
在Validatable介面中定義了一個validate()方法,重寫該方法,如果校驗表單輸入域出現錯誤,則將錯誤新增到ActionSupport類的fieldErrors域中,然後通過OGNL表示式負責輸出。
為了讓Struts 2增加輸入資料校驗的功能,改寫程式中的LoginAction,增加重寫validate方法。修改後的LoginAction類程式碼如下:

import com.opensymphony.xwork2.ActionSupport;

public class LoginAction extends ActionSupport{
    private static final long serialVersionUID = -5364041394865092784L;
    // 下面是Action內用於封裝使用者請求引數的兩個屬性
    private String username;
    private String password;

    // username屬性對應的getter方法
    public String getUsername() {
        return username;
    }
    // username屬性對應的setter方法
    public void setUsername(String username) {
        this.username = username;
    }
    // password屬性對應的getter方法
    public String getPassword() {
        return password;
    }
    // password屬性對應的setter方法
    public void setPassword(String password) {
        this.password = password;
    }
    // 處理使用者請求的execute方法
    public String execute() throws Exception {
        // 當用戶請求引數的username等於scott,密碼請求引數為tiger時,返回success字串
        // 否則返回error的字串
        if (getUsername().equals("scott") && getPassword().equals("tiger")) {
            return "success";
        } else {
            return "error";
        }
    }
    // 完成輸入校驗需要重寫的validate方法
    public void validate() {
        // 如果使用者名稱為空,或者使用者名稱為空字串
        if (getUsername() == null || getUsername().trim().equals("")) {
            // 新增表單校驗錯誤
            addFieldError("username", "user.required");
        }
        // 當密碼為空,或者密碼為空字串時,新增表單校驗錯誤
        if (getPassword() == null || getPassword().trim().equals("")) {
            addFieldError("password", "pass.required");
        }
    }
}

       上面的Action類重寫了validate方法,該方法會在執行系統的execute方法之前執行,如果執行該方法後,Action類的fieldErrors中已經包含了資料校驗錯誤,請求將被轉發到input邏輯檢視處。
       為了在校驗失敗後,系統能將檢視轉入input處,必須在配置該Action時配置input屬性。下面是修改後login Action的配置片段:

<!-- 定義login的Action -->
<action name="Login" class="lee.LoginAction">
    <!-- 定義input的邏輯檢視名,對應login.jsp頁面 -->
    <result name="input">/login.jsp</result>
    <!-- 定義error的邏輯檢視名,對應error.jsp頁面 -->
     <result name=" success ">/error.jsp</result>
    <!-- 定義welcome的邏輯檢視名,對應welcome.jsp頁面 -->
     <result name="success">/welcome.jsp</result>        
</action>

       對比上面的Action配置與前面的Action配置,我們發現該Action配置片段中增加了input邏輯檢視的配置,該邏輯檢視對映到login.jsp頁面。
       前面已經提到:當用戶提交請求時,請求得到execute方法處理之前,先會被validate方法處理,如果該方法處理結束後,Action的fieldErrors裡的校驗錯誤不為空,請求將被轉發給input邏輯檢視。如果我們不輸入使用者名稱、密碼而直接提交表單,將看到提示介面:輸入校驗的介面

       看到這裡也許讀者覺得非常神奇:我們僅僅在Action添加了資料校驗錯誤,並未在輸入頁面輸出這些校驗錯誤資訊,卻可以看到頁面已經輸出了這些校驗資訊——這是因為Struts 2的標籤,上面的JSP頁面中表單使用的並不是HTML表單,而是用了<s:form .../>標籤,Struts 2的<s:form ... />標籤已經具備了輸出校驗錯誤的能力。
提示  Struts 2的<s:form .../>預設已經提供了輸出校驗錯誤的能力。
       但上面的程式還存在一個問題:校驗資訊的國際化。檢視上面的Action類程式碼發現:重寫validate方法時,如果發生校驗失敗的問題,校驗錯誤的提示資訊是以硬編碼方式寫死了——這就失去了國際化的能力。
實際上,ActionSupport類已經提供了國際化資訊的能力,它提供了一個getText(String key)方法,該方法用於從資原始檔中獲取國際化資訊。為了讓校驗資訊支援國際化,再次改寫Action裡的validate方法,改寫後的validate方法程式碼如下:

    // 執行資料校驗的validate方法
    public void validate() {
        // 如果使用者名稱為空,或者為空字串
        if (getUsername() == null || getUsername().trim().equals("")) {
            // 新增校驗錯誤提示,使用getText方法來使提示資訊國際化
            addFieldError("username", getText("user.required"));
        }
        if (getPassword() == null || getPassword().trim().equals("")) {
            addFieldError("password", getText("pass.required"));
        }
    }

       在上面的validate方法中,新增校驗錯誤提示時,並不是直接給出了錯誤提示的字串,而是呼叫了getText方法來獲取錯誤提示。因為在Action中,使用getText方法來獲取了兩個國際化提示:user.required和pass.required,因此應該在國際化資原始檔中新增這兩條提示資訊。提示  ActionSupport增加了讓提示資訊國際化的能力,ActionSupport提供的getText方法可以根據資原始檔載入獲得國際化提示資訊。此時,如果沒有任何輸出,直接提交登入表單,將看到所示的介面:國際化資料校驗的錯誤提示