20160501--struts2入門3

破玉發表於2016-05-02
一、自定義攔截器
要自定義攔截器需要實現com.opensymphony.xwork2.interceptor.Interceptor介面:
public class PermissionInterceptor implements Interceptor {
   private static final long serialVersionUID = -5178310397732210602L;
   public void destroy() {
   }
   public void init() {
   }
   public String intercept(ActionInvocation invocation) throws Exception {
     System.out.println("進入攔截器");    
    if(session裡存在使用者){
        String result = invocation.invoke();
    }else{
        return “logon”;
    }
    //System.out.println("返回值:"+ result);
    //return result;
    }
}

 

<package name="itcast" namespace="/test" extends="struts-default">
    <interceptors>
              <interceptor name=“permission" class="cn.itcast.aop.PermissionInterceptor" />
              <interceptor-stack name="permissionStack">
          <interceptor-ref name="defaultStack" />
         <interceptor-ref name=" permission " />
               </interceptor-stack>
     </interceptors>
    <action name="helloworld_*" class="cn.itcast.action.HelloWorldAction" method="{1}">
        <result name="success">/WEB-INF/page/hello.jsp</result>
        <interceptor-ref name="permissionStack"/>
    </action>
</package>
因為struts2中如檔案上傳,資料驗證,封裝請求引數到action等功能都是由系統預設的defaultStack中的攔截器實現的,所以我們定義的攔截器需要引用系統預設的defaultStack,這樣應用才可以使用struts2框架提供的眾多功能。
如果希望包下的所有action都使用自定義的攔截器,可以通過<default-interceptor-ref name=“permissionStack”/>把攔截器定義為預設攔截器。注意:每個包只能指定一個預設攔截器。另外,一旦我們為該包中的某個action顯式指定了某個攔截器,則預設攔截器不會起作用。
舉例:定義訪問許可權攔截器
package com.dzq.action;

public class HelloWorldAction {
    private String message;

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
    
    
    public String addUI(){
        this.message="addUI";
        return "success";
    }
    
    public String execute() {
        this.message="execute";
        return "success";
    }
}
package com.dzq.interceptor;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;

public class PermissionInterceptor implements Interceptor {

    @Override
    public void destroy() {
        

    }

    @Override
    public void init() {
        

    }

    @Override
    public String intercept(ActionInvocation invocation) throws Exception {
        Object user=ActionContext.getContext().getSession().get("user");
        if(user!=null){
            return invocation.invoke();//如果user不為空,代表使用者已經登入,允許執行action中的方法
        }
        ActionContext.getContext().put("message", "對不起,請先登入");
        return "success";
    }

}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
  
    <!-- 指定訪問字尾 -->
    <constant name="struts.action.extension" value="do,action"/>
    
    <package name="department" namespace="/test/department" extends="struts-default">
        
        <interceptors>
            <interceptor name="permission" class="com.dzq.interceptor.PermissionInterceptor"/>
            <!--攔截器棧  -->
            <interceptor-stack name="permissionStack">
                <interceptor-ref name="defaultStack"/>
                 <interceptor-ref name="permission"/>
            </interceptor-stack>
        </interceptors>
        <!-- 包內所有action都使用預設攔截器 -->
      <!--   <default-interceptor-ref name="permissionStack"/> -->
        <global-results>
            <result name="success">/WEB-INF/page/message.jsp</result>
        </global-results>
      
        <!--使用萬用字元訪問  -->
        <action name="list_*" class="com.dzq.action.HelloWorldAction" method="{1}">
            <interceptor-ref name="permissionStack"/> 
           <!-- <interceptor-ref name=""></interceptor-ref> -->
        </action>
    </package>
</struts>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
  ${message}<br>

</body>
</html>
message.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<%
request.getSession().setAttribute("user", "dudu");
%>
使用者已登入
</body>
</html>
user.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<%request.getSession().removeAttribute("user"); %>
使用者退出登入
</body>
</html>
logout.jsp

流程:直接訪問localhost:8080.../test/department/list_addUI.do,報使用者尚未登入資訊,訪問user.jsp,設定使用者登入session,再訪問action,則顯示已登入,訪問logout.jsp銷燬session,再訪問action,則顯示未登入,通過攔截器實現,攔截器在struts.xml中註冊後使用,攔截action

二、輸入校驗
在struts2中,我們可以實現對action的所有方法進行校驗或者對action的指定方法進行校驗。
 
對於輸入校驗struts2提供了兩種實現方法:
1. 採用手工編寫程式碼實現。
2. 基於XML配置方式實現。
 
 
1.手工編寫程式碼實現對action中所有方法輸入校驗
通過重寫validate() 方法實現, validate()方法會校驗action中所有與execute方法簽名相同的方法。當某個資料校驗失敗時,我們應該呼叫addFieldError()方法往系統的fieldErrors新增校驗失敗資訊(為了使用addFieldError()方法,action可以繼承ActionSupport ),如果系統的fieldErrors包含失敗資訊,struts2會將請求轉發到名為input的result。在input檢視中可以通過<s:fielderror/>顯示失敗資訊。
validate()使用例子:
 
public void validate() {
       if(this.mobile==null || "".equals(this.mobile.trim())){  this.addFieldError("username", "手機號不能為空");
        }else{  if(!Pattern.compile("^1[358]\\d{9}").matcher(this.mobile.trim()).matches()){
        this.addFieldError(“mobile", "手機號的格式不正確"); }
       }
}
驗證失敗後,請求轉發至input檢視:
 
<result name="input">/WEB-INF/page/addUser.jsp</result>
addUser.jsp頁面中使用<s:fielderror/>顯示失敗資訊。
 例項程式碼:
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    <%@taglib uri="/struts-tags" prefix="s"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>輸入校驗</title>
</head>
<body>
<div align="center">
<h1>struts2輸入校驗</h1><hr>
<s:fielderror/>
<form action="${pageContext.request.contextPath }/person/manage_update.do" method="post">
使用者名稱:<input type="text" name="username"/><br>
手機號:<input type="text" name="mobile"/><br>
<input type="submit" value="驗證"/>
</form>
</div>
</body>
</html>
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>結果</title>
</head>
<body>
${message }
</body>
</html>
message.jsp
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
  
    <!-- 指定訪問字尾 -->
    <constant name="struts.action.extension" value="do,action"/>
    
    <package name="department" namespace="/person" extends="struts-default">
       <action name="manage_*" class="com.dzq.action.PersonAction" method="{1}">
           <result name="message">/WEB-INF/page/message.jsp</result>
           <result name="input">/index.jsp</result>
       </action>
    </package>
</struts>
package com.dzq.action;

import java.util.regex.Pattern;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;

public class PersonAction extends ActionSupport{
    private String username;
    private String mobile;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getMobile() {
        return mobile;
    }

    public void setMobile(String mobile) {
        this.mobile = mobile;
    }
    
    public String update(){
        ActionContext.getContext().put("message", "更新成功");
        return "message";
    }
    
    public String save(){
        ActionContext.getContext().put("message", "儲存成功");
        return "message";
    }
    
    /**
     * 輸入校驗,對action中所有方法進行校驗
     */
    
    @Override
    public void validate() {
        if(this.username==null||"".equals(this.username.trim())){
            this.addFieldError("username","使用者名稱不能為空");
        }
        if(this.mobile==null||"".equals(this.mobile.trim())){
            this.addFieldError("mobile","手機號不能為空");
        }else{
            if(!Pattern.compile("^1[358]\\d{9}$").matcher(this.mobile).matches()){
                this.addFieldError("mobile","手機號格式不正確");
            }
        }
    }
}

 2.手工編寫程式碼實現對action中指定方法輸入校驗

通過validateXxx()方法實現, validateXxx()只會校驗action中方法名為Xxx的方法。其中Xxx的第一個字母要大寫。當某個資料校驗失敗時,我們應該呼叫addFieldError()方法往系統的fieldErrors新增校驗失敗資訊(為了使用addFieldError()方法,action可以繼承ActionSupport ),如果系統的fieldErrors包含失敗資訊,struts2會將請求轉發到名為input的result。在input檢視中可以通過<s:fielderror/>顯示失敗資訊。
 
 
validateXxx()方法使用例子:
 
public String add() throws Exception{  return "success";}    
public void validateAdd(){
          if(username==null && "".equals(username.trim()))  this.addFieldError("username", "使用者名稱不能為空");
}
驗證失敗後,請求轉發至input檢視:
<result name="input">/WEB-INF/page/addUser.jsp</result>
addUser.jsp頁面中使用<s:fielderror/>顯示失敗資訊
例項程式碼:將上述例項的validate方法改為validateUpdate
/*
     * 只會對update方法輸入校驗
     */
    public void validateUpdate() {
        if(this.username==null||"".equals(this.username.trim())){
            this.addFieldError("username","使用者名稱不能為空");
        }
        if(this.mobile==null||"".equals(this.mobile.trim())){
            this.addFieldError("mobile","手機號不能為空");
        }else{
            if(!Pattern.compile("^1[358]\\d{9}$").matcher(this.mobile).matches()){
                this.addFieldError("mobile","手機號格式不正確");
            }
        }
    }

 

輸入校驗的流程:
1.型別轉換器對請求引數執行型別轉換,並把轉換後的值賦給action中的屬性。
 
2.如果在執行型別轉換的過程中出現異常,系統會將異常資訊儲存到ActionContext,conversionError攔截器將異常資訊新增到fieldErrors裡。不管型別轉換是否出現異常,都會進入第3步。
 
3.系統通過反射技術先呼叫action中的validateXxx()方法,Xxx為方法名。
 
4.再呼叫action中的validate()方法。
 
5.經過上面4步,如果系統中的fieldErrors存在錯誤資訊(即存放錯誤資訊的集合的size大於0),系統自動將請求轉發至名稱為input的檢視。如果系統中的fieldErrors沒有任何錯誤資訊,系統將執行action中的處理方法。
 
3.基於XML配置方式實現對action的所有方法進行輸入校驗
使用基於XML配置方式實現輸入校驗時,Action也需要繼承ActionSupport,並且提供校驗檔案校驗檔案和action類放在同一個包下,檔案的取名格式為:ActionClassName-validation.xml,其中ActionClassName為action的簡單類名,-validation為固定寫法。如果Action類為cn.itcast.UserAction,那麼該檔案的取名應為:UserAction-validation.xml。下面是校驗檔案的模版:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.3//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.3.dtd"> 
<validators>
    <field name="username">
        <field-validator type="requiredstring">
            <param name="trim">true</param>
            <message>使用者名稱不能為空!</message>
        </field-validator>
    </field>
</validators>
<field>指定action中要校驗的屬性,<field-validator>指定校驗器,上面指定的校驗器requiredstring是由系統提供的,系統提供了能滿足大部分驗證需求的校驗器,這些校驗器的定義可以在xwork-2.x.jar中的com.opensymphony.xwork2.validator.validators下的default.xml中找到。
<message>為校驗失敗後的提示資訊,如果需要國際化,可以為message指定key屬性,key的值為資原始檔中的key。
在這個校驗檔案中,對action中字串型別的username屬性進行驗證,首先要求呼叫trim()方法去掉空格,然後判斷使用者名稱是否為空。
 例項程式碼:
import com.opensymphony.xwork2.ActionSupport;

public class PersonAction extends ActionSupport{
    private String username;
    private String mobile;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getMobile() {
        return mobile;
    }

    public void setMobile(String mobile) {
        this.mobile = mobile;
    }
    
    public String update(){
        ActionContext.getContext().put("message", "更新成功");
        return "message";
    }
    
    public String save(){
        ActionContext.getContext().put("message", "儲存成功");
        return "message";
    }
}

PersonAction-validation.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.3//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.3.dtd">
<validators>
    <field name="username">
        <field-validator type="requiredstring"><!-- 指定校驗器 -->
            <param name="trim">true</param>
            <message>使用者名稱不能為空!</message>
        </field-validator>
    </field>
    <field name="mobile">
        <field-validator type="requiredstring"><!-- 指定校驗器 -->
            <param name="trim">true</param>
            <message>手機號不能為空!</message>
        </field-validator>
        <field-validator type="regex">  <!-- 指定正則校驗器-->
            <param name="expression"><![CDATA[^1[358]\d{9}$]]></param>
            <message>手機號格式不正確!</message>
        </field-validator>
    </field>
</validators>

struts.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
  
    <!-- 指定訪問字尾 -->
    <constant name="struts.action.extension" value="do,action"/>
    
    <package name="department" namespace="/person" extends="struts-default">
       <action name="manage_*" class="com.dzq.action.PersonAction" method="{1}">
           <result name="message">/WEB-INF/page/message.jsp</result>
           <result name="input">/index.jsp</result>
       </action>
    </package>
</struts>

 

struts2提供的校驗器列表
 
系統提供的校驗器如下:
required (必填校驗器,要求field的值不能為null)
requiredstring (必填字串校驗器,要求field的值不能為null,並且長度大於0,預設情況下會對字串去前後空格)
stringlength(字串長度校驗器,要求field的值必須在指定的範圍內,否則校驗失敗,minLength引數指定最小長度,maxLength引數指定最大長度,trim引數指定校驗field之前是否去除字串前後的空格)
regex(正規表示式校驗器,檢查被校驗的field是否匹配一個正規表示式.expression引數指定正規表示式,caseSensitive引數指定進行正規表示式匹配時,是否區分大小寫,預設值為true)
int(整數校驗器,要求field的整數值必須在指定範圍內,min指定最小值,max指定最大值)
double(雙精度浮點數校驗器,要求field的雙精度浮點數必須在指定範圍內,min指定最小值,max指定最大值)
fieldexpression(欄位OGNL表示式校驗器,要求field滿足一個ognl表示式,expression引數指定ognl表示式,該邏輯表示式基於ValueStack進行求值,返回true時校驗通過,否則不通過)
email(郵件地址校驗器,要求如果field的值非空,則必須是合法的郵件地址)
url(網址校驗器,要求如果field的值非空,則必須是合法的url地址)
date(日期校驗器,要求field的日期值必須在指定範圍內,min指定最小值,max指定最大值)
conversion(轉換校驗器,指定在型別轉換失敗時,提示的錯誤資訊)
visitor(用於校驗action中的複合屬性,它指定一個校驗檔案用於校驗複合屬性中的屬性)
expression(OGNL表示式校驗器,expression引數指定ognl表示式,該邏輯表示式基於ValueStack進行求值,返回true時校驗通過,否則不通過,該校驗器不可用在欄位校驗器風格的配置中)
 
校驗器的使用例子
required  必填校驗器
<field-validator type="required">
       <message>性別不能為空!</message>
</field-validator>
requiredstring  必填字串校驗器
<field-validator type="requiredstring">
       <param name="trim">true</param>
       <message>使用者名稱不能為空!</message>
</field-validator>
stringlength:字串長度校驗器
<field-validator type="stringlength">
<param name="maxLength">10</param>
<param name="minLength">2</param>
<param name="trim">true</param>
<message><![CDATA[產品名稱應在2-10個字元之間]]></message>
</field-validator>
email:郵件地址校驗器
<field-validator type="email">
<message>電子郵件地址無效</message>
</field-validator>
regex:正規表示式校驗器
<field-validator type="regex">
     <param name="expression"><![CDATA[^1[358]\d{9}$]]></param>
     <message>手機號格式不正確!</message>
</field-validator>
int:整數校驗器
<field-validator type="int">
<param name="min">1</param>
<param name="max">150</param>
<message>年齡必須在1-150之間</message>
</field-validator>
 
欄位OGNL表示式校驗器
<field name="imagefile">
<field-validator type="fieldexpression">
<param name="expression"><![CDATA[imagefile.length() <= 0]]></param>
<message>檔案不能為空</message>
</field-validator>
</field>
 

 

 
4、基於XML配置方式對指定action方法實現輸入校驗
當校驗檔案的取名為ActionClassName-validation.xml時,會對 action中的所有處理方法實施輸入驗證。如果你只需要對action中的某個action方法實施校驗,那麼,校驗檔案的取名應為:ActionClassName-ActionName-validation.xml,其中ActionName為struts.xml中action的名稱。例如:在實際應用中,常有以下配置:
<action name="user_*" class="cn.itcast.action.UserAction" method="{1}“ >
    <result name="success">/WEB-INF/page/message.jsp</result>
    <result name="input">/WEB-INF/page/addUser.jsp</result>
</action>
UserAction中有以下兩個處理方法:
 
public String add() throws Exception{
   ....
}
public String update() throws Exception{
   ....
}
要對add()方法實施驗證,校驗檔案的取名為: UserAction-user_add-validation.xml
要對update()方法實施驗證,校驗檔案的取名為: UserAction-user_update-validation.xml
 
示例程式碼:PersonAction-manage_update-validation.xml  只對update方法進行校驗
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.3//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.3.dtd">
<validators>
    <field name="username">
        <field-validator type="requiredstring"><!-- 指定校驗器 -->
            <param name="trim">true</param>
            <message>使用者名稱不能為空!</message>
        </field-validator>
    </field>
    <field name="mobile">
        <field-validator type="requiredstring"><!-- 指定校驗器 -->
            <param name="trim">true</param>
            <message>手機號不能為空!</message>
        </field-validator>
        <field-validator type="regex">
            <param name="expression"><![CDATA[^1[358]\d{9}$]]></param>
            <message>手機號格式不正確!</message>
        </field-validator>
    </field>
    
</validators>

 

 
5、基於XML校驗的一些特點
當為某個action提供了ActionClassName-validation.xmlActionClassName-ActionName-validation.xml兩種規則的校驗檔案時,系統按下面順序尋找校驗檔案:
1.AconClassName-validation.xml
2.ActionClassName-ActionName-validation.xml
系統尋找到第一個校驗檔案時還會繼續搜尋後面的校驗檔案,當搜尋到所有校驗檔案時,會把校驗檔案裡的所有校驗規則彙總,然後全部應用於action方法的校驗。如果兩個校驗檔案中指定的校驗規則衝突,則只使用後面檔案中的校驗規則。
 
當action繼承了另一個action,父類action的校驗檔案會先被搜尋到。
 
假設UserAction繼承BaseAction:
 
<action name="user" class="cn.itcast.action.UserAction" method="{1}">
</action>
訪問上面action,系統先搜尋父類的校驗檔案:BaseAction-validation.xml, BaseAction-user-validation.xml,接著搜尋子類的校驗檔案: UserAction-validation.xml, UserAction-user-validation.xml。應用於上面action的校驗規則為這四個檔案的總和。
 
 
 

相關文章