走進Struts2(二) — Struts2的基石(攔截器)

攔截器(Interceptor)是Struts2的基石,攔截器的主要作用是在Action執行之前和Result執行之後進行一些特定功能的處理機制。


如圖,攔截器是用來負責在Action執行之前和Result執行之後處理一些功能的類。每個不同的攔截器,它們分別執行不同的功能處理,而運行的時機就是在Action執行之前和Result執行之後,需要注意的是在執行Action之前和Result之後,攔截器的執行順序是正好相反的。

一、攔截器的好處

  • 1.簡化Action的實現,可以把很多功能從Action中獨立出來,大量減少了Action的代碼書寫。
  • 2.功能更單一,把功能從Action中分離出來,分散到不同的攔截器裏面,這樣使每個攔截器和Action的功能更加單一,便於維護。
  • 3.通用代碼模塊化和重用性,把Action中的功能分離出來,放到攔截器去實現,這樣就能實現多個Action中通用的代碼進行模塊化,多個Action公用一個攔截器
  • 4.實現AOP,Struts2通過攔截器實現了AOP(面向切面編程),AOP是一種分散實現關注功能的編程模式。
  • 攔截器將通用需求功能從不相關的Action之中分離出來,能夠使得很多Action共享同一個行爲,一旦行爲發生變化,不必修改很多Action,只要修改這個行爲就可以了。
  • 二、預定義的攔截器
  • 在Struts-default.xml中,提供了很多預定義的攔截器
  • <interceptors>
                <interceptor name="alias" class="com.opensymphony.xwork2.interceptor.AliasInterceptor"/>
                <interceptor name="autowiring" class="com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor"/>
                <interceptor name="chain" class="com.opensymphony.xwork2.interceptor.ChainingInterceptor"/>
                <interceptor name="conversionError" class="org.apache.struts2.interceptor.StrutsConversionErrorInterceptor"/>
                <interceptor name="cookie" class="org.apache.struts2.interceptor.CookieInterceptor"/>
                <interceptor name="clearSession" class="org.apache.struts2.interceptor.ClearSessionInterceptor" />
                <interceptor name="createSession" class="org.apache.struts2.interceptor.CreateSessionInterceptor" />
                <interceptor name="debugging" class="org.apache.struts2.interceptor.debugging.DebuggingInterceptor" />
                <interceptor name="externalRef" class="com.opensymphony.xwork2.interceptor.ExternalReferencesInterceptor"/>
                <interceptor name="execAndWait" class="org.apache.struts2.interceptor.ExecuteAndWaitInterceptor"/>
                <interceptor name="exception" class="com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor"/>
                <interceptor name="fileUpload" class="org.apache.struts2.interceptor.FileUploadInterceptor"/>
                <interceptor name="i18n" class="com.opensymphony.xwork2.interceptor.I18nInterceptor"/>
                <interceptor name="logger" class="com.opensymphony.xwork2.interceptor.LoggingInterceptor"/>
                <interceptor name="modelDriven" class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/>
                <interceptor name="scopedModelDriven" class="com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor"/>
                <interceptor name="params" class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>
                <interceptor name="actionMappingParams" class="org.apache.struts2.interceptor.ActionMappingParametersInteceptor"/>
                <interceptor name="prepare" class="com.opensymphony.xwork2.interceptor.PrepareInterceptor"/>
                <interceptor name="staticParams" class="com.opensymphony.xwork2.interceptor.StaticParametersInterceptor"/>
                <interceptor name="scope" class="org.apache.struts2.interceptor.ScopeInterceptor"/>
                <interceptor name="servletConfig" class="org.apache.struts2.interceptor.ServletConfigInterceptor"/>
                <interceptor name="sessionAutowiring" class="org.apache.struts2.spring.interceptor.SessionContextAutowiringInterceptor"/>
                <interceptor name="timer" class="com.opensymphony.xwork2.interceptor.TimerInterceptor"/>
                <interceptor name="token" class="org.apache.struts2.interceptor.TokenInterceptor"/>
                <interceptor name="tokenSession" class="org.apache.struts2.interceptor.TokenSessionStoreInterceptor"/>
                <interceptor name="validation" class="org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor"/>
                <interceptor name="workflow" class="com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor"/>
                <interceptor name="store" class="org.apache.struts2.interceptor.MessageStoreInterceptor" />
                <interceptor name="checkbox" class="org.apache.struts2.interceptor.CheckboxInterceptor" />
                <interceptor name="profiling" class="org.apache.struts2.interceptor.ProfilingActivationInterceptor" />
                <interceptor name="roles" class="org.apache.struts2.interceptor.RolesInterceptor" />
                <interceptor name="jsonValidation" class="org.apache.struts2.interceptor.validation.JSONValidationInterceptor" />
                <interceptor name="annotationWorkflow" class="com.opensymphony.xwork2.interceptor.annotations.AnnotationWorkflowInterceptor" />
                <interceptor name="multiselect" class="org.apache.struts2.interceptor.MultiselectInterceptor" />
    </interceptors>

幾個常用的攔截器

1.params攔截器,把請求參數設置到相應的Action的屬性去的,並自動進行類型轉換。

2:staticParams攔截器,將struts.xml配置文件裏定義的Action參數,設置到對應的Action實例中,Action參數使用<param>標籤,是<action>標籤的子元素。

注意:如果request裏面有account參數,而struts.xml中也有account參數,Action中最終的值是誰?

       在Action初始化過後,就會把struts.xml中配置的數據設置到Action實例中相應的屬性上去。然後,把用戶請求的數據設置到Action實例中相應的屬性上去。

3.prepare攔截器,在Action執行之前調用Action的prepare()方法,這個方法是用來準備Action執行之前要做的工作。它要求我們的Action必需實現com.opensymphony.xwork2.Preparable接口,一般都是與ModelDriven一起使用

4.modelDriven攔截器,如果Action實現ModelDriven接口,它將getModel()取得的模型對象存入OgnlValueStack中

5.chain攔截器,將前一個執行結束的Action屬性設置到當前的Action中。它被用在ResultType爲“chain”所指定的結果的Action中,該結果Action對象會從值棧中獲得前一個Action對應的屬性,它實現Action鏈之間的數據傳遞

6.validation攔截器,調用驗證框架讀取 *-validation.xml文件,並且應用在這些文件中聲明的校驗

7.token攔截器(令牌攔截器),覈對當前Action請求(request)的有效標識,防止重複提交。使用標籤<s:token>可以生成表單令牌,該標籤會在session中設置一個預期的值並且在表單中創建一個隱藏的input字段。Token攔截器會檢查這個令牌,如果不合法,將不會執行action,注意這個攔截器需要手工添加,還需要配置一個invalid.token的result。

8.timer攔截器,記錄ActionInvocation餘下部分執行的時間,並做爲日誌信息記錄下來,便於查找性能優化。

預定義的攔截器棧

在struts-default.xml中給出了Struts2的默認的預定義攔截器棧defaultStack

  • <interceptors>
    <interceptor>。。。。
    <interceptor-stack>。。。
    <default-interceptor-ref>。。。。
    </interceptors>
    1.<interceptor>用來定義一個攔截器,僅僅是一個定義,還沒有被Action來引用它。name屬性作爲唯一標誌,而class屬性就是這個攔截器的實現類的全類名。攔截器的實現類都應該是com.opensymphony.xwork2.interceptor.Interceptor這個接口的實現類
  • 2.<interceptor-stack>定義了一個攔截器棧,這個棧中可以引用其他已經定義好的攔截器。攔截器棧簡化了動作類Action在引用攔截器時的操作。

    因爲大多數動作類Action在引用攔截器的時候都不會僅僅引用一個攔截器,而是引用一組攔截器。Action在引用的時候,只需要引用這個攔截器棧就可以了,而不是引用每一個攔截器

    攔截器的調用順序

  • (1).要找它自己有沒有聲明攔截器的引用,即<action>元素有沒有<interceptor-ref>子元素,如果有,則不用繼續再找,如果沒有,(2)。

    (2):在這個<action>所在的包有沒有聲明默認的攔截器引用,即<package>元素的<default-interceptor-ref>子元素, 如果有,則不用繼續再找,直接使用這些攔截器,如果沒有,(3)。

  •  (3):遞歸地尋找當前包的父包有沒有聲明默認的攔截器引用,直到找到有攔截器引用就爲止

  • 注意:三者是覆蓋關係


  • 三、自定義攔截器
所有的攔截器都要實現com.opensymphony.xwork2.interceptor.Interceptor接口

public interface Interceptor {
    void destroy();
    void init();
    String intercept(ActionInvocation invocation) throws Exception;
}
自定義登錄攔截器

判斷用戶是否登錄,如果沒有返回登錄頁面

public class PermissionInterceptor implements Interceptor {

	private static final long serialVersionUID = 1L;

	@Override
	public void destroy() {
	}

	@Override
	public void init() {
	}

	@Override
	public String intercept(ActionInvocation invocation) throws Exception {

		HttpSession session = ServletActionContext.getRequest().getSession();
		Object obj = session.getAttribute("user");
		if(obj==null){
			return "login";
		}else{
			return invocation.invoke();
		}
	}

}

配置struts.xml文件

創建父包

<package name="mydefault" extends="struts-default">
		<interceptors>
			<interceptor name="PermissionInterceptor" class="cn.cil.interceptor.PermissionInterceptor"></interceptor>
			<interceptor-stack name="mydefaultStack">
				<interceptor-ref name="PermissionInterceptor"></interceptor-ref>
				<interceptor-ref name="defaultStack"></interceptor-ref>
			</interceptor-stack>
		</interceptors>
	</package>
有需要使用自定義的權限攔截器,就可以繼承這個pacjage

<package name="struts" namespace="/user" extends="mydefault">
	
		<action name="user_*" class="cn.cil.domain.User" method="{1}">
		<interceptor-ref name="mydefaultStack"></interceptor-ref>
			<result>/listUsers.jsp </result>
			<result name="input">/{1}.jsp</result>
			<result name="login">/login.jsp</result>
		</action>
		<action name="download" class="cn.cil.domain.User" method="download">
			<interceptor-ref name="mydefaultStack"></interceptor-ref>
			<result type="stream" name="success">
					<param name="contentType">application/octet-stream</param>
					<param name="inputStream">inputStream</param>
					<param name="contentDisposition">attachment;filename=${filename}</param>
			</result>
			<result name="login">/login.jsp</result>
		</action>
</package>

向攔截器傳入參數

同一個攔截器爲不同的Action服務的時候,需要根據傳入的參數進行處理上的變化。比如說,一個記錄日誌的攔截器,可以根據配置來決定到底把日誌記錄在數據庫還是文件裏面。

可以把這種配置數據作爲一個參數,在配置的時候設置值,會自動傳入攔截器中

<interceptor-ref name=“myInterceptor”>
            	<param name="param">params</param>
        </interceptor-ref>

public class MyInterceptor implements Interceptor{
	private String param;
	public void setParam(String param) {
		this.param = param;
	}
	public void destroy() {
	}
	public void init() {
	}
	public String intercept(ActionInvocation invocation) throws Exception {
		System.out.println("接到param的參數=="+this.param);
		if("params".equalsIgnoreCase(this.param)){
			System.out.println("記錄日誌到數據庫");
		}else{
			System.out.println("記錄日誌到文件");
		}
		String result = invocation.invoke();
		return result;
	}	
}
注意setter方法,在初始化這個攔截器的時候,Struts2就會反射的調用對應的setter,把在<param>元素中配置的值設置到param屬性上去


創建數據庫時,最好加上最後的default...,以前都忽視了

create database mydatabase default character set utf8;

Mysql執行本地的sql腳本文件

source c:/a.sql   或   \.c:/a.sql

是在記不住,就敲 help

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章