五、攔截器與標籤庫

1、攔截器概述:

攔截器(interceptor)是Struts2最強大的特性之一,也能夠說是struts2的核心,攔截器可讓你在Action和result被執行以前或以後進行一些處理。同時,攔截器也可讓你將通用的代碼模塊化並做爲可重用的類。Struts2中的不少特性都是由攔截器來完成的。攔截是AOP的一種實現策略。在Webwork的中文文檔的解釋爲:攔截器是動態攔截Action調用的對象。它提供了一種機制可使開發者能夠定義在一個action執行的先後執行的代碼,也能夠在一個action執行前阻止其執行。同時也是提供了一種能夠提取action中可重用的部分的方式。談到攔截器,還有一個詞你們應該知道——攔截器鏈(Interceptor Chain,在Struts 2中稱爲攔截器棧Interceptor Stack)。攔截器鏈就是將攔截器按必定的順序聯結成一條鏈。在訪問被攔截的方法或字段時,攔截器鏈中的攔截器就會按其以前定義的順序被調用。css

2、攔截器原理:

大部分時候,攔截器方法都是經過代理的方式來調用的。Struts 2的攔截器實現相對簡單。當請求到達Struts 2的ServletDispatcher時,Struts 2會查找配置文件,並根據其配置實例化相對的攔截器對象,而後串成一個列表(list),最後一個一個地調用列表中的攔截器。Struts2攔截器是可插拔的,攔截器是AOP的一種實現。Struts2攔截器棧就是將攔截器按必定的順序聯結成一條鏈。在訪問被攔截的方法或字段時,Struts2攔截器鏈中的攔截器就會按其以前定義的順序被調用。html

3、Struts2執行流程圖

                      

 

 

(1)  客戶端(Client)向Action發用一個請求(Request)java

(2)  Container經過web.xml映射請求,並得到控制器(Controller)的名字web

(3)  容器(Container)調用控制器(StrutsPrepareAndExecuteFilter或FilterDispatcher)。在Struts2.1之前調用FilterDispatcher,Struts2.1之後調用StrutsPrepareAndExecuteFilterajax

(4)  控制器(Controller)經過ActionMapper得到Action的信息算法

(5)  控制器(Controller)調用ActionProxyapache

(6)  ActionProxy讀取struts.xml文件獲取action和interceptor stack的信息。服務器

(7)  ActionProxy把request請求傳遞給ActionInvocationsession

(8)  ActionInvocation依次調用action和interceptorapp

(9)  根據action的配置信息,產生result

(10) Result信息返回給ActionInvocation

(11) 產生一個HttpServletResponse響應

(12) 產生的響應行爲發送給客服端。

4、攔截器流程圖:

                               

 

5、攔截器和過濾器: 

過濾器能夠簡單理解爲「取你所想取」,忽視掉那些你不想要的東西;攔截器能夠簡單理解爲「拒你所想拒」,關心你想要拒絕掉哪些東西,好比一個BBS論壇上攔截掉敏感詞彙。
  1.攔截器是基於java反射機制的,而過濾器是基於函數回調的。
  2.過濾器依賴於servlet容器,而攔截器不依賴於servlet容器。
  3.攔截器只對action起做用,而過濾器幾乎能夠對全部請求起做用。
  4.攔截器能夠訪問action上下文、值棧裏的對象,而過濾器不能。
  5.在action的生命週期裏,攔截器能夠多起調用,而過濾器只能在容器初始化時調用一次。

6、自定義一個攔截器

1 .自定義一個實現Interceptor接口(或者繼承自AbstractInterceptor)的類,反正是要直接或者是間接的實現便可。
2 .在struts.xml中註冊上一步中定義的攔截器。
3 .在須要使用的Action中引用上述定義的攔截器,爲了方便也可將攔截器定義爲默認的攔截器,這樣在不加特殊聲明的狀況下全部的Action都被這個攔截器攔截。
 

                       

 

 
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.opensymphony.xwork2.interceptor;

import com.opensymphony.xwork2.ActionInvocation;
import java.io.Serializable;

public interface Interceptor extends Serializable {
    void destroy();

    void init();

    String intercept(ActionInvocation var1) throws Exception;
}

 

void init() : 該方法在攔截器被建立後會當即被調用,他在攔截器的生命週期內只被調用一次,能夠吧數據的初始化操做放在這個方法裏面完成
void destory():和init方法對象,在攔截器實例被銷燬以前調用,他在他在攔截器的生命週期內只被調用一次,能夠把攔截器的資源釋放放在這個方法中
String intercept(ActionIvocation invocation) :該方法是攔截器的核心,用來添加真正執行攔截工做的代碼。它返回一個字符串做爲邏輯視圖,系統根據返回的字符串跳轉到對應的
視圖資源。每攔截一個動做請求,該方法就會被調用一次,該方法的參數包含了攔截器的Action的引用,能夠經過經過該參數的invoke方法,將控制權交給 下一個攔截器或者是Action的execute方法
正常開發中,咱們實現攔截器只須要使用intercept方法便可,實現上面的接口未免要實現的方法有點多。經常使用的是繼承抽象攔截器類AbstractInterceptor
 
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.opensymphony.xwork2.interceptor;

import com.opensymphony.xwork2.ActionInvocation;

public abstract class AbstractInterceptor implements Interceptor {
    public AbstractInterceptor() {
    }

    public void init() {
    }

    public void destroy() {
    }

    public abstract String intercept(ActionInvocation var1) throws Exception;
}

 

7、攔截器的配置

 

一、攔截器

 

二、攔截器棧

 在實際開發中,常常須要在Action執行前同時執行多個攔截動做,如:用戶登入檢查、權限檢查等。這時,能夠吧多個攔截器組成一個攔截器棧,在執行Action時就要所有執行攔截器棧中的攔截器了。攔截器棧中還能夠包含另外一個攔截器棧。
 
    <!--定義攔截器,攔截器與攔截器棧的定義是相似,只是標籤不一樣-->
    <interceptors>
        <!--定義自定義攔截器-->
        <interceptor name="XXX" class="XXX"/>
        <!--定義攔截器棧-->
        <interceptor-stack name="XXX">
            <interceptor-ref name="XXX"/>
            <interceptor-ref name="XXX"/>
        </interceptor-stack>
    </interceptors> 

 

通常都會使用攔截器棧,由於除了咱們自定義的攔截器外,還須要使用系統默認的攔截器,defaultStack攔截器。

8、案例:

package com.turtle.demo2;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
import org.apache.struts2.ServletActionContext;


public class InterceptorDemo extends MethodFilterInterceptor {

    @Override
    protected String doIntercept(ActionInvocation actionInvocation) throws Exception {
        // 從session中取用戶
        Object user = ServletActionContext.getRequest().getSession().getAttribute("user");
        if(user == null){
            ActionSupport actionSupport = (ActionSupport) actionInvocation.getAction();
            actionSupport.addActionError("抱歉,用戶沒有登入");
            return actionSupport.LOGIN;
        }
        // 放行
        return actionInvocation.invoke();
    }
}

 

 9、UI標籤庫

如下內容均來自該博客:http://www.javashuo.com/article/p-hluftonm-gt.html

 一、概述:

 對於一個MVC框架而言,重點是實現兩部分:業務邏輯控制器部分和視圖頁面部分。Struts2做爲一個優秀的MVC框架,也把重點放在了這兩部分上。控制器主要由Action來提供支持,而視圖則是由大量的標籤來提供支持。
在JavaWeb中,Struts2標籤庫是一個比較完善,並且功能強大的標籤庫,它將全部標籤都統一到一個標籤庫中,從而簡化了標籤的使用,它還提供主題和模板的支持,極大地簡化了視圖頁面代碼的編寫,同時它還提供對ajax的支持,大大的豐富了視圖的表現效果。與JSTL(JSP Standard Library,JSP 標準標籤庫)相比,Struts2標籤庫更加易用和強大。

二、Struts2的模板和主題

Struts2的UI標籤都是基於模板和主題的。所謂模板,就是一些代碼,Struts2標籤使用這些代碼渲染生成相應的HTML代碼。模板是一個UI標籤的外在表現形式,而且每一個標籤都會有本身對應的模板。若是爲全部的UI標籤提供樣式和視覺效果類似的模板, 那麼這一系列的模板就造成了一個主題。
     Struts2 默認提供了4 種主題,分別爲 simple、xhtml、css_xhtml和Ajax。
    simple主題:這是最簡單的主題,使用該主題時,每一個UI標籤只生成最基本的HTML元素,沒有任何附加功能。
    xhtml主題:這是Struts2的默認主題,它對simple主題進行了擴展,提供了佈局功能、Label顯示名稱、以及與驗證框架和 國際化框架的集成。
    css_xhtml:該主題是xhtml的擴展,在對xhtml的基礎之上添加對CSS的支持和控制。
    Ajax:繼承自對xhtml,提供 Ajax支持。

這4種內建主題中,xhtml爲默認主題,但xhtml有必定的侷限性。由於它使用表格進行佈局,而且只支持每一行放一個表單項,這樣一來,一旦遇到複雜的頁面佈局,xhtml就難以勝任了。此時,就須要改變Struts2的默認主題。
     一般,經過設置常量struts.ui.theme,來改變默認主題,具體作法是在struts.xml或者struts.properties文件中增長相應的配置。好比想要設置使用simple的主題,那麼須要在struts.xml中增長以下配置:

<constant name="struts.ui.theme" value="simple"/>

 

或者在struts.properties文件中增長以下配置:

struts.ui.theme=simple

三、Struts2的標籤庫分類:

                           

 

控制標籤

if-elseif-else

<%--1if elseif else的使用 --%>

<% //存入請求域中一個學生的成績

    request.setAttribute("score", 89);

%>

<!-- 判斷學生成績,輸出成績所對應的ABCD -->

<s:if test="#request.score>90">

    優秀

</s:if>

<s:elseif test="#request.score>80">

    良好

</s:elseif>

<s:else>

    通常

</s:else>

 

iterator

<s:iterator value="customers">

<%--s:iterator是struts2的一個迭代標籤,它的value屬性取值是一個OGNL表達式

var屬性:它的取值就是一個普通的字符串.

用了var:把每次遍歷的對象做爲value,把var的值做爲key,存入ContextMap中

沒用var:把每次遍歷的對象壓入棧頂,再下次遍歷以前彈棧(從棧頂移走)。

begin:開始遍歷的索引

end:遍歷的結束索引

step:遍歷的步長。 

status:計數器對象

    count 已經遍歷的集合元素個數

    index 當前遍歷元素的索引值

    odd   是否奇數行

    even  是否偶數行

    first 是否第一行

    last  是否最後一行

--%>

     <TR style="FONT-WEIGHT: normal; FONT-STYLE: normal; BACKGROUND-COLOR: white; TEXT-DECORATION: none">

          <TD><s:property value="custName"/></TD>

          <TD><s:property value="custLevel"/></TD>

          <TD><s:property value="custSource"/></TD>

          <TD><s:property value="custIndustry"/</TD>

          <TD><s:property value="custAddress"/></TD>

          <TD><s:property value="custPhone"/></TD>

     </TR>

</s:iterator>

 

 

數據標籤

property

  id:可選屬性,指定該元素的標識。

  default:可選屬性,若是要輸出的屬性值爲null,則顯示default屬性的指定值。

  escape:可選屬性,指定是否忽略HTML代碼。

  value:可選屬性,指定須要輸出的屬性值,若是沒有指定該屬性,則默認輸出ValueStack棧頂的值

<%-- 輸出值棧中的值 --%>

<s:property value="custName"/>

 

a

<%--使用struts2的超連接標籤發送請求:

    <s:a>鏈接內容</s:a>

    屬性:

    href:指定url路徑

    action:請求的動做名稱(類名)

    namespace:動做名稱所在的名稱空間

    id:指定id

    method:指定Action調用方法

 --%>

 <s:a action="addUIUser" namespace="/user">添加用戶</s:a>

 <s:a action="editUIUser" namespace="/user"> 編輯用戶

     <s:param name="userid" value="%{'1'}"></s:param>

 </s:a>

 <a href="${pageContext.request.contextPath}/user/editUIUser.action?userid=1">原始超連接標籤-編輯用戶</a>

 

debug

     debug標籤用於調試Struts2,使用它會在頁面中生成一個debug標籤,點擊後會顯示服務器各類對象信息,包括值棧、ContextMap等。

<s:debug/>

 

date

<%--s:date標籤的使用:

    它是用於格式化輸出日期

    name屬性:取值是一個ognl表達式,表示要格式化的日期對象

    format屬性:指定格式

    var屬性:取值是一個普通的字符串。

           把格式化好的日期字符串做爲value,把var的取值做爲key。存入contextMap中

--%>

<% request.setAttribute("myDate",new Date());

  /*  SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日");

   String date = format.format(new Date());

   out.println(date); */

%>

${requestScope.myDate}<br/>

<s:property value="#request.myDate"/>

<s:date name="#request.myDate" format="yyyy年MM月dd日" var="sdate"/>

<br>

格式化後的日期:<s:property value="#sdate"/>

<br/>

${sdate}

 

url

<%-- url標籤

    做用:用於存放一個路徑

    屬性:

        action:動做名稱

        namespace:名稱空間

        var:取值是一個普通字符串。他會把action和namespace組成一個url做爲value,把var的取值做爲一個key,存入contextMap中

--%>

<s:url action="addUIUser" namespace="/user" var="myurl"/>

<a href="<s:property value='#myurl'/>">添加用戶——url</a>

 

 

表單標籤

                      

                           

                          

案例:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>註冊界面</title>
    </head>
    <body>
        <s:form action="register" namespace="">
            <s:textfield name="username" label="用戶名" key="Switch"/>       
            <s:password name="password" label="密碼"/>
            <s:radio name="gender" list="#{'0':'男','1':'女'}" label="性別" value="0" />
            <s:textfield name="age" label="年齡"/>
            <s:select name="city" list="#{'bj':'北京','sh':'上海','gz':'廣州','sz':'深圳'}" label="城市" headerKey="-1" headerValue="---請選擇城市---" emptyOption="true"/>
            <s:checkboxlist name="hibbies" list="#{'code':'寫代碼','algorithm':'算法','movie':'電影'}" label="愛好"/>
            <s:checkbox name="married" label="是否已婚" value="true" labelposition="left"/>
            <s:textarea name="description" label="自我介紹" rows="5" cols="20"/>
            <s:file name="phone" label="頭像"/>
            <s:submit value="提交"/>
            <s:reset value="重置"/>
        </s:form>
    </body>
</html>
 
 結果顯示
                               
相關文章
相關標籤/搜索