Struts2之Action接收請求參數和攔截器



    
技術分析之在Struts2框架中使用Servlet的API
    
    1. 在Action類中也可以獲取到Servlet一些常用的API
        * 需求:提供JSP的表單頁面的數據,在Action中使用Servlet的API接收到,然后保存到三個域對象中,最后再顯示到JSP的頁面上。
            * 提供JSP注冊的頁面,演示下面這三種方式     

  <h3>注冊頁面</h3>
                <form action="${ pageContext.request.contextPath }/xxx.action" method="post">
                    姓名:<input type="text" name="username" /><br/>
                    密碼:<input type="password" name="password" /><br/>
                    <input type="submit" value="注冊" />
                </form>

   
    2. 完全解耦合的方式
        * 如果使用該種方式,Struts2框架中提供了一個類,ActionContext類,該類中提供一些方法,通過方法獲取Servlet的API
        * 一些常用的方法如下
            * static ActionContext getContext()                                                      -- 獲取ActionContext對象實例
            * java.util.Map<java.lang.String,java.lang.Object> getParameters()          -- 獲取請求參數,相當於request.getParameterMap();
            * java.util.Map<java.lang.String,java.lang.Object> getSession()               -- 獲取的代表session域的Map集合,就相當於操作session域。
            * java.util.Map<java.lang.String,java.lang.Object> getApplication()           -- 獲取代表application域的Map集合
            * void put(java.lang.String key, java.lang.Object value)                           -- 注意:向request域中存入值。
    
    3. 使用原生Servlet的API的方式(常用到)
        * Struts2框架提供了一個類,ServletActionContext,該類中提供了一些靜態的方法
        * 具體的方法如下
            * getPageContext()
            * getRequest()
            * getResponse()
            * getServletContext()
    

    
技術分析之結果頁面的跳轉
    
    1. 結果頁面存在兩種方式
        * 全局結果頁面
            > 條件:如果<package>包中的一些action都返回success,並且返回的頁面都是同一個JSP頁面,這樣就可以配置全局的結果頁面。
            > 全局結果頁面針對的當前的包中的所有的Action,但是如果局部還有結果頁面,會優先局部的。使用的標簽是           

 <global-results>
    <result>/demo3/suc.jsp</result>
 </global-results>        

        * 局部結果頁面    

  <result>/demo3/suc.jsp</result>    

    2. 結果頁面的類型
        * 結果頁面使用<result>標簽進行配置,包含兩個屬性
            > name    -- 邏輯視圖的名稱
            > type    -- 跳轉的類型,值一些,需要掌握一些常用的類型。常見的結果類型去struts-default.xml中查找。
                * dispatcher        -- 轉發.type的默認值.Action--->JSP
                * redirect            -- 重定向.    Action--->JSP
                * chain                -- 多個action之間跳轉.從一個Action轉發到另一個Action.    Action---Action
                * redirectAction    -- 多個action之間跳轉.從一個Action重定向到另一個Action.    Action---Action
                * stream            -- 文件下載時候使用的



技術分析之Struts2框架的數據封裝
    
    1. 為什么要使用數據的封裝呢?
        * 作為MVC框架,必須要負責解析HTTP請求參數,並將其封裝到Model對象中
        * 封裝數據為開發提供了很多方便
        * Struts2框架提供了很強大的數據封裝的功能,不再需要使用Servlet的API完成手動封裝了!!
    
    2. Struts2中提供了兩類數據封裝的方式?
        * 第一種方式:屬性驅動
            > 提供對應屬性的set方法進行數據的封裝。
                * 表單的哪些屬性需要封裝數據,那么在對應的Action類中提供該屬性的set方法即可。
                * 表單中的數據提交,最終找到Action類中的setXxx的方法,最后賦值給全局變量。
                
                * 注意0:Struts2的框架采用的攔截器完成數據的封裝。
                * 注意1:這種方式不是特別好:因為屬性特別多,提供特別多的set方法,而且還需要手動將數據存入到對象中.
                * 注意2:這種情況下,Action類就相當於一個JavaBean,就沒有體現出MVC的思想,Action類又封裝數據,又接收請求處理,耦合性較高。
            
            > 在頁面上,使用OGNL表達式進行數據封裝。
                * 在頁面中使用OGNL表達式進行數據的封裝,就可以直接把屬性封裝到某一個JavaBean的對象中。
                * 在頁面中定義一個JavaBean,並且提供set方法:例如:private User user;
                * 頁面中的編寫發生了變化,需要使用OGNL的方式,表單中的寫法:<input type="text" name="user.username">
                
                * 注意:只提供一個set方法還不夠,必須還需要提供user屬性的get和set方法!!!
                    > 先調用get方法,判斷一下是否有user對象的實例對象,如果沒有,調用set方法把攔截器創建的對象注入進來,

/**
 * 屬性驅動方式,把數據封裝到JavaBean的對象中
 * @author Administrator
 */
public class Regist2Action extends ActionSupport{
    
    private static final long serialVersionUID = 6556880331550390473L;
    
    // 注意二:屬性驅動的方式,現在,要提供是get和set方法
    private User user;
    public User getUser() {
        System.out.println("getUser...");
        return user;
    }
    public void setUser(User user) {
        System.out.println("setUser...");
        this.user = user;
    }
    
    public String execute() throws Exception {
        System.out.println(user);
        return NONE;
    }

}


        * 第二種方式:模型驅動
            > 使用模型驅動的方式,也可以把表單中的數據直接封裝到一個JavaBean的對象中,並且表單的寫法和之前的寫法沒有區別!
            > 編寫的頁面不需要任何變化,正常編寫name屬性的值
            > 模型驅動的編寫步驟:
                * 手動實例化JavaBean,即:private User user = new User();
                * 必須實現ModelDriven<T>接口,實現getModel()的方法,在getModel()方法中返回user即可!!

/**
 * 模型驅動的方式
 *     實現ModelDriven接口
 *  必須要手動實例化對象(需要自己new好)
 * @author Administrator
 */
public class Regist3Action extends ActionSupport implements ModelDriven<User>{
    
    private static final long serialVersionUID = 6556880331550390473L;
    
    // 必須要手動實例化
    private User user = new User();
    // 獲取模型對象
    public User getModel() {
        return user;
    }
    
    public String execute() throws Exception {
        System.out.println(user);
        return NONE;
    }

}

 



技術分析之Struts2把數據封裝到集合中
    
    1. 封裝復雜類型的參數(集合類型 Collection 、Map接口等
    2. 需求:頁面中有可能想批量添加一些數據,那么現在就可以使用上述的技術了。把數據封裝到集合中
    3. 把數據封裝到Collection中
        * 因為Collection接口都會有下標值,所有頁面的寫法會有一些區別,注意:

<input type="text" name="products[0].name" />

        * 在Action中的寫法,需要提供products的集合,並且提供get和set方法。
    
    4. 把數據封裝到Map中
        * Map集合是鍵值對的形式,頁面的寫法

   <input type="text" name="map['one'].name" />

        * Action中提供map集合,並且提供get和set方法
    代碼:

/**
 * 屬性驅動的方式,把數據封裝到map集合中
 * @author Administrator
 */
public class Regist5Action extends ActionSupport{
    
    private static final long serialVersionUID = 6556880331550390473L;
    
    private Map<String, User> map;
    public Map<String, User> getMap() {
        return map;
    }
    public void setMap(Map<String, User> map) {
        this.map = map;
    }

    public String execute() throws Exception {
        System.out.println(map);
        return NONE;
    }

}




案例總結之Struts2的攔截器技術
    
    1. 攔截器的概述
        * 攔截器就是AOP(Aspect-Oriented Programming)的一種實現。(AOP是指用於在某個方法或字段被訪問之前,進行攔截然后在之前或之后加入某些操作。)
        * 過濾器:過濾從客服端發送到服務器端請求的
        
        * 攔截器:攔截對目標Action中的某些方法進行攔截
            * 攔截器不能攔截JSP
            * 攔截到Action中某些方法
    
    2. 攔截器和過濾器的區別
        1)攔截器是基於JAVA反射機制的,而過濾器是基於函數回調的
        2)過濾器依賴於Servlet容器,而攔截器不依賴於Servlet容器
        3)攔截器只能對Action請求起作用(Action中的方法),而過濾器可以對幾乎所有的請求起作用(CSS JSP JS)
        
        * 攔截器 采用 責任鏈 模式
            > 在責任鏈模式里,很多對象由每一個對象對其下家的引用而連接起來形成一條鏈
            > 責任鏈每一個節點,都可以繼續調用下一個節點,也可以阻止流程繼續執行
        
        * 在struts2 中可以定義很多個攔截器,將多個攔截器按照特定順序 組成攔截器棧 (順序調用 棧中的每一個攔截器 )
    3. Struts2自帶的攔截器

  1.   Exception : 異常處理機制攔截器
  2.  i18n : 處理中文問題
  3.   modelDriven : 將請求參數,封裝model對象 (Action 實現ModelDriven接口)
  4.  fileUpload :文件上傳
  5.  params : 請求參數轉換封裝
  6.  conversionError : 將類型轉換異常進行處理
  7.   validation : 請求參數校驗
  8.   workflow : 判斷fieldError 是否存在,如果存在,自動跳轉input視圖


   4. Struts2的核心是攔截器,看一下Struts2的運行流程


    
自定義攔截器和配置

用戶登錄(用戶信息保存到session中),如果登錄可以訪問BookAction中的方法

    1. BookAction代碼:

public class BookAction extends ActionSupport {

    private static final long serialVersionUID = 1L;
    public String add(){
        System.out.println("添加圖書");
        return NONE;
    }
    public String delete(){
        System.out.println("刪除圖書");
        return NONE;
    }
}

   
    2.定義攔截器,控制如果用戶未登陸,無法訪問BookAction

public class LoginInterceptor extends MethodFilterInterceptor {
    private static final long serialVersionUID = 1L;

    protected String doIntercept(ActionInvocation invocation) throws Exception {
        //判斷用戶是否登錄
       if(ServletActionContext.getRequest().getSession().getAttribute("user")==null){
           return "input";
       }else{
       //執行像一個方法 
        return invocation.invoke();
    }
 }
}

   
    3. 需要在struts.xml中進行攔截器的配置,配置一共有兩種方式

<struts>
    <!-- 開啟開發者模式 -->
    <constant name="struts.devMode" value="true"></constant>
    <package name="login" namespace="/" extends="struts-default">
    <interceptors>
            <!-- 攔截器  名=實現類 映射  -->
            <interceptor name="loginI" class="cn.it.ation.LoginInterceptor"/>
            <!-- 攔截器棧處理  取名 隨便 望文生義 -->
            <interceptor-stack name="loginStack">
                <interceptor-ref name="defaultStack"/>
                <!--通過攔截器名 找到實現類   :  配置 參數  不攔截的方法  -->
                <interceptor-ref name="loginI">
                    <!-- 你想攔截的方法-->
                    <param name="includeMethods">add,delete</param> 
                    <!-- 排除在外的方法 
                    <param name="excludeMethods">login</param>-->
                </interceptor-ref>
            </interceptor-stack>
        </interceptors>

        <!-- 對所有Action生效 -->
       <default-interceptor-ref name="loginStack"/>
    <action name="user_*" class="cn.it.ation.UserAction" method="{1}">
      <result name="success">/welcome.jsp</result>
      <result name="input">/login.jsp</result>
    </action> 
    <action name="book_*" class="cn.it.ation.BookAction" method="{1}">
    <result name="input">/login.jsp</result><!--配置跳轉視圖  -->
    </action>
   </package>
</struts>


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM