Struts2 教程

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();
    }
相關文章
相關標籤/搜索