Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
前言:前面2篇博客,我們分析了Java中過濾器和監聽器的實現原理,今天我們來看看攔截器。
1,攔截器的概念
java里的攔截器是動態攔截Action調用的對象,它提供了一種機制可以使開發者在一個Action執行的前后執行一段代碼,也可以在一個Action
執行前阻止其執行,同時也提供了一種可以提取Action中可重用部分代碼的方式。在AOP中,攔截器用于在某個方法或者字段被訪問之前,進行攔截
然后再之前或者之后加入某些操作。目前,我們需要掌握的主要是Spring的攔截器,Struts2的攔截器不用深究,知道即可。
2,攔截器的原理
大部分時候,攔截器方法都是通過代理的方式來調用的。Struts2的攔截器實現相對簡單。當請求到達Struts2的時,Struts2
會查找配置文件,并根據配置實例化相對的攔截器對象,然后串成一個列表(List),最后一個一個的調用列表中的攔截器。Struts2的攔截器是可
插拔的,攔截器是AOP的一個實現。Struts2攔截器棧就是將攔截器按一定的順序連接成一條鏈。在訪問被攔截的方法或者字段時,Struts2攔截器鏈
中的攔截器就會按照之前定義的順序進行調用。
3,自定義攔截器的步驟
第一步:自定義一個實現了接口的類,或者繼承抽象類。
第二步:在配置文件中注冊定義的攔截器。
第三步:在需要使用Action中引用上述定義的攔截器,為了方便也可以將攔截器定義為默認的攔截器,這樣在不加特殊說明的情況下,所有的
Action都被這個攔截器攔截。
4,過濾器與攔截器的區別
過濾器可以簡單的理解為“取你所想取”,過濾器關注的是web請求;攔截器可以簡單的理解為“拒你所想拒”,攔截器關注的是方法調用,比如攔截
敏感詞匯。
4.1,攔截器是基于java反射機制來實現的,而過濾器是基于函數回調來實現的。(有人說,攔截器是基于動態代理來實現的)
4.2,攔截器不依賴servlet容器,過濾器依賴于servlet容器。
4.3,攔截器只對Action起作用,過濾器可以對所有請求起作用。
4.4,攔截器可以訪問Action上下文和值棧中的對象,過濾器不能。
4.5,在Action的生命周期中,攔截器可以多次調用,而過濾器只能在容器初始化時調用一次。
5,Spring攔截器
5.1,抽象類apter
我們如果在項目中使用了Spring框架,那么,我們可以直接繼承apter.java這個抽象類,來實現我們自己的攔截器。
Spring框架,對java的攔截器概念進行了包裝,這一點和Struts2很類似。apter繼承了抽象接口。
package org..web.servlet.handler;
import javax.servlet.http.;
import javax.servlet.http.;
import org..web.servlet.;
import org..web.servlet.;
public class apter {
// 在業務處理器處理請求之前被調用
public boolean ( request, , Object handler) throws {
return true;
// 在業務處理器處理請求完成之后,生成視圖之前執行
public void ( request, , Object handler, )
throws {
// 在完全處理完請求之后被調用,可用于清理資源
public void ( request, , Object handler, ex)
throws {
接下來我們看一下Spring框架實現的一個簡單的攔截器,繼承了
抽象類apter,實現了用戶登錄認證的攔截功能,如果當前用戶沒有通過認證,會報403錯誤。
package org..web.servlet.handler;
import java.io.;
import javax.servlet.;
import javax.servlet.http.;
import javax.servlet.http.;
public class extends apter{
// 字符串數組,用來存放用戶角色信息
private String[] ;
public final void (String[] ){
this. = ;
public final boolean ( request, , Object handler)
throws , {
if (this. != null) {
for (int i = 0; i < this..length; ++i) {
if (request.(this.[i])) {
return true;
(request, , handler);
return false;
void ( request, , Object handler)
throws , {
// 403表示資源不可用。服務器理解用戶的請求,但是拒絕處理它,通常是由于權限的問題
.(403);
下面,我們利用Spring框架提供的apter抽過類,來實現一個自定義的攔截器。我們這個攔截器叫做
,進行登錄攔截控制。工作流程是這樣的:如果當前用戶沒有登錄,則跳轉到登錄頁面;登錄成功后,跳轉到
之前訪問的URL頁面。
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.;
import javax.servlet.http.;
import org..web.servlet.;
import org..web.servlet.handler.apter;
/**
* @ 利用spring框架提供的apter,實現自定義攔截器
*/
public class extends apter{
// 在業務處理器處理請求之前被調用
public boolean ( request, , Object handler) throws {
// 與 equals的區別?
if("GET".(request.())){
//.();
System.out.println("...");
String = request.();
String = request.();
String url = .(.length());
System.out.println("" + );
System.out.println("" + );
System.out.println("url" + url);
String = (String) request.().("");
if(null == ){
// 跳轉到登錄頁面
request.("/WEB-INF/login.jsp").forward(request, );
return false;
else{
return true;
// 在業務處理器處理請求完成之后,生成視圖之前執行
public void ( request, , Object handler, ) throws {
System.out.println("...");
if( != null){
Map map = new HashMap();
.(map);
// 在完全處理完請求之后被調用,可用于清理資源
public void ( request, , Object handler, ex) throws {
System.out.println("...");
攔截器是依賴Java反射機制來實現的。攔截器的實現,用到的是JDK實現的動態代理,我們都知道,JDK實現的動態代理,需要依賴接口。攔截器
是在面向切面編程中應用的,就是在你的service或者一個方法前調用一個方法,或者在方法后調用一個方法。攔截器不是在web.xml,比如struts在
struts.xml中配置。
public Object invoke(Object proxy, Method method, Object[] args) throws {
Object result = null;
System.out.println("方法調用前,可以執行一段代碼" + method.getName());
result = method.invoke(this., args);
System.out.println("方法調用后,可以執行一段代碼 " + method.getName());
return result;
總結:
1.過濾器(Filter):所謂過濾器顧名思義是用來過濾的,Java的過濾器能夠為我們提供系統級別的過濾,也就是說,能過濾所有的web請求,
這一點,是攔截器無法做到的。在Java Web中,你傳入的request,提前過濾掉一些信息,或者提前設置一些參數,然后再傳入servlet或
者struts的action進行業務邏輯,比如過濾掉非法url(不是login.do的地址請求,如果用戶沒有登陸都過濾掉),或者在傳入servlet或者struts
的action前統一設置字符集,或者去除掉一些非法字符(聊天室經常用到的,一些罵人的話)。filter 流程是線性的,url傳來之后,檢查之后,
可保持原來的流程繼續向下執行,被下一個filter, servlet接收。
2.監聽器():Java的監聽器,也是系統級別的監聽。監聽器隨web應用的啟動而啟動。Java的監聽器在c/s模式里面經常用到,它
會對特定的事件產生產生一個處理。監聽在很多模式下用到,比如說觀察者模式,就是一個使用監聽器來實現的,在比如統計網站的在線人數。
又比如struts2可以用監聽來啟動。Servlet監聽器用于監聽一些重要事件的發生,監聽器對象可以在事情發生前、發生后可以做一些必要的處理。
3.攔截器():java里的攔截器提供的是非系統級別的攔截,也就是說,就覆蓋面來說,攔截器不如過濾器強大,但是更有針對性。
Java中的攔截器是基于Java反射機制實現的,更準確的劃分,應該是基于JDK實現的動態代理。它依賴于具體的接口,在運行期間動態生成字節碼。
攔截器是動態攔截Action調用的對象,它提供了一種機制可以使開發者在一個Action執行的前后執行一段代碼,也可以在一個Action執行前阻止其
執行,同時也提供了一種可以提取Action中可重用部分代碼的方式。在AOP中,攔截器用于在某個方法或者字段被訪問之前,進行攔截然后再之前或
者之后加入某些操作。java的攔截器主要是用在插件上,擴展件上比如 Spring Struts2等,有點類似面向切片的技術,在用之前先要在
配置文件即xml,文件里聲明一段的那個東西。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。