1、Struts2是什麼
Struts2是在WebWork2基礎發展而來的。和Struts1同樣, Struts2也是基於MVC的web層框架。
那麼既然有了Struts1,爲什麼還要Struts2?
Struts2和Struts1雖然都是基於MVC的Web框架,可是它們的實現機制徹底不一樣。
Struts1是基於Servlet的實現,而且Struts1的API過度依賴容器,致使了Action開發、測試都很是繁瑣,而Struts2是基於過濾器的實現,API再也不依賴容器,測試過程當中沒必要再模擬Web容器環境,開發、測試較Struts1都有很大的進步。
Struts1的Action是單例模式全部請求共享一個ActionServlet,因此線程必須是安全的,而Struts2每一個請求都會綁定一個Action,再也不有線程安全問題。
Struts2開始支持註解並提供了更爲強大的OGNL標籤庫以及值棧,從類到頁面的開發都更加簡潔高效。
Struts2和Struts1都是基於MVC的Web層框架,因此,他們工做原理仍是同樣的,都是對請求進行攔截、分發、處理,以後返回頁面,只不過他們的實現機制不一樣罷了。
所以,Struts2的工做原理就再也不過多介紹,下面咱們來看如何使用Sturts2搭建一個Web開發環境。
2、Struts2的使用
讓咱們先用Sturts2 展現一個Helloworld。
一、建立web項目struts2_helloworld,添加Struts2的依賴支持
struts2-core-2.3.8.jar
xwork-core-2.3.8.jar
commons-lang3-3.1.jar
ognl-3.0.6.jar
javassist-3.11.0.GA.jar
asm-3.3.jar
asm-commons-3.3.jar
asm-tree-3.3.jar
freemarker-2.3.19.jar
commons-fileupload-1.2.2.jar
commons-io-2.3.jar
二、在web.xml中配置struts2
<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>
三、建立Struts2配置文件struts.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!
DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.1//EN"
"http://struts.apache.org/dtds/struts-2.1.dtd">
<struts>
<package
name="default" namespace="/" extends="struts-default">
<
action
name="hello"
class="com.boya.struts2.web.HelloAction">
<result>
/helloWorld.jsp
</result>
</
action>
</package>
</struts>
注意,與Struts1不一樣,Struts2的配置文件並不放在WEB-INF目錄下,而須要放置在src源碼根目錄下
四、建立Action類
public class HelloAction {
public String execute() {
return "success";
}
}
五、建立返回頁面helloWorld.jsp
如今就完成了一個簡單的Struts2應用。啓動Web服務器,訪問:
就能夠看到咱們建立的helloWorld.jsp頁面了。
3、Sturts2的配置介紹
一、在web.xml配置Strut2過濾器攔截
Sturts1是經過servlet映射實現的對請求的攔截,Struts2是經過Filter完成的對請求攔截。前者會在ActionSerlvet中加載核心配置文件,後者會在StrutsPrepareAndExecuteFilter過濾器中加載。所以,與Struts1不一樣的是,咱們要在web.xml裏面配置Struts2的Filter來攔截請求。
配置方式見上文。
二、Strtus2核心配置文件
Struts2的默認配置文件是struts.xml,須要放置在源碼根目錄下。
struts.xml中的action標籤和Struts1中的做用同樣,都是定義了一種映射關係。package標籤則代表以包的形式來管理action和攔截器,一般狀況下,按將邏輯相關一組業務Action做爲一個模塊放在同一個package下管理。
package有如下屬性;
name:包名稱,其餘包使用name繼承當前包,不能重複
namespace:定義當前包的命名空間,匹配請求URL的路徑部分,不一樣的命名空間下能夠有重名的action
extends:當前包繼承的父包,繼承以後,當前包擁有父包中所定義的任意類、攔截器等
abstract:定義當前包爲一個抽象的包,也就是說不能有action元素在當前包中
action屬性:
name:action名稱,用來匹配請求URL
class:對應的具體Action實現類,默認爲ActionSupport
method:執行action時調用的方法,默認執行execute(),也能夠在URL中動態指定,例如:
<a href="${ctx}/system/user!add">添加用戶</a>
result標籤:定義action的返回跳轉頁面
name:定義頁面跳轉名稱,默認爲success。在action中返回一個對應name的字符串,就會返回到對應的jsp頁面
type:設置返回結果類型,默認爲dispatcher,用於返回jsp頁面
三、URL映射機制
Struts1中,咱們是使用path來映射URL請求的。在Struts2中是使用namespace + action的name來映射URL的。
例如:
namespace="/system" ,
action設置name爲"/user"
那麼這個action對應的URL就是 http://主機地址/工程名/system/user
namespace尋址機制:
對於咱們的一個URL請求,例如http://主機地址/工程名/path1/path2/path3/user
Struts2會自動將URL中的後綴,以及Host和工程名去掉,將/path1/path2/path3這部分認爲是namespace,首先會查找namespace="/path1/path2/path3",若是這個命名空間查找不到,會繼續查找namespace="/path1/path2",仍然沒有的話,會繼續查找上一級命名空間,直到查找到namespace="/"爲止。
查找到命名空間,會在該命名空間的package下查找name="/user"的action。最後將這個請求交給action對應的業務處理類處理。
namespace默認爲"",當在其餘namespace中映射不到的時候,都在這個namespace中尋找。
Struts2是用namespace和actionName來惟一區別一個Action,所以,在同一個namespace下不能配置同名的action,在不一樣的namespace下,能夠有重名action。
四、映射方式配置
在web.xml的過濾器映射中除了這樣配置:
<filter-mapping>
<filter-
name>struts2</filter-
name>
<
url-pattern>/*</
url-pattern>
</filter-mapping>
也可使用擴展名配置:
<filter-mapping>
<filter-
name>struts2</filter-
name>
<
url-pattern>*.action</
url-pattern>
</filter-mapping>
action是struts2默認支持的擴展名。/*在完成*.action的基礎映射功能下,提供了額外的支持
a、用於訪問classpath中特定的靜態資源(若是是/struts、或者/static開始的資源,則在classpath下查找特定的包下面的匹配資源;)
b、支持無後綴的action請求
使用/*方式映射時:
訪問/struts或/static目錄,不但願加載strtus的靜態資源的配置方式
<constant name="struts.serve.static" value="false" />
但願強制使用擴展名映射的配置方式
<constant name="struts.action.extension" value="action" />
一樣可使用上面的配置修改struts2的默認擴展名
<constant name="struts.action.extension" value="do" />
不但願映射某個目錄時(目錄須要是一個正則表達式,所以須要使用.*的方式表示)
<constant name="struts.action.excludePattern" value="/dwr/.*,/noaction/.*" />
五、Action的方法映射
a、Action的方法映射能夠經過method指定,未指定method方法時,默認執行execute()方法
b、映射方法還能夠在URL中動態指定(動態方法調用DMI)
例如訪問 http://localhost:8080/struts2_helloworld/hello!print 會調用hello對應的Action中的print()方法
注:可使用struts.enable.DynamicMethodInvocation參數配置DMI的開啓關閉,默認爲開啓
<constant name="struts.enable.DynamicMethodInvocation" value="false" />
c、使用通配符映射
<action name="*_*" class="com.boya.struts2.web.{1}Action" method="{2}">
<result>
/{0}.jsp
</result>
</action>
使用{1}{2}{3}...{9}的順序來匹配*,{0}匹配總體
注:Struts2的通配符配置方式,極不靈活,不推薦使用
六、設置返回結果類型
返回結果類型能夠經過result標籤的type屬性配置,默認類型爲dispatcher,用於返回jsp頁面。經常使用的返回結果類型有redirect、chain、json等
redirect類型配置(重定向到一個新的URL請求):
<result name="success" type="redirect">/hello.jsp?name=${name}</result> <!--重定向到一個jsp頁面-->
<result name="success" type="redirect">/hello.action</result> <!--重定向到一個acton請求-->
redirectAction類型配置(重定向到其餘action):
<result type="redirectAction">
<param name="namespace">/</param> <!--重定向Action所在的命名空間,默認爲當前命名空間-->
<param name="actionName">user</param> <!--重定向的Action名稱-->
<param name="method">login</param> <!--重定向Action的方法名稱-->
<param name="name">boya</param> <!--重定向傳參-->
<param name="password">123456</param> <!--重定向傳參-->
</result>
chain類型配置,配置相似redirectAction(鏈到其餘action,也就是轉發操做):
<result type="chain">
<param name="namespace">/</param> <!--Action所在的命名空間,默認爲當前命名空間-->
<param name="actionName">user</param> <!--Action名稱-->
<param name="method">login</param> <!--Action的方法名稱-->
</result>
json類型配置
a、添加struts2-json-plugin-2.3.8.jar
b、Action代碼(省略getter、setter方法,省略User實體類):
public
class JsonAction
extends ActionSupport {
private Map<String,Object> dataMap;
public String json() {
dataMap =
new HashMap<String, Object>();
User user =
new User();
user.setName("張三");
user.setAge(50);
dataMap.put("user", user);
return SUCCESS;
}
}
c、配置struts.xml
<package
name="json" extends="struts-default,json-default" >
<
action
name="json"
class="com.boya.struts2.web.JsonAction">
<result
type="json">
<
param
name="root">dataMap</
param>
</result>
</
action>
</package>
package須要繼承"json-default"
result類型須要配置爲json
result參數:
root:指定返回屬性,默認返回全部有返回值的getter方法的值
excludeNullProperties:是否返回值爲空的屬性,值爲boolean類型
ignoreHierarchy:是否忽略父類屬性,值爲boolean類型
includeProperties:指定返回root中的哪些屬性,值爲正則表達式,可以使用逗號分隔設置多個
excludeProperties:指定排除root中的哪些屬性,值爲正則表達式,可以使用逗號分隔設置多個
d、返回內容:
{"user":{"age":22,"name":"張三"}}
excludeProperties和includeProperties的驗證區別:
首先,假設dataMap中返回結果爲:{"users":[{"age":22,"name":"張三","password":"123456"},{"age":40,"name":"李四","password":"654321"}]}
設置了排除或包含的屬性後,以上結果須要驗證的元素有users、users[0]、users[0].age、users[0].name、users[0].password、users[1]、users[1].age、users[1].name、users[1].password
若是要排除password屬性,須要設置<param name="excludeProperties">users.*\.password</param> ,excludeProperties是將正則表達式做爲總體分別匹配以上各元素,這樣就會把password排除掉。
若是要只包含name屬性,則不能設置爲<param name="includeProperties">users.*\.name</param>,includeProperties會將正則表達式拆爲users.*、users.*\.name(對分隔符,數組索引符合,對象屬性間的點鏈接符等進行分割處理),這兩個正則分別與上面各元素匹配,而users.*就會匹配所有元素,因此沒法排除。
要精確包含name屬性,須要設置爲:<param name="includeProperties">users\[\d+\]\.name</param> ,而這時,正則表達式會被拆爲users, users\[\d+\], users\[\d+\]\.name ,最終只輸出name屬性。
4、Action處理
一、接收參數
a、使用屬性來接收參數
例如,在UserAction中定義以下屬性,並添加getter、setter方法
private String name;
private String password;
jsp使用對應名稱的控件
用戶名<input type="text" name="name"><br>
密碼<input type="password" name="password"><br>
這樣就能夠把提交的參數值傳給UserAction的屬性。
也能夠經過URL將參數值傳遞給Action,如:
b、使用DomainModel接收參數
例如,在UserAction中添加實體Bean類型的屬性,一樣須要添加getter、setter方法
private User user;
jsp的控件名稱使用「對象.屬性」形式,如
用戶名<input type="text" name="user.name"><br>
密碼<input type="password" name="user.password"><br>
這樣,提交的參數會自動封裝如user對象中。在Action方法中,使用user.getName()就能夠獲取提交的用戶名
使用URL傳遞參數就是這樣的形式:
二、獲取web容器的request和session
Struts2不像Struts1那樣依賴容器,默認狀況下,request、session這些容器對象都是隱藏的,而且Struts2層分別使用RequestMap、SessionMap對request、session進行封裝,是咱們可使用Map的key-value形式對request、session進行操做。咱們能夠獲取RequestMap來做爲request使用,也能夠像傳統web開發那樣獲取一個HttpServletRequest對象。
a、非IoC方式
這種方式主要是利用了com.opensymphony.xwork2.ActionContext類以及org.apache.struts2.ServletActionContext類,分別用於獲取RequestMap和HttpServletRequest對象。
獲取RequestMap、SessionMap對象
Map request = (Map)ActionContext.getContext().get("request");
Map session = ActionContext.getContext().getSession();
獲取HttpServletRequest、HttpSession對象
HttpServletRequest request = ServletActionContext.getRequest();
HttpSession session = request.getSession();
b、IoC方式
這種方式相似SpringIoc控制反轉,是使用依賴注入的方式得到request和session對象的。
獲取RequestMap、SessionMap對象,Action須要實現RequestAware, SessionAware接口
private Map request;
private Map session;
@Override
public
void setRequest(Map request) {
this.request = request;
}
@Override
public
void setSession(Map session) {
this.session = session;
}
獲取HttpServletRequest、HttpSession對象,Action須要實現ServletRequestAware接口
private HttpServletRequest request;
private HttpSession session;
@Override
public
void setServletRequest(HttpServletRequest request) {
this.request = request;
this.session = request.getSession();
}