Struts2核心技術 (一)

struts2

 

struts2發展歷史


     通過不少年發展,Struts1已經成爲了高度成熟的框架,但隨着時間的發展,Struts1的侷限性和缺點不斷的暴露出來。 
     如今Struts已經分化成了兩個框架 

     -第一個是在Struts1的基礎上,融合了另外一個web框架Webwork的Struts2.Struts2實質上是以Webwork爲核心的,和Struts1有很大區別。
     -第二個是Shale,與原有Struts1關聯不多,使用了全新的設計思想。java

MVC思想概述

     java web動態編程技術,經歷了Model和Model2時代。

     Model1時代:整個Web應用幾乎所有由jsp頁面組成,jsp頁面接收處理客戶端請求,對請求處理後直接作出響應,用少許的JavaBean來處理數據庫鏈接訪問等操做。Model1的侷限性很是明顯,jsp頁面同時擔任View和Controller兩種角色,將頁面表現和邏輯處理混雜在一塊兒,代碼重用性極低,增長了擴展和維護難度。

    Model2時代:已經採用了MVC的設計。在Model 2架構中,Servlet做爲Controller,負責接收用戶請求,只包含控制邏輯,而後調用後端來進行具體的邏輯處理。最後轉發到相應的jsp頁面負責顯示。 

    MVC由Model(模型),View(視圖),Controller(控制器)組成。

    javaWeb中的三層架構 
         表現層:MVC,struts2框架實際上是對錶現層的MVC做了優化 
         業務層:service 
         持久層:daoweb

Struts2環境的搭建

(1)下載Struts2spring

目錄結構
            apps:該文件夾下包含了基於Struts2的示例應用
            docs:包含了Struts2的相關文檔 
            lib:包含了Struts2的核心類庫,以及Struts2的第三方類庫
            src:包含了Struts框架的全部源代碼
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

(2)建立web項目,導入struts2所需jar包,lib中有struts2的全部jar包,可是咱們不須要那麼多。數據庫

咱們只把必需的添加到項目便可。將apps目錄下struts2-blank.war壓縮包中的lib目錄下的jar包添加到咱們項目中便可。這是struts2必需的jar包。 
 apache

Struts2架構

struts使用攔截器做爲加強處理,以用戶的邏輯控制器爲目標,建立一個控制器代理,控制器代理回調業務控制器的execute方法處理用戶請求,該方法的返回值決定struts2將怎樣的視圖資源呈現給用戶編程

struts2大體處理流程:後端

(1)瀏覽器發送請求 
(2)核心控制器根據請求決定是否調用相應的Action 
(3)struts2內置的攔截器鏈會自動對請求進行一些操做 
(4)回調Action的execute方法,執行操做。 
(5)Action會將處理結果存入stack Context中,並返回字符串,核心控制器根據字符串跳轉到指定的視圖資源。 
(6)視圖資源會讀取Stack Context中的信息,向瀏覽器生成響應數據。瀏覽器

Struts2入門案例

只需跟着作便可,先沒必要了解爲什麼這樣作。緩存

(1)編輯web應用的web.xml配置文件,配置struts2的核心攔截器。tomcat

<filter>
            <filter-name>struts2</filter-name>
            <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
 </filter>   

 <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
 </filter-mapping>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

(2)從用戶請求開始,咱們實現一個登錄表單

這裏的action屬性比較特殊,不是普通的servlet。
    當表單提交給login時,struts的攔截器會起做用,調用用戶開發的Action處理用戶請求 

        <body>
            <form action="login" method="post">
                用戶名:<input type="text" name="username"><br>
                密   碼:<input type="password" name="password"><br>
                <input type="submit" value="登陸">
            </form>
        </body>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

(3)實現控制器Action類處理用戶請求

咱們已經指出,MVC框架的核心就是控制器,控制器處理具體用戶請求。

這個類實現Action接口,並實現接口的execute方法。  

    該類包含的多個屬性用於封裝用戶的請求參數。 咱們可能如今很難理解,咱們請求的參數是怎麼賦值給這個類的。
    咱們說過,在調用Action方法以前,struts2的內置攔截器會自動負責解析用戶請求參數,並賦值給Action相應的參數

    public class LoginAction extends Action{
                private String username;   //用戶名
                private String password;   //密碼
                public String getUsername() {
                    return username;
                }
                public void setUsername(String username) {
                    this.username = username;
                }
                public String getPassword() {
                    return password;
                }
                public void setPassword(String password) {
                    this.password = password;
                } 
                //判斷用戶名和密碼是否相同
                public String execute(){
                    if(getUsername().equals("cad")&&getPassword().equals("123456")){
                        return "success";
                    }else
                    {
                        return "error";
                    }
                }

            }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

(4)配置Action

咱們用戶發送login請求,那麼若是根據login請求去調用相應的Action實現類呢?這就須要咱們去配置Action。

配置struts.xml ,struts.xml應該放在src的classes路徑下   

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

        <struts>                                    //根元素
            <package name="demo" extends="struts-default"> //包  name隨便取,extends照寫就ok 

                <action name="login" class="com.cad.struts2.LoginAction"> //action name爲login,即爲負責處理login的請求,action默認調用自身的execute方法處理請求
                    <result name="success">/welcome.jsp</result>  //根據返回的字符串轉發到相應頁面
                    <result name="error">/error.jsp</result> 

                </action>
            </package>
        </struts>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

Struts2兩個重要組成部分

struts2核心就是核心控制器和業務控制器。

核心控制器StrutsPrepareAndExecuteFilter

StrutsPrepareAndExecuteFilter做爲一個filter運行在web應用中,負責攔截全部用戶請求,該filter 會過濾用戶請求,然 

後將請求都交給struts2框架處理。攔截器會默認攔截擴展名爲.action的請求,什麼後綴名都不寫也能夠。例如  

hello.action或者hello都會進行攔截。xxx.jsp就不會進行攔截,直接放行。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

(1)啓動Tomcat,tomcat加載web.xml文件。同時加載和初始化核心過濾器,查看struts2源碼,發現核心過濾器的初始化方法中會加載struts.xml等struts2配置文件。

(2)當用戶請求到達時,核心過濾器攔截用戶請求,將請求交給struts2框架來處理,即去匹配struts.xml的內容。 
struts2框架獲取用戶請求後,根據請求的名字來決定調用哪一個業務邏輯組件,實例化相應的類。例如,對於login請求,調用名爲login的Action處理。

(3)struts2的全部Action都被定義在struts.xml文件中,Action有name和class屬性,name決定了該Action處理哪一個用戶請求,class決定了該Action的實現類。

(4)Struts2用戶處理用戶請求的Action實例,並非用戶實現的業務控制器,而是Action代理,他會回調用戶的處理方法,由於用戶實現的業務控制器沒有與Servlet API有任何關係,因此根本沒辦法進行獲取參數等請求處理,而struts2定義了一系列攔截器,會對請求參數解析,傳入到Action中,回調execute方法。

咱們每次請求都會實例化相應的類,因此不會出現線程不安全的狀況。而Servlet爲單例,會出現線程不安全。

業務控制器:

業務控制器就是用戶實現的Action類,Action類中一般包含一個execute方法,該方法返回一個字符串,字符串與struts.xml中的result的name相對應,跳轉到不一樣頁面。
  • 1
  • 2

 

struts2內部運行流程

這裏寫圖片描述

(1)客戶端發出HTTP請求

(2)而後請求被核心過濾器StrutsPrepareAndExecuteFilter攔截

(3)核心過濾器將請求轉發到Action映射器,Action映射器負責識別當前的請求是否須要交由Struts2處理。

(4)Action映射器返回須要struts2處理的信息,StrutsPrepareAndExecuteFilter會建立一個Action代理

(5)Action代理並不知道執行哪個Action,它會向配置管理器詢問調用哪個Action,配置管理器會從struts.xml讀取咱們配置的Action信息。

(6)Action代理建立相關請求的Action對象,調用相關的方法以前,struts2的一系列攔截器會幫咱們作一些操做,例如獲取請求參數等。

(7)而後調用execute方法根據返回的字符串去匹配相應的頁面,

(8)頁面能夠獲取一些頁面模板,而後生成最終頁面,再倒序的執行攔截器的後續操做

(9)最後生成HTTP響應內容

Struts2配置文件

Struts2核心配置文件是struts.xml,該文件主要負責管理業務控制器Action。 

    struts2有不少配置文件,按照如下順序加載配置  
    (在服務器開啓時,加載web.xml文件,而後初始化核心過濾器,核心過濾器的init初始化方法中,
    提供了加載配置文件的方法。因此服務器一啓動,這些配置文件就已經加載到內存中了。 )

        default.properties:該文件保存在struts2-core-2.3.32.jar中的org.apache.struts2包裏面  
                            裏面保存一些常量。 

        struts-default.xml :該文件保存在struts2-core-2.3.32.jar中 
                            定義了一些struts2的基礎Bean和struts2內建支持的結果類型,還有struts2內建的攔截器(攔截器有不少,分爲一系列的攔截器塊,咱們默認使用defaultStack攔截器塊) 

        struts-plugin.xml :該文件保存在struts-xxx-2.3.32.jar等struts2插件jar包中 
                            咱們整合spring等框架時,都須要這種插件的jar包。 

        struts.xml:是web應用默認的本身的struts2配置文件 

        struts.properties :是struts2的默認配置文件 

        web.xml:web應用的配置文件 

        若是多個文件配置了同一個struts2常量,則後一個文件中配置的常量值會覆蓋前面文件中配置的常量值。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

配置文件中經常使用的常量

struts.i18n.encoding:該常量指定struts2應用默認使用的字符集。 

            struts.objectFactory.spring.autoWire:和spring框架整合有關。 

            struts.multipart.parser:指定文件上傳用的組件。默認爲jakarta(即common-fileupload上傳組件) 

            struts.multipart.saveDir:指定上傳文件的臨時保存路徑  

            struts.multipart.maxSize:指定上傳中整個請求所容許上傳的最大字節數。 

            struts.action.extension:指定struts2須要處理的請求後綴。默認值爲.action或者什麼都不寫 

            struts.serve.static.browserCache:設置瀏覽器是否緩存靜態內容,當應用處於開發階段時,咱們但願不緩存,可設置爲false  

            struts.enable.DynamicMethodInvocation:設置struts2是否支持動態方法調用,默認值爲true 

            struts.devMode:設置struts2是否使用開發模式。若是設置爲true,爲開發模式,修改struts.xml配置文件不須要重啓服務器,會顯示更多更友好的錯誤提示。 

            struts.ui.theme:指定視圖主題。 

            struts.url.includeParams:指定struts2生成url時是否包含請求參數。有none,get和all三個值。分別對應不包含,僅包含get類型請求參數和包含所有請求參數。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

struts.xml文件中配置和修改常量

在struts.xml文件中配置,使用<constant .../>配置常量。
            name:常量名
            value:常量值
            <constant name="" value=""/>
  • 1
  • 2
  • 3
  • 4
  • 5
例子:咱們修改請求後綴爲.abc 

                在struts.xml文件中配置 
                    <package name="demo" extends="struts-default">
                        <action name="hello" class="com.cad.struts2.Hello" method="sayHello">
                            <result name="success">/welcome.jsp</result>
                            <result name="error">/error.jsp</result>
                        </action>
                    </package>  
                    //修改請求後綴爲abc
                    <constant name="struts.action.extension" value="abc"></constant>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
編寫jsp頁面 
                <body>
                    //使用默認請求後綴
                    <a href="${pageContext.request.contextPath }/hello.action">後綴爲.action</a>
                    <a href="${pageContext.request.contextPath }/hello">沒有後綴</a>
                    <a href="${pageContext.request.contextPath }/hello.abc">後綴爲.abc</a>
                </body>

                結果爲前兩個都出現404 
                最後一個超連接訪問成功
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

在web.xml文件中配置常量

//修改請求後綴爲do
                <init-param>
                    <param-name>struts.action.extension</param-name>
                    <param-value>do</param-value>
                </init-param>  

                jsp頁面 
                    <body>
                        <a href="${pageContext.request.contextPath }/hello.action">後綴爲.action</a>
                        <a href="${pageContext.request.contextPath }/hello">沒有後綴</a>
                        <a href="${pageContext.request.contextPath }/hello.abc">後綴爲.abc</a>
                        <a href="${pageContext.request.contextPath }/hello.do">後綴爲.do</a>
                    </body> 

                前三個都請求失敗,最後.do結尾的請求成功。這也驗證了咱們說的配置文件的加載順序。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

深刻struts2配置文件

Bean配置

struts2是一個高度可擴展的框架。框架的大部分核心組件,並非硬編碼寫在代碼中,而是以本身的IOC容器管理框架的核心組件。 

struts2以可配置的方式來管理核心組件,從而容許開發者很方便的擴展該框架的核心組件,當開發者須要擴展,替換核心組件時,只須要提供本身組件的實現類,將其部署在struts2的IoC容器中便可。 

struts-default.xml文件中配置了大量的struts2框架的內置Bean。

    咱們在struts.xml中定義Bean時,一般有兩個做用
            -建立該Bean的實例,將該實例做爲struts2框架的核心組件使用。

            -Bean包含的靜態方法須要注入一個值。能夠很方便地容許不建立某個類的實例,卻能夠接受框架常量。

            這個部分只須要了解便可,百分之九十九的struts2應用都不用咱們去定義核心組件和去配置Bean。 

            使用<bean />元素在struts.xml定義Bean
            屬性:
                class:必填屬性。指定了Bean實例的實現類
                type:可選屬性,制定了Bean實例實現的struts2規範,該規範經過某個接口實現。
                name:可選屬性。Bean實例的名字
                scope:可選屬性。指定Bean實例的做用域
                static:可選屬性。指定Bean是否使用靜態方法注入。
                optional:可選屬性。指定該Bean是不是一個可選Bean。

                例如 
                使用自定義的ObjectFactory,實現了ObjectFactory接口。實現類是MyObjectFactory
                <bean type="com.opensymphony.xwork2.ObjectFactory" name="myfactory" class="com.my.MyObjectFactory"/>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

瞭解便可,不須要深刻。

package包配置

struts2框架的核心組件就是Action,攔截器等。struts2使用包來管理Action,攔截器等。 

            屬性
            name:配置包時,必須指定name屬性,是包的惟一標識。  

            extends:屬性值必須是另外一個包的name屬性。指定extends屬性表示繼承其餘包。子包能夠集成一個或多個父包中的攔截器,攔截器棧,action等配置。 

            例如咱們前面項目中定義的 <package name="demo" extends="struts-default"> ,就繼承struts-default.xml中的struts-default包。 

            abstract:可選屬性。指定該包是不是抽象包,抽象包不能包含Action定義。

            namespace:該屬性是一個可選屬性,定義該包的命名空間。一個web應用中可能出現同名Action。同一個命名空間中不能有同名Action 

            某個包指定命名空間後,該包下的全部action的url地址必須是 命名空間+action 

            例如咱們加一個命名空間,則訪問這個動做的時候必須加上命名空間。例如 http://localhost:8080/Struts2Demo/user/hello.action 

            <package name="demo" extends="struts-default" namespace="/user">
                <action name="hello" class="com.cad.struts2.Hello" method="sayHello">
                    <result name="success">/welcome.jsp</result>
                    <result name="error">/error.jsp</result>
                </action>
            </package>  

            若是包沒有指定命名空間,則默認的命名空間爲""  
            根命名空間爲"/"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

包的執行順序

例如http://localhost:8080/Struts2Demo/user/my/hello.action

(1)搜索配置文件全部package的namespace 

        (2)先去匹配命名空間/user/my,若是匹配到,就查找Action,查找到就執行,沒查找到會到默認命名空間查找Action,查找到執行,沒找到報錯。 

        (3)若是沒匹配到該命名空間,就接着匹配命名空間/user,若是匹配到,就查找Action,查找到就執行,沒查找到會到默認命名空間查找Action,查找到執行,沒找到報錯。 

        (4)沒匹配到就去根命名空間(」/「)查找action,沒查找到會到默認命名空間查找Action,查找到執行,沒找到報錯。 

        (5)沒匹配到任何命名空間直接報錯。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

Struts2的Action

開發者須要提供大量的Action,並在struts.xml中配置Action.Action類裏包含了對用戶請求的處理邏輯,由於咱們也稱Action爲業務控制器。

編寫Action處理類

第一種建立處理類方法 :

struts2採用了低侵入式的設計,struts2不要求Action類繼承任何的struts基類,也不須要實現任何接口。Action類只是一個普通的POJO(Plain Ordinary Java Object簡單的java對象)
  • 1
  • 2

第二種:建立一個類實現Action接口,該接口定義了五個字符串常量。還包含一個String execute()方法

public interface Action{
                五個字符串常量
                public static final String  ERROR="errror";
                public static final String  INPUT="input";
                public static final String  LOGIN="login";
                public static final String  NONE="none";
                public static final String  SUCCESS="success"; 
                //處理用戶請求的execute方法
                    public String execute()throws Exception;
            }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

第三種:繼承Action接口的實現類ActionSupport,該類提供了不少的默認方法,包括獲取國際化信息,數據校驗的方法等。大大簡化了Action的開發。咱們開發中選擇第三種

配置Action

在struts.xml文件中配置。struts2使用包來組織action。因此action定義放在包定義的下面 。

            <action.../>
            屬性
                name:action的名字
                class:指定該action的實現類,class屬性並非必須的,若是咱們不指定class屬性,系統默認使用ActionSupport類 


        配置Action的默認處理類
            若是咱們不指定<action>中的class屬性,默認使用ActionSupport類。
            咱們可使用<default-class-ref class=""></default-class-ref>來指定默認的動做處理類。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

Action的方法調用

咱們繼承的ActionSupport,當咱們執行Action的時候,默認執行他的execute方法,如今咱們來執行本身的方法。< action >中有一個method屬性,能夠指定用戶調用哪一個方法。

例子:
            咱們寫一個Action類,類裏有四個方法。
                    public class Hello extends ActionSupport{
                        public String addUser(){
                            System.out.println("添加用戶");
                            return SUCCESS;
                        }
                        public String updateUser(){
                            System.out.println("修改用戶");
                            return SUCCESS;
                        }

                        public String selectUser(){
                            System.out.println("查詢用戶");
                            return SUCCESS;
                        }

                        public String deleteUser(){
                            System.out.println("刪除用戶");
                            return SUCCESS;
                        }
                    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
咱們在struts.xml中配置咱們的action 

        <package name="demo" extends="struts-default">

                <action name="addUser" class="com.cad.struts2.Hello" method="addUser">
                            <result name="success">/welcome.jsp</result>
                            <result name="error">/error.jsp</result>
                </action> 

                <action name="updateUser" class="com.cad.struts2.Hello" method="updateUser">
                            <result name="success">/welcome.jsp</result>
                            <result name="error">/error.jsp</result>
                </action> 

                <action name="selectUser" class="com.cad.struts2.Hello" method="selectUser">
                            <result name="success">/welcome.jsp</result>
                            <result name="error">/error.jsp</result>
                </action> 

                <action name="deleteUser" class="com.cad.struts2.Hello" method="deleteUser">
                            <result name="success">/welcome.jsp</result>
                            <result name="error">/error.jsp</result>
                </action>

        </package>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
在jsp頁面中請求action
                    <body>
                        <a href="${pageContext.request.contextPath }/addUser">添加用戶</a>
                        <a href="${pageContext.request.contextPath }/updateUser">修改用戶</a>
                        <a href="${pageContext.request.contextPath }/selectUser">查看用戶</a>
                        <a href="${pageContext.request.contextPath }/deleteUser">刪除用戶</a>
                    </body>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

咱們發現這種方式寫的不少代碼相似,至關冗餘,爲了解決這個問題,struts2提供了通配符的配置方式幫咱們解決這個問題。

使用通配符

咱們在struts.xml文件中配置 
                    <package name="demo" extends="struts-default">

                        <action name="*" class="com.cad.struts2.Hello" method="{1}">
                            <result name="success">/{1}.jsp</result>
                            <result name="error">/error.jsp</result>
                        </action>

                    </package>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

action的name中可使用通配符 * , * 能夠匹配全部的action, * 的值爲傳入的action名字,例如傳入了addUser.action,那麼 * 的值就爲addUser。method屬性中可使用表達式來獲取 * 的值,{第幾個*}

例如 」 * _ * 「,咱們傳遞add_User,那麼{1}的值就是add,{2}的值就是User。

動態方法調用

使用動態調用前要先將動態調用的常量更改爲true,動態調用默認是false,由於不安全。 

        <constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>

        咱們使用動態方法調用咱們須要的方法。 

        格式 :動做名稱!方法名稱
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
咱們配置struts.xml文件 ,不寫method值,也不用通配符
    <package name="demo" extends="struts-default">

        <action name="user" class="com.cad.struts2.Hello" >
            <result name="success">/welcome.jsp</result>
            <result name="error">/error.jsp</result>
        </action>
    </package>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
咱們更改jsp頁面按照動態方法調用的格式,就能夠調用相關的方法。 
            <body>
                    <a href="${pageContext.request.contextPath }/user!addUser">添加用戶</a>
                    <a href="${pageContext.request.contextPath }/user!updateUser">修改用戶</a>
                    <a href="${pageContext.request.contextPath }/user!selectUser">查看用戶</a>
                    <a href="${pageContext.request.contextPath }/user!deleteUser">刪除用戶</a>
            </body>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

管理處理結果

當Action處理完用戶請求時,處理結果應該經過視圖資源實現,但將哪一個視圖呈現給瀏覽者呢。由<result.../>來決定

Action處理完用戶請求後,返回一個普通字符串。整個普通字符串就是一個邏輯視圖名。 

經過配置文件將邏輯視圖和物理視圖聯繫起來。一旦系統收到Action返回的邏輯視圖名,就把對應的物理視圖呈現給瀏覽者。

struts2支持多種視圖技術。當一個Action處理用戶請求後,僅僅返回一個字符串,這個字符串只是邏輯視圖名

邏輯視圖名能夠和不少視圖資源關聯。例如 JSP,FreeMarker等
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

結果類型。

好比咱們邏輯視圖名是success,對應success.jsp,那麼咱們是請求轉發到該頁面仍是重定向呢。這就須要咱們指定結果類型。struts2提供了一系列的內置結果類型,在struts-default.xml中能看到。

<result../>屬性 
            name:邏輯視圖名稱,應該與Action返回的字符串相同,若是不填寫,默認爲success
            type:結果視圖類型,不寫的時候默認值爲dispatcher(請求轉發)
            name是去哪裏,type是怎麼去。
  • 1
  • 2
  • 3
  • 4
  • 5

struts內建支持的經常使用結果類型

-chain:Action鏈式處理。當一個Action處理完成以後,系統並不想轉發到視圖資源,而是但願下一個Action進行處理,此時就須要這個類型。  

    -dispatcher:請求轉發 

    -redirect:重定向 

    -redirectAction:重定向到其餘Action 

    -stream:向瀏覽器返回一個InputStream的結果類型(通常用於文件下載)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

Chain例子

struts.xml文件配置 
        當發送請求demo1時,返回的結果轉發到demo2的Action處理  

        <package name="demo" extends="struts-default">

            <action name="demo1" class="com.cad.struts2.Hello" >
                <result type="chain">demo2</result>
            </action>

            <action name="demo2" >
                <result name="success" >/welcome.jsp</result>
                <result name="error">/error.jsp</result>
            </action> 

        </package>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

不一樣包之間的請求轉發

<package name="demo" extends="struts-default">

    <action name="demo1" class="com.cad.struts2.Hello" >
        <result type="chain"> 
            //由於結果類型都有對應的實現類,咱們到請求轉發的實現類中發現,有actionName和namespace兩個參數,並提供了get和set方法
            //使用的是注入的思想,在請求轉發以前,先調用setNamespace和setActionName賦值
            <param name="actionName">demo2</param>
            <param name="namespace">/user</param>
        </result>
    </action>

</package> 
<package name="demo1" extends="struts-default" namespace="/user">
    <action name="demo2" >
        <result name="success" >/welcome.jsp</result>
        <result name="error">/error.jsp</result>
    </action>
</package> 

重定向也是同樣。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

自定義結果類型

須要實現一個結果類型類,繼承StrutsResultSupport類  
                咱們這裏面使用咱們的驗證碼小工具,輸出一個驗證碼 
                至於這個驗證碼小工具,之前的文章中有詳細的說明。 

            public class VcodeResult extends StrutsResultSupport {

                @Override
                protected void doExecute(String arg0, ActionInvocation arg1) throws Exception {
                    VerifiCode v=new VerifiCode();
                    HttpServletResponse response=ServletActionContext.getResponse();
                    BufferedImage  b=v.getImage();
                    v.output(b, response.getOutputStream());
                }

            }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
而後再建立一個Action類 ,什麼都不用寫
                    public class VcodeAction extends ActionSupport {

                        }
  • 1
  • 2
  • 3
  • 4
在struts.xml中進行配置 
                <package name="vcode" extends="struts-default" > 
                    //配置咱們自定義的結果類型
                    <result-types>
                        <result-type  name="vcode" class="com.cad.struts2.VcodeResult"></result-type>
                    </result-types> 
                    //咱們仍是在咱們的原頁面,因此不須要指定其餘頁面,type即爲咱們的自定義結果類型
                    <action name="vcode" class="com.cad.struts2.VcodeAction">
                        <result name="success" type="vcode"></result>
                    </action>
                </package>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
咱們能夠在自定義的結果類型類中添加get和set方法,來方便咱們的一些參數自定義。
            例如咱們添加了weight,height的get和set方法。 

                    <action name="vcode" class="com.cad.struts2.VcodeAction">
                        <result name="success" type="vcode">
                            <param name="weight">100</param>
                            <param name="height">100</param>
                        </result>
                    </action>    

    咱們就能夠自定義驗證碼的長寬等。這也又體現了咱們的注入思想。
    咱們前面請求轉發前設置nameSpace和actionName和咱們作的實際上是相同的操做。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

全局結果視圖和局部結果視圖

咱們在包中定義了本身的結果類型,只有在本身的包或者子包中才能使用,在別的包中仍是沒法使用這個結果類型,爲了全部的Action都能使用,咱們須要將其變爲全局。

                咱們只須要定義一個包,繼承struts2的默認配置文件
                <package name="myresult" extends="struts-default">
                    <result-types>
                        <result-type  name="vcode" class="com.cad.struts2.VcodeResult"></result-type>
                    </result-types>
                    <global-results>
                        <result>
                            <param name="weight">500</param>
                            <param name="height">1000</param>
                        </result>
                    </global-results>
                </package> 

        而後若是咱們須要這個結果類型,只須要咱們的包繼承這個包便可。
        在<global-results>中配置全局參數,全部的action使用這個類型生成的驗證碼尺寸都同樣。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

Action訪問Servlet API

第一種方式

            Struts2提供了一個ServletActionContext對象能夠訪問ServletAPI。
            例如
                HttpServletRequest request=ServletActionContext.getRequest();
                HttpServletResponse response=ServletActionContext.getResponse();
                ServletContext context=ServletActionContext.getServletContext();
                HttpSession session=request.getSession();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
第二種方式,實現ServletContextAware,ServletRequestAware,ServletResponseAware三個接口 

                public class VcodeAction extends ActionSupport implements ServletContextAware,ServletRequestAware,ServletResponseAware { 
                    //定義三個參數
                    private HttpServletRequest request;
                    private HttpServletResponse response;
                    private ServletContext context;

                    public String execute() throws Exception {

                        return null;
                    } 
                    //實現接口中設置參數的方法
                    @Override
                    public void setServletResponse(HttpServletResponse response) {
                        this.response=response;

                    }
                    @Override
                    public void setServletRequest(HttpServletRequest request) {
                        this.request=request;

                    }
                    @Override
                    public void setServletContext(ServletContext context) {
                        this.context=context;

                    }
                }


                執行流程是什麼,誰調用了set方法?
                struts的內建攔截器有一個ServletConfig的攔截器。
                它會先獲得咱們的動做類的引用,
                而後經過instanceof方法判斷咱們動做類是否屬於ServletContextAware,ServletRequestAware,ServletResponseAware類型
                由於咱們實現了這個接口,固然屬於這個類型
                而後獲取request,response等
                而後調用咱們動做類實現的接口方法 setServletResponse,setServletRequest,setServletContext等爲咱們的request,response賦值。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

分文件編寫配置文件

struts2容許將一個配置文件分解成多個配置文件,從而進行模塊化的設計,也提升了配置文件的可讀性。

            例如咱們有一個商城系統,分爲用戶模塊,訂單模塊等等不少模塊 
            <struts>
                <include file="struts-user.xml"/>
                <include file="struts-order.xml"/>
                .......
            </struts>
相關文章
相關標籤/搜索