Struts2用戶輸入驗證(2)

10.2.2 常用的用戶輸入驗證實現方式

         10.2.1中雖然實現了用戶登陸功能的,用戶輸入驗證。但是這種方式卻很少被使用。本節中介紹實際應用中較爲常見的編碼方式。代碼實現進需要修改Action類,其餘文件的內容無需修改。
代碼10-1中登陸案例代碼編寫中將用戶輸入驗證的代碼實現放到execute方法中,這種方法雖然容易被讀者理解。但是從代碼設計角度來看存在execute方法過於臃腫、不利於代碼的重用等問題。更爲常見的代碼實現方式,則是重寫ActionSupport類中的validate方法,在該方法中完成用戶輸入驗證。具體代碼如下所示:
packagecom.study.erp.action;
importcom.opensymphony.xwork2.ActionSupport;
public class LoginAction extendsActionSupport{
    private String username;
    private String password;
    //此處省略屬性對應的getset方法
    ….
    @Override
    public void validate() {
        if(username == null || username.trim().equals("")){
            addFieldError("username", "用戶名不能爲空.");
        }
        if(password == null || password.trim().equals("")){
            addFieldError("password", "密碼不能爲空.");         
        }else if(password.length()<6 || password.length()>12){
            addFieldError("password", "密碼長度應在612位之間.");  
        }
    }
    public String execute(){
            return "success";
    }
}
     代碼10-4用戶登陸功能LoginAction
比較上述10-4代碼和10-1代碼讀者可以發現,10-4的內容更加簡潔。當進行用戶輸入驗證時,該驗證代碼編寫到validate方法。該方法中如果發現用戶輸入錯誤時,將錯誤信息添加到框架FieldError中即可。在進行完所有的用戶輸入驗證後,無需用戶編碼實現頁面的跳轉。框架會驗證用戶輸入驗證是否正確,如果正確會繼續執行execute方法,如果錯誤會跳轉到該Action對應的名爲input的結果視圖中。
本節案例中的代碼實現,是Struts框架下基於編碼方式實現用戶輸入驗證所提倡的方式。讀者在編寫時常見的錯誤是沒有在配置文件中配置名爲input的結果視圖,其配置文件的代碼爲:<result name="input">/xxx.jsp</result>

10.2.3 多方法Action的用戶輸入驗證實現方式

         在學習第二章Action的編寫和配置時,我們已經瞭解到Struts2Action類中可以包含多個方法,每個方法用來完成不同的邏輯操作。例如,我們可以利用同一個Action來完成一組邏輯相關的操作:用戶登陸、用戶註冊、用戶信息修改和用戶信息刪除。代碼實現時需要在一個Action類中需要包括4個方法,但是對於這4個方法來說用戶輸入校驗的規則也是不同的,如果再使用10.2.2所講的validate方法來實現用戶輸入驗證,很難實現預期的效果。
Struts2框架對於這類情況也提供了相應的解決方案。當Action中包括多個邏輯操作方法時,爲完成用戶輸入驗證Action類的編碼須實現Validateable接口(ActionSupport類已經實現了Validateable接口)並編寫validateXxx方法,Xxx即對應Action邏輯操作方法的名字。Struts2框架利用了反射機制在對應的邏輯操作方法執行之前調用相應的validateXxx方法。
爲了讓讀者更容易讀懂本節中的代碼,本案例中僅實現了用戶註冊和用戶登陸功能的用戶輸入校驗。用戶登陸的用戶輸入驗證規則不變,用戶註冊功能的用戶輸入驗證規則包括:用戶名不能爲空、密碼不能爲空、密碼長度必須在612位之間、年齡的輸入範圍必須在0-100之間,郵箱必須包括@字符。
用戶登陸功能圖示與圖10-110-210-3一致,以下爲用戶註冊功能截圖:
(1)      當在頁面上只輸入年齡-11,郵箱爲11
      
圖10-3 用戶註冊功驗證錯誤1
(2)      當在頁面上輸入用戶名爲11,密碼爲11,年齡爲-11,郵箱爲11時:
     
圖10-4 用戶註冊功驗證錯誤2
(3)         當在頁面上輸入用戶名爲唐琳,密碼爲123456,年齡爲33,郵箱爲[email protected]時:
     
圖10-5 用戶註冊功驗證成功
         以下爲【用戶登陸功能】、【用戶註冊功能】實現的代碼結構:
圖10-6 用戶登陸、用戶註冊功驗證代碼結構
編寫該功能時用戶需要編寫和創建的文件:
文件名
說明
備註
Login.jsp
用戶登陸頁面
視圖
LoginSuccess.jsp
用戶登陸成功頁面
視圖
Regist.jsp
用戶註冊頁面
視圖
RegistSuccess.jsp
用戶註冊成功頁面
視圖
UserAction
Action
控制器
struts.xml
Struts2框架的配置文件
配置文件
web.xml
項目的部署描述文件
配置文件
由於篇幅的關係,以下僅列出UserAction類,Regist.jspstruts.xml文件的部分代碼。其它代碼參考光盤中Unit10文件夾下03的項目代碼。
         UserAction類包含兩個邏輯,因此包含了兩個邏輯方法分別是loginregistlogin方法用於實現用戶登陸功能,對應的用戶輸入校驗方法爲validateLogin方法;regist方法用於實現用戶註冊功能,對應的用戶輸入校驗方法爲validateRegist方法。具體代碼如下所示:
packagecom.study.erp.action;
importcom.opensymphony.xwork2.ActionSupport;
public class UserActionextends ActionSupport{
    private String username;
    private String password;
    private int age;
    private String email;
    //此處省略屬性對應的getset方法
    ….
    //用戶登陸功能對應的用戶輸入校驗方法
    public void validateLogin() {
        if(username == null || username.trim().equals("")){
            addFieldError("username","用戶名不能爲空.");
        }
        if(password == null || password.trim().equals("")){
            addFieldError("password", "密碼不能爲空.");          
        }else if(password.length()<6 || password.length()>12){
            addFieldError("password", "密碼長度應在612位之間.");
        }
    }
//用戶註冊功能對應的用戶輸入校驗方法
    public void validateRegist() {
        if(username == null || username.trim().equals("")){
            addFieldError("username", "用戶名不能爲空.");
        }
        if(password == null || password.trim().equals("")){
            addFieldError("password", "密碼不能爲空.");          
        }else if(password.length()<6 || password.length()>12){
            addFieldError("password", "密碼長度應在612位之間.");
        }
        if(age <0 || age>100){
            addFieldError("age", "年齡不符合要求."); 
        }
        if(email.indexOf("@") == -1){
            addFieldError("email", "Email格式不符合要求.");  
        }
    }
 
    public String login(){
            return "success";
    }
   
    public String regist(){
            return "success";
    }
}
         以上代碼中用戶輸入校驗方法名編寫時務必注意:  1.validateXxx方法,方法名Xxx爲對應的邏輯方法方法名,首字母大寫。2. 方法的權限爲public,方法沒有參數,返回值爲void類型。
         struts.xml文件中當前的Action類對應的每個action配置都需要包含名爲“input”的結果視圖,具體的配置信息如下所示:
<?xml version="1.0"encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTDStruts Configuration 2.0//EN"
   "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
     <package name="default"namespace="/" extends="struts-default">
        <action name="login"class="com.study.erp.action.UserAction" method="login">
            <result name="input">/Login.jsp</result>
            <result name="success">/LoginSuccess.jsp</result>
        </action>
        <action name="regist"class="com.study.erp.action.UserAction"  method="regist">
            <result name="input">/Regist.jsp</result>
            <result name="success">/RegistSuccess.jsp</result>
        </action>
    </package>
</struts>
    用戶註冊視圖Regist.jsp代碼如下所示:
<%@ pagelanguage="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<%@ tagliburi="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC"-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>用戶註冊頁面</title>
</head>
<body>
    <h1>用戶註冊</h1>
    <hr>
    <s:form action="regist.action">
        <s:textfield name="username" label="用戶名"></s:textfield>
        <s:password name="password" label="密碼"></s:password>
        <s:textfield name="age" label="年齡"></s:textfield>
        <s:textfield name="email" label="電子郵件:"></s:textfield>
        <s:submit name="login" value="註冊"/>
    </s:form>
</body>
</html>
    以上爲實現登陸和註冊功能的主要代碼,我們仔細分析發現validateLogin()validateRegist()代碼中部分代碼是重複的,但是上面的代碼中由於用戶輸入驗證對應的方法是不同的,所以代碼出現了重複的現象,雖然我們可以單獨把這段重複的代碼單獨寫到一個方法中,然後在這兩個用戶輸入驗證方法中進行調用以進行改進。
Struts2框架的validate方法是由DefaultWorkFlowInterceptor攔截器調用的。該攔截器包含在defaultStack攔截器棧中。因此,只要使用默認的攔截器棧該攔截器都回被運行,從而validate方法會被調用。換句話說,默認情況下當前Action的所有邏輯方法執行之前都會執行validate方法。如果validate方法和validateXxx方法同時存在,它們的執行順序是先執行validateXxx方法,再執行validate方法。針對於Struts框架中本例中的Action類可以做如下優化:
packagecom.study.erp.action;
importcom.opensymphony.xwork2.ActionSupport;
public class UserActionextends ActionSupport{
    private String username;
    private String password;
    private int age;
    private String email;
    //此處省略屬性對應的getset方法
    ….
    //用戶登陸功能對應的用戶輸入校驗方法,此時本方法可以省略不寫
    public void validateLogin() {
    }
    //用戶註冊功能對應的用戶輸入校驗方法
    public void validateRegist() {
        if(age <0 || age>100){
            addFieldError("age", "年齡不符合要求.");
        }
        if(email.indexOf("@") == -1){
            addFieldError("email", "Email格式不符合要求."); 
        }
    }
    //用戶輸入驗證方法
    public void validate(){
        if(username == null || username.trim().equals("")){
            addFieldError("username", "用戶名不能爲空.");
        }
        if(password == null || password.trim().equals("")){
            addFieldError("password", "密碼不能爲空.");         
        }else if(password.length()<6 || password.length()>12){
            addFieldError("password", "密碼長度應在612位之間.");  
        }
    }
    public String login(){
            return "success";
    }
    public String regist(){
            return "success";
    }
}
    如果某action中包含了多個邏輯方法,其中絕大部分方法都有相同的驗證規則,只有個別方法不需要該驗證規則時。可以使用DefaultWorkFlowInterceptor攔截器的excludeMethods參數,指定被排除的方法。如果被排除的方法超過1個,方法名中間使用逗號進行間隔。
    例如UserAction類中包含了3個方法:用戶登陸login方法,用戶註冊regist方法,用戶信息刪除的delete方法。而用戶信息刪除不需要執行validate方法用戶名和用戶密碼的驗證規則。具體的實現方法可以包括以下兩種,比較而言第二種方法更容易理解也更加簡單。
1.重新設定默認的攔截器棧,在該攔截器棧中將delete方法排除掉。對應的struts.xml文件的內容如下所示:
<struts>
     <package name="default"namespace="/" extends="struts-default">
         <interceptors>
             <interceptor-stackname="mydefaultStack">
                 <interceptor-refname="defaultStack">
                  <paramname="workflow.excludeMethods">delete</param>
              </interceptor-ref>
             </interceptor-stack>
         </interceptors>
         <default-interceptor-refname="mydefaultStack"></default-interceptor-ref>
        <action name="login"class="com.study.erp.action.UserAction" method="login">
            <result name="input">/Login.jsp</result>
            <result name="success">/LoginSuccess.jsp</result>
        </action>
        <action name="regist"class="com.study.erp.action.UserAction"  method="regist">
            <result name="input">/Regist.jsp</result>
            <result name="success">/RegistSuccess.jsp</result>
        </action>
        <action name="delete"class="com.study.erp.action.UserAction"  method="delete">
            <result name="success">/DeleteSuccess.jsp</result>
        </action>
    </package>
</struts>
    2.只在刪除用戶信息對應的action配置信息中將delete方法從攔截器中刪除掉。對應的配置文件內容
<?xml version="1.0"encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTDStruts Configuration 2.0//EN"
   "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
     <package name="default"namespace="/" extends="struts-default">
        <action name="login"class="com.study.erp.action.UserAction" method="login">
            <result name="input">/Login.jsp</result>
            <result name="success">/LoginSuccess.jsp</result>
        </action>
        <action name="regist"class="com.study.erp.action.UserAction"  method="regist">
            <result name="input">/Regist.jsp</result>
            <result name="success">/RegistSuccess.jsp</result>
        </action>
        <action name="delete"class="com.study.erp.action.UserAction"  method="delete">
            <result name="success">/DeleteSuccess.jsp</result>
            <interceptor-ref name="defaultStack">
                  <paramname="workflow.excludeMethods">delete</param>
            </interceptor-ref>
        </action>
    </package>
</struts>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章