轉載自:http://www.cnblogs.com/zhhuanl/archive/2011/03/29/1998556.html
四種共同點:
對一類url,或所有url進行業務處理
對各種url之類進行匹配,查找,執行相應操作,與action相比較而言,action只能針對某一特定的url進行匹配,進行操作 如: <form action ="update.action"> action對應的url是固定的,對於struts1.x可能一個action只有一個url
對於struts2.0,一個action可能有多個url,看它實現的方法數量,不過這些url在提交之前都是已經的,固定的。而上面四種可以對任意url進行操作,如<url-pattern>*.action</url-pattern>
區別:1,servlet 流程是短的,url傳來之後,就對其進行處理,之後返回或轉向到某一自己指定的頁面。它主要用來在
業務處理之前進行控制.
2,filter 流程是線性的, url傳來之後,檢查之後,可保持原來的流程繼續向下執行,被下一個filter, servlet接收等,而servlet 處理之後,不會繼續向下傳遞。filter功能可用來保持流程繼續按照原來的方式進行下去,或者主導流程,而servlet的功能主要用來主導流程。
filter可用來進行字符編碼的過濾,檢測用戶是否登陸的過濾,禁止頁面緩存等
3,servlet,filter都是針對url之類的,而listener是針對對象的操作的,如session的創建,session.setAttribute的發生,在這樣的事件發生時做一些事情。
可用來進行:Spring整合Struts,爲Struts的action注入屬性,web應用定時任務的實現,在線人數的統計等
4,interceptor 攔截器,類似於filter,不過在struts.xml中配置,不是在web.xml,並且不是針對URL的,而是針對action,當頁面提交action時,進行過濾操作,相當於struts1.x提供的plug-in機制,可以看作,前者是struts1.x自帶的filter,而interceptor 是struts2 提供的filter.
與filter不同點:(1)不在web.xml中配置,而是在struts.xml中完成配置,與action在一起
( 2 ) 可由action自己指定用哪個interceptor 來在接收之前做事
一,servlet
1, 在web.xml中配置
Servlet
<servlet>
<servlet-name>AutoServlet</servlet-name>
<servlet-class>
com.servlet.AutoServlet
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>AutoServlet</servlet-name>
<url-pattern>/AutoServlet</url-pattern>
</servlet-mapping>
2,定義AutoServlet,繼承HttpServlet,實現方法doGet, doPost
3, 應用:
(1)Struts1.x 就是一個Servlet, 它會在doGet方法中讀取配置文件struts-config.xml進行action的匹配,進行 業務處理
(2)驗證碼生成(也可用action來做)
二,filter
1, web.xml配置
<filter>
<filter-name>checkUrl</filter-name>
<filter-class>com.lvjian.filter.CheckUrl</filter-class>
<init-param>
<param-name>name</param-name>
<param-value>asong</param-value>
//初始化傳參,得到時在filter的init方法中用filterConfig.getInitParameter("name" )
</init-param>
</filter>
<filter-mapping>
<filter-name>checkUrl</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
2, 繼承 javax.servlet.Filter,實現 doFilter(HttpServletRequestrequest, HttpServletResponse response
FilterChain filterChain) 等方法
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
//獲取用戶請求的URI
String request_uri = request.getRequestURI();
//獲取web應用程序的上下文路徑
String contextPath = request.getContextPath();
//去除上下文路徑,得到剩餘部分的路徑
String uri = request_uri.substring(contextPath.length());
//創建會話session
HttpSession session = request.getSession(true);
//保持原有流程不變
filterChain.doFilter( servletRequest , servletResponse );
3,應用:(1)Struts2.0
(2) 進行字符編碼的過濾,檢測用戶是否登陸的過濾等
(3)禁止頁面緩存,原理就是對各個請求的url令其爲空,在doFilter加入:
request.setCharacterEncoding("GB2312");//設置編碼
((HttpServletResponse)response).setHeader("Pragma","No-cache");
((HttpServletResponse)response).setHeader("Cache-Control","no-cache");
((HttpServletResponse)response).setHeader("Expires","0");//禁止緩存
三,listener
1, 在web.xml中配置
<listener>
<listener-class>demo.listener.MyContextLoader</listener-class>
</listener>
//這樣服務器就會在啓動時創建MyContextLoader的一個實例,並開始監聽servlet,session的操作
2, 實現
常用的listener有:
(1)ServletContextListener 監聽ServletContext。
當創建ServletContext時,激發 contextInitialized(ServletContextEvent sce)方法;
當銷燬ServletContext時,激發contextDestroyed(ServletContextEvent sce)方法。
(2)ServletContextAttributeListener監聽對ServletContext屬性的操作,比如增加、刪除、修改屬性。
(3)HttpSessionListener監聽HttpSession的操作。
當創建一個Session時,激發 session Created(HttpSessionEvent se)方法;
當銷燬一個Session時,激發sessionDestroyed (HttpSessionEvent se)方法。
(4)HttpSessionAttributeListener監聽HttpSession中的屬性的操作。
當在Session增加一個屬性時,激發 attributeAdded(HttpSessionBindingEvent se) 方法;
當在Session刪除一個屬性時,激發attributeRemoved(HttpSessionBindingEventse)方法;
當在Session屬性被重新設置時,激發attributeReplaced(HttpSessionBindingEvent se) 方法。
四,interceptor
1, 在struts.xml中配置
創建一個strus.xml的子配置文件struts-l99-default.xml,它繼承與struts2的struts-default,此配置文件是其他子配置文件的父類,只要是繼承與該文件的配置文件所聲明的路徑都會被它過濾 .
方法1. 普通配置法
<struts>
<package name="struts2"extends="struts-default">
<interceptors>
<interceptor name="myInterceptor"class="edu.hust.interceptor.MyInterceptor"></interceptor>
</interceptors>
<action name="register"class="edu.hust.action.RegisterAction">
<result name="input">/register.jsp</result>
<result>/result.jsp</result>
<!-- 在自定義interceptor並將其ref時, 系統會覆蓋掉默認的interceptor-stack(defaultStack),爲了保證系統默認的defaultStack不受影響, 我們需要顯式的將其引入 -->
<!-- 注意兩個interceptor-ref的順序, 順序不同, 執行效果也不同: 先配置的先執行/後配置的先退出(先進後出)-->
<interceptor-refname="defaultStack"></interceptor-ref>
<interceptor-refname="myInterceptor"></interceptor-ref>
</action>
</package>
</struts>
方法2. 配置攔截器棧(即將多個interceptor串聯的一種元素)。然後在<action>中引入該攔截器棧就可以了。
執行順序爲先配置的先執行
這樣做的原因是:多個action有相同的多個interceptor時,如一般自己寫一個,系統默認的有一個,要注入兩個,
對多個action都寫這兩個,不利於修改,可以寫成一個鏈,只需引用此鏈即可。
(1)攔截目標對象(被代理對象),這裏目標對象就是action;(2)攔截器(一個類,動態的將某些方法插入到目標對象的某方法的before、after);(3)對目標對象生成的(動態)代理對象(代理對象內部方法綜合了目標對象方法+攔截器方法)。程序最終執行的是目標對象的代理,而這個代理已經插入了interceptor。攔截器作用:攔截action。interceptor相當於一個入口和出口,通過interceptor進入action,執行完action的代碼再通過interceptor出去。針對"struts2 --interceptor(Interceptor怎麼寫)"這篇文章的MyInterceptor.class和MyInterceptor2.class。根據下面的配置文件執行程序 <struts> <packagename="struts2" extends="struts-default">
<struts>
<package name="struts2"extends="struts-default">
<interceptors>
<interceptor name="myInterceptor"class="edu.hust.interceptor.MyInterceptor"></interceptor>
<interceptor-stack name="myInterceptorStack">
<interceptor-refname="myInterceptor"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</interceptor-stack>
</interceptors>
<action name="register"class="edu.hust.action.RegisterAction">
<result name="input">/register.jsp</result>
<result>/result.jsp</result>
<interceptor-refname="myInterceptorStack"></interceptor-ref>
</action>
</package>
</struts>
方法3. 修改默認攔截器,將自定義的攔截器棧定義爲struts2的默認攔截器。
<struts>
<package name="struts2"extends="struts-default">
<interceptors>
<interceptor name="myInterceptor"class="edu.hust.interceptor.MyInterceptor"></interceptor>
<interceptor-stack name="myInterceptorStack">
<interceptor-refname="myInterceptor"></interceptor-ref>
<interceptor-refname="defaultStack"></interceptor-ref>
</interceptor-stack>
</interceptors>
<!-- 此默認interceptor是針對當前包內所有action的,若不爲action顯式指定interceptor,就會用 default-interceptor-ref-->
<!-- 如果某個action中引入了interceptor, 則在這個action中此默認interceptor就會失效 -->
<default-interceptor-refname="myInterceptorStack"></default-interceptor-ref>
<action name="register"class="edu.hust.action.RegisterAction">
<result name="input">/register.jsp</result>
<result>/result.jsp</result>
</action>
</package>
</struts>
3. extends MethodFilterInterceptor的攔截器如何配置哪些方法該攔截、哪些方法不該攔截(針對方法攔截的配置)
<struts>
<package name="struts2"extends="struts-default">
<interceptors>
<interceptor name="myInterceptor3"class="edu.hust.interceptor.MyInterceptor3"></interceptor>
</interceptors>
<action name="register"class="edu.hust.action.RegisterAction"method="queryAll">
<result name="input">/register.jsp</result>
<result>/result.jsp</result>
<!-- myInterceptor3攔截器只對RegisterAction中的queryAll()方法和insert()方法進行了攔截, 其他方法未進行攔截 -->
<interceptor-ref name="myInterceptor3">
<param name="includeMethods">queryAll,execute</param>
</interceptor-ref>
<interceptor-refname="defaultStack"></interceptor-ref>
</action>
<action name="register"class="edu.hust.action.RegisterAction" method="insert">
<result <span
2, 實現
interceptor類似於filter, 自定義filter是實現javax.servlet.Filter來完成,而interceptor類似,它通過實現com.opensymphony.xwork2.interceptor.Interceptor來自定義實現。
該接口提供了三個方法:
1) void init(); 在該攔截器被初始化之後,在該攔截器執行攔截之前,系統回調該方法。對於每個攔截器而言,此方法只執行一次。
2) void destroy();該方法跟init()方法對應。在攔截器實例被銷燬之前,系統將回調該方法。
3) String intercept(ActionInvocation invocation) throws Exception; 該方法是用戶需要實現的攔截動作。該方法會返回一個字符串作爲邏輯視圖。
除此之外,繼承類com.opensymphony.xwork2.interceptor.AbstractInterceptor是更簡單的一種實現攔截器類的方式,因爲此類提供了init()和destroy()方法的空實現,這樣我們只需要實現intercept方法。
3, 應用
import java.util.Map;
import com.opensymphony.xwork2.Action;
importcom.opensymphony.xwork2.ActionInvocation;
importcom.opensymphony.xwork2.interceptor.AbstractInterceptor;
/**
* 權限檢查攔截器
*
* @author qiujy
* @version 1.0
*/
public class AuthorizationInterceptorextends AbstractInterceptor {
/*
* 攔截Action處理的攔截方法
*
*/
public String intercept(ActionInvocationinvocation) throws
Exception {
//清除後臺頁面的緩存
HttpServletResponse response =ServletActionContext.getResponse();
// ServletActionContext 自動提供,可讓其獲得request,session,response等
response.setHeader("Pragma","No-cache");
response.setHeader("Cache-Control","no-cache");
response.setHeader("Expires","0");
Map session =invocation.getInvocationContext().getSession();
String userName = (String)session.get("userName");
if (null != userName &&userName.equals("test")) {
System.out.println("攔截器:合法用戶登錄---");
return invocation.invoke(); //保持原來的流程不改變
} else {
System.out.println("攔截器:用戶未登錄---");
returnAction.LOGIN; //返回到配置文件中名字爲login的action
}
}