通過不少年發展,Struts1已經成爲了高度成熟的框架,但隨着時間的發展,Struts1的侷限性和缺點不斷的暴露出來。
如今Struts已經分化成了兩個框架
-第一個是在Struts1的基礎上,融合了另外一個web框架Webwork的Struts2.Struts2實質上是以Webwork爲核心的,和Struts1有很大區別。
-第二個是Shale,與原有Struts1關聯不多,使用了全新的設計思想。java
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
(1)下載Struts2spring
目錄結構 apps:該文件夾下包含了基於Struts2的示例應用 docs:包含了Struts2的相關文檔 lib:包含了Struts2的核心類庫,以及Struts2的第三方類庫 src:包含了Struts框架的全部源代碼
(2)建立web項目,導入struts2所需jar包,lib中有struts2的全部jar包,可是咱們不須要那麼多。數據庫
咱們只把必需的添加到項目便可。將apps目錄下struts2-blank.war壓縮包中的lib目錄下的jar包添加到咱們項目中便可。這是struts2必需的jar包。
apache
struts使用攔截器做爲加強處理,以用戶的邏輯控制器爲目標,建立一個控制器代理,控制器代理回調業務控制器的execute方法處理用戶請求,該方法的返回值決定struts2將怎樣的視圖資源呈現給用戶編程
struts2大體處理流程:後端
(1)瀏覽器發送請求
(2)核心控制器根據請求決定是否調用相應的Action
(3)struts2內置的攔截器鏈會自動對請求進行一些操做
(4)回調Action的execute方法,執行操做。
(5)Action會將處理結果存入stack Context中,並返回字符串,核心控制器根據字符串跳轉到指定的視圖資源。
(6)視圖資源會讀取Stack Context中的信息,向瀏覽器生成響應數據。瀏覽器
只需跟着作便可,先沒必要了解爲什麼這樣作。緩存
(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>
(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>
(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"; } } }
(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>
struts2核心就是核心控制器和業務控制器。
核心控制器StrutsPrepareAndExecuteFilter
StrutsPrepareAndExecuteFilter做爲一個filter運行在web應用中,負責攔截全部用戶請求,該filter 會過濾用戶請求,然 後將請求都交給struts2框架處理。攔截器會默認攔截擴展名爲.action的請求,什麼後綴名都不寫也能夠。例如 hello.action或者hello都會進行攔截。xxx.jsp就不會進行攔截,直接放行。
(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)客戶端發出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核心配置文件是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常量,則後一個文件中配置的常量值會覆蓋前面文件中配置的常量值。
配置文件中經常使用的常量
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類型請求參數和包含所有請求參數。
struts.xml文件中配置和修改常量
在struts.xml文件中配置,使用<constant .../>配置常量。 name:常量名 value:常量值 <constant name="" value=""/>
例子:咱們修改請求後綴爲.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>
編寫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 最後一個超連接訪問成功
在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結尾的請求成功。這也驗證了咱們說的配置文件的加載順序。
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"/>
瞭解便可,不須要深刻。
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> 若是包沒有指定命名空間,則默認的命名空間爲"" 根命名空間爲"/"
包的執行順序
例如http://localhost:8080/Struts2Demo/user/my/hello.action
(1)搜索配置文件全部package的namespace (2)先去匹配命名空間/user/my,若是匹配到,就查找Action,查找到就執行,沒查找到會到默認命名空間查找Action,查找到執行,沒找到報錯。 (3)若是沒匹配到該命名空間,就接着匹配命名空間/user,若是匹配到,就查找Action,查找到就執行,沒查找到會到默認命名空間查找Action,查找到執行,沒找到報錯。 (4)沒匹配到就去根命名空間(」/「)查找action,沒查找到會到默認命名空間查找Action,查找到執行,沒找到報錯。 (5)沒匹配到任何命名空間直接報錯。
開發者須要提供大量的Action,並在struts.xml中配置Action.Action類裏包含了對用戶請求的處理邏輯,由於咱們也稱Action爲業務控制器。
編寫Action處理類
第一種建立處理類方法 :
struts2採用了低侵入式的設計,struts2不要求Action類繼承任何的struts基類,也不須要實現任何接口。Action類只是一個普通的POJO(Plain Ordinary Java Object簡單的java對象)
第二種:建立一個類實現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; }
第三種:繼承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>來指定默認的動做處理類。
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; } }
咱們在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>
在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>
咱們發現這種方式寫的不少代碼相似,至關冗餘,爲了解決這個問題,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>
action的name中可使用通配符 * , * 能夠匹配全部的action, * 的值爲傳入的action名字,例如傳入了addUser.action,那麼 * 的值就爲addUser。method屬性中可使用表達式來獲取 * 的值,{第幾個*}
例如 」 * _ * 「,咱們傳遞add_User,那麼{1}的值就是add,{2}的值就是User。
動態方法調用
使用動態調用前要先將動態調用的常量更改爲true,動態調用默認是false,由於不安全。 <constant name="struts.enable.DynamicMethodInvocation" value="true"></constant> 咱們使用動態方法調用咱們須要的方法。 格式 :動做名稱!方法名稱
咱們配置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>
咱們更改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>
當Action處理完用戶請求時,處理結果應該經過視圖資源實現,但將哪一個視圖呈現給瀏覽者呢。由<result.../>來決定 Action處理完用戶請求後,返回一個普通字符串。整個普通字符串就是一個邏輯視圖名。 經過配置文件將邏輯視圖和物理視圖聯繫起來。一旦系統收到Action返回的邏輯視圖名,就把對應的物理視圖呈現給瀏覽者。 struts2支持多種視圖技術。當一個Action處理用戶請求後,僅僅返回一個字符串,這個字符串只是邏輯視圖名 邏輯視圖名能夠和不少視圖資源關聯。例如 JSP,FreeMarker等
結果類型。
好比咱們邏輯視圖名是success,對應success.jsp,那麼咱們是請求轉發到該頁面仍是重定向呢。這就須要咱們指定結果類型。struts2提供了一系列的內置結果類型,在struts-default.xml中能看到。
<result../>屬性 name:邏輯視圖名稱,應該與Action返回的字符串相同,若是不填寫,默認爲success type:結果視圖類型,不寫的時候默認值爲dispatcher(請求轉發) name是去哪裏,type是怎麼去。
struts內建支持的經常使用結果類型
-chain:Action鏈式處理。當一個Action處理完成以後,系統並不想轉發到視圖資源,而是但願下一個Action進行處理,此時就須要這個類型。 -dispatcher:請求轉發 -redirect:重定向 -redirectAction:重定向到其餘Action -stream:向瀏覽器返回一個InputStream的結果類型(通常用於文件下載)
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>
不一樣包之間的請求轉發
<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> 重定向也是同樣。
自定義結果類型
須要實現一個結果類型類,繼承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()); } }
而後再建立一個Action類 ,什麼都不用寫 public class VcodeAction extends ActionSupport { }
在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>
咱們能夠在自定義的結果類型類中添加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和咱們作的實際上是相同的操做。
全局結果視圖和局部結果視圖
咱們在包中定義了本身的結果類型,只有在本身的包或者子包中才能使用,在別的包中仍是沒法使用這個結果類型,爲了全部的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使用這個類型生成的驗證碼尺寸都同樣。
第一種方式 Struts2提供了一個ServletActionContext對象能夠訪問ServletAPI。 例如 HttpServletRequest request=ServletActionContext.getRequest(); HttpServletResponse response=ServletActionContext.getResponse(); ServletContext context=ServletActionContext.getServletContext(); HttpSession session=request.getSession();
第二種方式,實現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賦值。
struts2容許將一個配置文件分解成多個配置文件,從而進行模塊化的設計,也提升了配置文件的可讀性。 例如咱們有一個商城系統,分爲用戶模塊,訂單模塊等等不少模塊 <struts> <include file="struts-user.xml"/> <include file="struts-order.xml"/> ....... </struts>