1、struts2工做原理(網友總結,千遍一概)java
1 客戶端初始化一個指向Servlet容器(例如Tomcat)的請求
2 這個請求通過一系列的過濾器(Filter)(這些過濾器中有一個叫作ActionContextCleanUp的可選過濾器,這個過濾器對於Struts2和其餘框架的集成頗有幫助,例如:SiteMesh Plugin)
3 接着FilterDispatcher被調用,FilterDispatcher詢問ActionMapper來決定這個請是否須要調用某個Action
4 若是ActionMapper決定須要調用某個Action,FilterDispatcher把請求的處理交給ActionProxy
5 ActionProxy經過Configuration Manager詢問框架的配置文件,找到須要調用的Action類
6 ActionProxy建立一個ActionInvocation的實例。
7 ActionInvocation實例使用命名模式來調用,在調用Action的過程先後,涉及到相關攔截器(Intercepter)的調用。
8 一旦Action執行完畢,ActionInvocation負責根據struts.xml中的配置找到對應的返回結果。返回結果一般是(但不老是,也可 能是另外的一個Action鏈)一個須要被表示的JSP或者FreeMarker的模版。在表示的過程當中可使用Struts2 框架中繼承的標籤。在這個過程當中須要涉及到ActionMapper
在上述過程當中全部的對象(Action,Results,Interceptors,等)都是經過ObjectFactory來建立的。程序員
2、struts2基本配置web
2.1 struts.xml配置文件詳解spring
<struts> <!-- 開發模式下使用,打印更多詳細錯誤信息 --> <constant name="struts.devMode" value="true" /> <!-- 國際化 --> <constant name="struts.i18n.encoding" value="UTF-8"/> <!-- 容許ognl訪問靜態方法 --> <constant name="struts.ognl.allowStaticMethodAccess" value="true" /> <!-- 該屬性指定須要struts2處理的請求後綴,默認值是action,即,全部匹配*.action的請求 都由struts2處理,若是用戶須要指定多個請求後綴,則多個後綴之間以英文逗號","隔開 --> <constant name="struts.action.extension" value="action"/> <!-- 設置瀏覽器是否緩存靜態內容,默認值爲true(生產環境下使用),開發階段最好關閉 --> <constant name="struts.serve.static.browserCache" value="false"/> <!-- 當struts的配置文件修改後,系統是否自動從新加載該文件,默認值false:不從新加載 --> <constant name="struts.configuration.xml.reload" value="true"/> <!-- 默認的視圖主題 --> <constant name="struts.ui.theme" value="simple"/> <!-- 與spring集成時,指定由spring負責管理action對象的建立 --> <constant name="struts.objectFactory" value="spring"/> <!-- 該屬性設置struts2是否支持動態方法調用,默認值true:支持 --> <constant name="struts.enable.DynamicMethodInvocation" value="false"/> <!-- 上傳文件的大小限制 --> <constant name="struts.multipart.maxSize" value="10701096"/> <!-- 引入文件 --> <include file="cn/qjc/action/login/login.xml"></include> <include file="cn/qjc/action/demo/demo01.xml"></include> <include file="cn/qjc/interceptor/interceptor.xml"></include> </struts>
struts2配置文件加載順序apache
a、default.properties:struts2-core**.jar org.apache.struts包中(程序員只能看)瀏覽器
b、struts-default.xml:struts2-core**.jar中(程序員只能看)緩存
c、struts-plugin.xml:在插件的jar包中(程序員只能看)安全
d、struts.xml:在應用的構建路徑頂端。本身定義的Struts配置文件(推薦)app
e、struts.properties:在應用的構建路徑頂端。程序員能夠編寫(不推薦)框架
f、web.xml:配置過濾器時,指定參數。程序員能夠編寫(不推薦)
特別注意:順序是固定的。後面的配置會覆蓋前面的同名配置信息。
加載struts.xml過程
說明:
一、 在啓動的時候加載了三個配置文件 struts-default.xml、struts-plugin.xml、struts.xml
二、 若是這三個文件有相同的項,後面覆蓋前面的。
三、 struts.xml文件必須放在src下才能找到。
2.2 package元素
意義:分模塊開發
屬性:
name:必須的。配置文件中要惟一。就是一個名字。
extends:指定父包。會把父包中的配置內容繼承下來。通常須要直接或間接的繼承一個叫作「struts-default」的包(在struts-default.xml配置文件中)。
若是不繼承該包,那麼Struts2中的核心功能將沒法使用。
abstract:是不是抽象包。沒有任何action子元素的package能夠聲明爲抽象包。
namespace:指定名稱空間。通常以」/」開頭。該包中的動做訪問路徑:namesapce+動做名稱。若是namespace=」」,這是默認名稱空間,和不寫該屬性是同樣的。
2.3 action配置
做用:定義一個動做。
屬性:
name:必須的。動做名稱。用戶用於發起請求。在包中要惟一。
class:指定動做類的全名。框架會經過反射機制實例化。默認是:com.opensymphony.xwork2.ActionSupport。
method:指定動做類中的動做方法。框架會執行該方法。默認是execute()。
<!-- 配置全局視圖:訪問動做時沒有局部視圖,則找全局視圖 --> <package name="default" extends="struts-default" abstract="true"> <global-results> <result name="success">/WEB-INF/login/success.jsp</result> </global-results> </package> <package name="login" namespace="/user" extends="default"> <action name="login" class="cn.qjc.action.login.Login" method="login"> <!-- type默認dispatcher 表示請求轉發 --> <result name="success" type="dispatcher">/WEB-INF/login/success.jsp</result> <result name="error">/WEB-INF/login/error.jsp</result> </action> </package>
3、動做類(Action類)
3.1 編寫動做類的三種方式:
a、POJO(Plain Old Java Object)普通的JavaBean。
/** * 編寫動做類方式一:普通javaBean * @author qjc */ public class Demo1Action { public String seyHello(){ System.out.println("動做類執行了"); return "success"; } }
b、實現com.opensymphony.xwork2.Action接口
/** * 編寫動做類方式二:實現Aaction接口 * @author qjc */ public class Demo2Action implements Action{ @Override public String execute() throws Exception { System.out.println("動做類執行了"); return SUCCESS; } }
c、繼承com.opensymphony.xwork2.ActionSupport(推薦)
意義:提供了一些基本的功能。好比驗證和國際化消息提示等。
/** * 編寫動做類方式三:繼承ActionSupport類 * @author qjc */ public class Demo3Action extends ActionSupport{ }
3.2 ActionSupport用法
在struts框架中,準備了一個ActionSupport類,源碼分析:
代碼段一:
public class ActionSupport implements Action, Validateable, ValidationAware, TextProvider, LocaleProvider, Serializable {
代碼段二:
/** * A default implementation that does nothing an returns "success". * <p/> ActionSupport是一個默認的Action實現,可是隻返回了一個字符串success * Subclasses should override this method to provide their business logic. * <p/>子類須要從新覆蓋整個方法,在這個方法中寫相應的邏輯 * See also {@link com.opensymphony.xwork2.Action#execute()}. * * @return returns {@link #SUCCESS} * @throws Exception can be thrown by subclasses. */ public String execute() throws Exception { return SUCCESS; }
代碼段三:
public static final String SUCCESS = "success";
說明:
一、代碼段一說明了ActionSupport也實現了Action接口(之前寫的類實現了Action接口)
二、代碼段二說明若是程序員寫本身的action繼承了ActionSupport,須要從新覆蓋execute方法便可。
三、這個方法默認的返回的是success;
因此在配置文件中也能夠這樣寫:
<action name="actionSupprotAction"> <result name="success">/baseconfig/successActionSupport.jsp</result> </action>
能夠看到action標籤中沒有class屬性,在struts-default.xml中,
<default-class-ref class="com.opensymphony.xwork2.ActionSupport" />
說明:
若是在action標籤中沒有寫class屬性。那麼根據上述的配置文件,struts2會啓用ActionSupport這個類。因此action標籤中的class屬性能夠不寫。
4、結果類型
一、 每一個action方法都返回一個String類型的值,struts一次請求返回什麼值是由這個值肯定的。
二、 在配置文件中,每個action元素的配置都必須有result元素,每個result對應一個action的返回值。
三、 Result有兩個屬性:
name:結果的名字,和action中的返回值同樣,默認值爲success;
type:響應結果類型,默認值爲dispatcher.
在struts-default.xml文件中,以下面所示
<result-types> <result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult"/> <result-type name="dispatcher" class="org.apache.struts2.dispatcher.ServletDispatcherResult" default="true"/> <result-type name="freemarker" class="org.apache.struts2.views.freemarker.FreemarkerResult"/> <result-type name="httpheader" class="org.apache.struts2.dispatcher.HttpHeaderResult"/> <result-type name="redirect" class="org.apache.struts2.dispatcher.ServletRedirectResult"/> <result-type name="redirectAction" class="org.apache.struts2.dispatcher.ServletActionRedirectResult"/> <result-type name="stream" class="org.apache.struts2.dispatcher.StreamResult"/> <result-type name="velocity" class="org.apache.struts2.dispatcher.VelocityResult"/> <result-type name="xslt" class="org.apache.struts2.views.xslt.XSLTResult"/> <result-type name="plainText"
說明:
一、 從上述能夠看出總共10種類型
二、 默認類型爲ServletDispatcherResult即轉發。
三、 結果類型能夠是這10種結果類型的任意一種。
4.1 dispatcher類型:
dispatcher類型是最經常使用的結果類型,也是struts框架默認的結果類型。
在配置文件中,能夠有兩種寫法:
第一種寫法: <result name="success">/resulttype/successDispatcher.jsp</result> 第二種寫法: <result name="success"> <param name="location">/resulttype/successDispatcher.jsp</param> </result>
下面的圖說明了location的來歷:
4.2 redirect類型:
這種結果類型與dispatcher類型相對,dispatcher結果類型是將請求forwsrd(轉發)到指定的JSP資源;而redirect結果類型,則意味着將請求redirect(重定向)到指定的視圖資源。
redirect與dispatcher差異主要是轉發和重定向的差異:重定向會丟失全部的請求參數、請求屬性,固然也丟失Action處理結果。
注意:
使用redirect類型的結果時,不能重定向到/WEB-INF/路徑下任何資源,由於重定向至關於從新發送請求,而Web應用的WEB-INF/路徑是受保護的。
4.3 redirectAction類型:
這種結果類型與redirect類型很是類似,同樣是從新生成一個全新請求,但與redirect區別在於:redirectAction使用ActionMapperFactory提供的ActionMapper來重定向求情。
即:把結果類型從新定向到action。
能夠接受兩種參數
a) actionName: action的名字
b) namespace:命名空間
第一種方式
<result name="success" type="redirectAction">resulttype/redirectactionAction.action</result>
第二種方式
<result name="success" type="redirectAction"> <!-- actionName: 請求的action的路徑 namespace: 若是不寫,默認就是請求的action的路徑,若是寫,路徑將被從新賦值 --> <param name="actionName"> resulttype/redirectactionAction.action </param> </result>
4.4 其餘類型
freemarker:用於轉發到另一個freemarker模板。(頁面靜態化)
velocity:用於轉發到另一個velocity模板。
httpheader:用於輸出http協議的消息頭。
xslt:XML有關的樣式
redirect:用於重定向到另一個JSP頁面。
redirectAction:用於重定向到另一個動做。
stream:用於文件下載(往後再講。文件上傳和下載)
plainText:以純文本的形式展示頁面。輸出源碼。
4.5 自定義類型
自定義結果類型步驟
以隨機驗證碼圖片爲例
a、編寫一個類,直接或間接實現com.opensymphony.xwork2.Result接口。通常繼承org.apache.struts2.dispatcher.StrutsResultSupport類
/** * 使用自定義結果集加載驗證碼 * @author qjc */ public class Demo02 extends StrutsResultSupport{ private int width=120; private int height=80; private int codeCount=4; private int lineCount=100; @Override protected void doExecute(String finalLocation, ActionInvocation invocation) throws Exception { //輸出結果便可 ValidateCode vc = new ValidateCode(width, height, codeCount, lineCount); BufferedImage image = vc.getBuffImg(); //輸出便可 HttpServletResponse response = ServletActionContext.getResponse(); ImageIO.write(image, "jpeg", response.getOutputStream()); } //此處省略getter and setter ...
}
b、聲明結果類型,而後才能使用
<!--
自定義結果集
--> <package name="p3" extends="struts-default"> <result-types> <!-- 結果類型定義 --> <result-type name="captcha" class="cn.qjc.action.demo.Demo02"></result-type> </result-types> </package>
c、使用
<action name="captcha"> <!--使用自定義結果類型:captcha --> <result name="success" type="captcha"> <param name="width">200</param> </result> </action>
頁面編寫
<body> <form action="${pageContext.request.contextPath }/user/login.action"> 用戶名:<input name="username"><br> 密 碼:<input type="password" name="password"><br> 驗證碼:<input name="code" size="4"> <img src="${pageContext.request.contextPath}/captcha.action"><br> <input type="submit" value="登陸"> </form> </body>
5、Action原型模式
在servlet中,一個servlet只有一個對象,也就是說servlet是單例模式。若是把一個集合寫在servlet屬性中,則要考慮線程安全的問題。
可是在struts2的框架中,並不存在這種狀況,action是多例的。也就是說struts2中的action,只要訪問一次就要實例化一個對象。這樣就不存在線程安全的問題。這也是struts2框架的一個好處。
能夠寫一個類,以下:
package cn.qjc.struts2.action.moreinstance; import com.opensymphony.xwork2.ActionSupport; @SuppressWarnings("serial") public class MoreInstanceAction extends ActionSupport{ public MoreInstanceAction(){ System.out.println("create new action"); } public String execute(){ System.out.println("more instance action"); return SUCCESS; } }
配置文件爲:
<struts> <package name="moreinstance" namespace="/moreinstance"> <action name="moreinstanceAction" class="cn.qjc.struts2.action.moreinstance.MoreInstanceAction"> </action> </package> </struts>
請求兩次http://localhost:8080/struts2/moreinstance/moreinstanceAction.action路徑,若是構造函數中的」create new action」輸出兩次,說明建立了兩次對象。