參考《JavaEE 輕量級框架應用與開發—S2SH》html
Struts框架是流行普遍的一個MVC開源實現,而Struts2是Struts框架的新一代產品,是將Struts1和WebWork兩種技術進行兼容、合併的全新的MVC框架。Struts2框架充分發揮了Struts1和WebWork這兩種技術的優點,拋棄原來Struts1的缺點,使得Web開發更加容易。java
Struts1運行原理: web
Struts1工做流程:
(1)客戶端向Web應用發送請求,請求被核心控制器ActionServlet攔截;
(2)ActionServlet根據請求決定是調用業務邏輯控制器仍是將請求轉發給相應JSP頁面;
(3)若調用業務邏輯控制器,則業務邏輯控制器再調用相應的模型來處理用戶的請求;
(4)處理的結果再經過JSP呈現給用戶apache
Struts1缺點:
(1)Struts1僅支持JSP做爲表現層技術
(2)在Model2的基礎上發展得來,徹底基於Servlet API,與Servlet API嚴重耦合,一旦脫離Web服務器,Action的測試將變得很是困難
(3)Action類必須繼承其提供的Action基類,實現處理方法時又必須使用Struts1的專有API,這種入侵式設計的最大弱點在於:一旦系統須要重構,這些Action類將沒有價值。api
Struts2結合Webwork的優點:
(1)Struts2支持更多表現層技術,有更好的適應性。
(2)Action無須跟Servlet API耦合,使得測試更加容易,同時提升代碼重用性;並且不耦合任何Servlet API(攔截器機制)
(3)Struts2具備更好的模塊化和可擴展性(插件機制)。瀏覽器
參考《JavaEE 輕量級框架應用與開發—S2SH》
博文推薦:struts2的核心與工做原理緩存
Struts2是以WebWork爲核心,採用攔截器機制對用戶的請求進行處理服務器
框架結構:
工做流程:
(1)客戶端瀏覽器發送HTTP請求到Web應用
(2)Web容器將請求傳遞到標準ActionContextCleanUp過濾器以消除屬性,而不讓後續過濾器清楚,以延長Action中屬性(包括自定義屬性)的生命週期。ActionContextCleanUp做用
(3)再通過如stimesh等其餘過濾器後,請求傳遞給StrutsPrepareAndExecuteFilter核心控制器
(4)StrutsPrepareAndExecuteFilter調用ActionMapper(Action映射器)肯定調用哪一個Action,再將控制權轉移給ActionProxy代理
(5)ActionProxy代理調用配置管理器ConfigurationManager從配置文件struts.xml中讀取配置信息,而後建立ActionInvocation對象
(6)ActionInvocation在調用攔截器鏈中的攔截器後再調用Action,根據Action返回的結果字符串查找對應的Result
(7)Result調用視圖模板,再以相反的順序執行攔截器鏈,返回HTTP響應
(8)HTTP響應以相反的順序返回給核心控制器StrutsPrepareAndExecuteFilter以及其餘web.xml中定義的過濾器,最終返回給客戶端app
(1)導入Struts所需的Jar包,這裏使用struts-2.3.31版本。下載地址
將struts-2.3.31\apps\struts2-blank.war解壓出來,並在struts2-blank\WEB-INF\lib中獲取運行struts2的最小包
特別注意版本對應問題,因爲不一樣版本的框架封裝的內容會有所不一樣,當跟着教程作的時候,若是步驟徹底相同可是出現異常,那麼很大多是由於版本迭代修改了部份內容所致。框架
(2)在web.xml中配置核心控制器StrutsPrepareAndExecuteFilter
任何MVC框架須要與Web應用整合時都須要藉助web.xml配置文件,因爲StrutsPrepareAndExecuteFilter本質上是一個過濾器,在web.xml中用< filter>以及< filter-mapping>進行配置。而Web應用加載了StrutsPrepareAndExecuteFilter以後就有了Struts2的基本功能。
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>Struts2Demo</display-name> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <!-- 配置StrutsPrepareAndExecuteFilter核心控制器 --> <filter> <!-- 過濾器名 --> <filter-name>struts2</filter-name> <!-- StrutsPrepareAndExecuteFilter核心控制器的實現類 --> <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> </web-app>
配置核心控制器StrutsPrepareAndExecuteFilter就是用其實現類過濾全部的請求。Struts-2.5.8版本中的核心控制器實現類更改成org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter
(3)建立用戶輸入視圖register.jsp
<%@ page language="java" import="java.util.*" contentType="text/html; charset=UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>用戶註冊</title> </head> <body> <form action="register.action" method="post"> username:<input type="text" name="username"/><br/> password:<input type="password" name="password"/><br/> <input type="submit" value="註冊"/><br/> </form> </body> </html>
< form>標籤中的action屬性爲表單參數提交到的地址
(4)建立業務Action
public class RegisterAction { 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() throws Exception{ if(username!=null&&username.length()>0&&password!=null&&password.length()>0){ return "success"; }else{ return "fail"; } } }
如代碼所示,RegisterAction是一個POJO,其屬性應與input.jsp中的表單name屬性對應。則當表單提交時,表單數據會經過setter()方法給Action對象賦值。
除此以外,Action類提供execute()方法返回結果字符串。
Struts2中的Action類優點:
(5)在src下建立struts.xml配置文件
<?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> <!-- 指定Struts2處於開發階段,能夠進行調試 --> <constant name="struts.devMode" value="true"/> <!-- Struts2的Action都必須配置在package裏。這裏使用默認的package --> <package name="default" namespace="/" extends="struts-default"> <action name="register" class="action.RegisterAction"> <!-- 配置execute()方法返回值與視圖資源之間的映射關係 --> <!-- <result name="success">/result.jsp</result> <result name="error">/error.jsp</result> --> <result name="success">/index.jsp</result> </action> </package> </struts>
極客學院Struts2配置文件Wiki
MyEclipse環境中,在src下建立的struts.xml在部署時會自動發佈到WEB-INF/classes目錄下
當Struts2生成ActionProxy代理時,須要訪問Struts2的配置文件,有struts.xml(配置Action相關信息)與struts.properties(配置Struts2全局屬性)兩種。
如上的struts.xml,用< constant>元素設置Struts2的全局屬性,在< package>中定義了一個名爲register的Action,並指定了實現類以及< result>元素用來指定execute()方法返回值與視圖資源之間的映射關係。
而struts.properties則以key=value的形式存儲全局屬性。
如
#指定Web應用的默認編碼集 struts.i18n.encoding=UTF-8 #當struts.xml修改後是否從新加載該文件,在開發階段最好打開 struts.configuration.xml.reload=true #設置瀏覽器是否緩存靜態內容,在開發階段最好關閉 struts.serve.static.browserCache=false
Struts2中的全局屬性詳解
注意:若使用MyEclispe開發,則struts.xml在第一行會報錯,主要是由於MyEclipse沒有找到對應的dtd文件,但這徹底不會影響運行。強迫症能夠把struts-2.3.31\src\core\src\main\resources目錄下的dtd文件導入到MyElipse中,如何導入
Demo運行流程分析:
(1)用戶在input.jsp中輸入數據提交後,所發送請求被核心控制器StrutsPrepareAndExecuteFilter過濾
(2)StrutsPrepareAndExecuteFilter調用ActionMapper,根據表單中action地址來肯定名爲register的Action類處理該請求
(3)而後Struts2框架讀取配置文件struts.xml信息生成ActionProxy
(4)ActionProxy根據package中action元素中的name和class屬性肯定Action實現類爲RegisterAction,並調用
(5)表單中的數據被setter()方法賦值給RegisterAction對象
(6)ActionProxy根據execute()返回值以及action元素中的result元素來肯定返回哪一個視圖資源給用戶
一、Action實現方式
Action是Struts2應用的核心,用於處理用戶的請求。
而Struts2框架實現Action類有如下三種方式
(1)POJO類
如demo所示,謹記Action中的屬性名與表單中的元素屬性名徹底相同,且對於表單中的每一個元素必定要有對應的getter/setter方法,這樣Struts2纔可以自動將請求參數賦值給對應的Action屬性
(2)實現Action接口方式
Struts2提供了一個Action接口,定義了Action處理類應該實現的通用規範
/* * Action接口 */ public interface Action { //定義Action接口中包含的一些結果字符串 public static final String ERROR="error"; public static final String INPUT="input"; public static final String LOGIN="login"; public static final String NONE="none"; public static final String SUCCESS="success"; //處理方法 public String execute() throws Exception; }
(3)繼承ActionSupport類方式
Struts2框架爲Action接口提供了一個實現類ActionSupport,該類提供了不少默認方法,如默認處理用戶請求的方法、數據校驗的方法、獲取國際化信息的方法等
ActionSupport類是Struts2的默認Action處理類,若是配置Action類時沒有指定class屬性,系統自動默認使用ActionSupport類做爲Action的處理類,對用戶的請求進行處理。
API文檔位置:struts-2.3.31/docs/xwork-apidocs/com/opensymphony/xwork2/ActionSupport.html
二、結合ServletAPI
有些時候Action類不訪問ServletAPI是不能實現業務邏輯的,例如跟蹤HTTP Session的狀態。Struts2也提供了一些方法訪問ServletAPI
(1)經過ActionContext
在Struts2框架中,Action能夠經過ActionContext類來訪問ServletAPI
API文檔位置:struts-2.3.31/docs/xwork-apidocs/com/opensymphony/xwork2/ActionContext.html
(2)經過實現訪問ServletAPI的接口並重寫相應方法
接口名 | 描述 |
---|---|
ServletContextAware | 實現該接口的Action能夠直接訪問Web應用的ServletContext實例 |
ServletRequestAware | 實現該接口的Action能夠直接訪問用戶請求的HttpServletRequest實例 |
ServletResponseAware | 實現該接口的Action能夠直接訪問服務器響應的HttpServletResponse實例 |
Struts2的特點是Action再也不與任何ServletAPI耦合,因此不推薦這種方式直接訪問Servlet API
(3)經過ServletActionContext工具類
API文檔位置:struts-2.3.31/docs/struts2-core-apidocs/org/apache/struts2/ServletActionContext.html
參考《JavaEE 輕量級框架應用與開發—S2SH》
配置文件下降了各組件之間的耦合,是聯繫整個Struts2框架的紐帶,經過配置文件將Struts2的核心控制器StrutsPrepareAndExecuteFilter、業務控制器Action以及視圖等組件關聯在一塊兒,實現相應的功能。雖然Struts2提供了Convention插件來管理Action、result,但大多數狀況下配置文件採用XML形式。
一、全局屬性的配置
能夠經過配置全局屬性來改變Struts2框架的一些默認行爲,在Struts2中可使用struts.xml、struts.properties以及web.xml進行配置
若是三個文件同時存在,則會按照struts.xml、struts.properties、web.xml的順序加載常量,後面的會覆蓋前面的,不過一般都在struts.xml中配置。
此外,struts.xml以及struts.properties應該保存在WEB-INF/classes目錄下,MyEclipse環境下能夠保存在src下
(1)經過< constant>元素在struts.xml中定義常量
<struts> <!-- struts.i18n.encoding的值默認爲UTF-8 --> <constant name="struts.i18n.encoding" value="GBK"> </struts>
(2)在struts.properties中定義
struts.i18n.encoding=GBK
(3)經過元素在web.xml中配置
<filter> <init-param> <param-name>struts.i18n.encoding </param-name> <param-value> GBK</param-value> </init-param> </filter>
二、經過包< package>對核心組件進行組織和管理
如demo代碼所示,Struts2配置文件中的包,是由多個Action、多個攔截器、多個攔截器引用組成的集合
<struts> <!-- Struts2的Action都必須配置在package裏。這裏使用默認的package --> <package name="default" namespace="/" extends="struts-default"> <action name="register" class="action.RegisterAction"> <result name="success">/index.jsp</result> </action> </package> </struts>
其中經常使用屬性以下:
(1)name
指定包的名字,當存在多個包時做爲惟一標識
(2)extends
指定包所繼承的其餘包。
struts-default是Struts2框架默認的抽象包,包含了大量結果類型的定義、攔截器及其引用定義等,是配置Action的基礎,所以定義包時都要繼承struts-default包。
定義時,父包要先於子包;Action相同,後面的覆蓋前面
(3)namespace
指定包的命名空間,沒有指定namespace值則爲默認命名空間」/」
Struts2以命名空間的方式來管理Action,同一個命名空間不能有同名的Action
若namespace=」/」,則訪問Action的URL爲:http://ip:port/applicationname/register.action
若namespace=」/user」,則訪問Action的URL爲:http://ip:port/applicationname/user/register.action
配置命名空間後,Struts2按照如下順序搜索Action:
- 指定命名空間,不存在則往下搜索
- 默認命名空間,不存在則往下搜索
- 報錯
三、< include>元素包含其餘配置文件
經常使用於團隊模塊化開發後的整合
<struts> <include file="struts-others.xml"/> </struts>
< include>元素引用的xml文件必須是完整的Struts2配置文件,實際上在< include>元素引用文件時,會單獨解析每一個xml文件
四、< action>配置
Struts2使用package下的action元素來配置Action,配置時須要指定action元素的name和class屬性
- name:指定該Action所處理請求的URL,如name=register,則處理的URL爲register.action
- class:指定Action實現類,若是沒有指定,則默認使用ActionSupport類
除此以外,action元素還可使用method屬性讓Action調用指定方法而不是execute()方法來處理用戶請求。
有時候,一個Action類中包含多個處理業務的方法,而不是execute()方法,如
public class UserAction { private String user; public String getUser() { return user; } public void setUser(String user) { this.user = user; } public String add() throws Exception{ return "add"; } public String del() throws Exception{ return "del"; } }
若要調用add方法以及del方法,則要經過method屬性
<action name="addUser" class="action.UserAction" method="add"></action> <action name="delUser" class="action.UserAction" method="del"></action>
像這種狀況,Struts2還支持 * 通配符以減小冗餘。利用通配符在定義Action的name屬性時使用模式字符串 * ,接下來就能夠在class、method屬性以及< result>子元素中使用{N}的形式表明前面的第N個 * 所匹配的字符串。
如上述代碼可轉化爲下面的代碼:
<action name="*User" class="action.UserAction" method="{1}"></action>
有了通配符以及{N},就能夠經過設計name來大大簡化代碼的編寫
五、result配置
Struts2框架經過配置文件中< action>的< result>子元素配置邏輯視圖名和物理視圖資源之間的映射關係。
配置< result>元素時一般須要指定name和type屬性:
- name屬性指定邏輯視圖名,也就是execute()返回的結果字符串
- type屬性指定結果類型,默認爲dispatcher,表示請求轉發到JSP頁面。
(1)做用範圍:局部result與全局result
<struts> <package name="default" namespace="/" extends="struts-default"> <action name="register" class="action.RegisterAction"> <result name="success">/index.jsp</result> </action> </package> </struts>
<struts> <package name="default" namespace="/" extends="struts-default"> <global-results> <result name="success">/index.jsp</result> </global-results> <action name="register" class="action.RegisterAction"></action> </package> </struts>
若是一個Action中包含了與全局result同名的局部result,則局部result會覆蓋全局result。亦即Action會首先搜索局部result,沒有匹配項再搜索全局result。
(2)結果類型
經過設置type屬性值來肯定返回的結果類型
Struts2學習之結果類型總結
Struts2返回JSON對象的方法總結
六、異常處理
Struts2框架提供了聲明式異常處理方式,經過在struts.xml文件中配置< exception-mapping>元素,指定exception與result屬性肯定映射關係
- exception屬性,用於指定Action出現異常所映射的異常類型
- result屬性,用於指定Action拋出異常時,系統轉入屬性值對應的< action>或< global-results>中的< result>元素
根據做用範圍的不一樣,又可分爲
- 局部異常映射——< exception-mapping>做爲< action>的子元素,針對該Action
- 全局異常映射——< exception-mapping>做爲元素的子元素,針對全部Action
與result做用範圍相似,先局部,再全局
1.過濾器Filter
過濾器Filter是Servlet中較爲實用的一種技術,容許Servlet對用戶請求進行預處理,並對Servlet響應進行後續處理.
在Struts2中,其核心控制器StrutsPrepareAndExecuteFilter就是一個過濾器,用來對用戶請求進行預處理以及後處理
參考詳談Filter過濾器
2.攔截器Interceptor
和過濾器相似,攔截器用於在Action被調用以前對請求進行預處理,以及Action被調用後進行後續處理
參考Struts2攔截器
此外,衆多默認攔截器的用法可參考攔截器詳解
3.案例:Struts2權限驗證功能的過濾器實現與攔截器實現
Struts2 角色權限
在JSP中,爲了減小JSP中嵌入大量的Java代碼,JSP規範制定了JSP標準標籤庫JSTL(JSP Standard Tag Library),提升了JSP頁面的可讀性和可維護性。
而Struts2也有本身獨特的標籤庫,並且更爲強大,不只能夠替代JSTL標籤庫,還適用於任何表示層技術(如Velocity、FreeMarker等)
解壓Struts2提供的struts2-core-x.x.x.jar文件,能夠在META-INF目錄下找到struts2標籤庫描述文件struts-tags.tld
在JSP中使用標籤庫時,須要使用taglib指令引入標籤庫
<%@ taglib prefix="s" uri="/struts-tags" %>
其中prefix=」s」 指定了標籤庫的前綴,uri=」/struts-tags」指定了標籤庫描述文件的路徑。
若是Sevlet規範版本是2.3及如下,還須要在web.xml中增長對標籤庫的定義
<taglib> <taglib-uri>/struts-tags</taglib-uri> <taglib-location>/WEB-INF/lib/**struts2-core-2.0.11.1.jar**</taglib-location> </taglib>