過濾器和攔截器的區別和執行順序

一、兩者的區別

1、攔截器

java裏的攔截器是動態攔截Action調用的對象。它提供了一種機制可以使開發者可以定義在一個action執行的前後執行的代碼,也可以在一個action執行前阻止其執行,同時也提供了一種可以提取action中可重用部分的方式。在AOP(Aspect-Oriented Programming)中攔截器用於在某個方法或字段被訪問之前,進行攔截然後在之前或之後加入某些操作。------百度百科

2、過濾器

在Web中稱之爲Filter,通過配置多個過濾器,Web系統可以對所有的Servlet請求進行一層一層的過濾,以完成一些特殊的功能。例如常用的資源訪問權限控制、特殊字符以及敏感詞過濾、響應信息壓縮等功能。

3、區別

1> 攔截器是基於java的反射機制的,而過濾器是基於函數回調。
2> 攔截器不依賴與servlet容器,過濾器依賴與servlet容器。
3> 攔截器只能對action請求起作用,而過濾器則可以對幾乎所有的請求起作用。
4> 攔截器可以訪問action上下文、值棧裏的對象,而過濾器不能訪問。
5> 在action的生命週期中,攔截器可以多次被調用,而過濾器只能在容器初始化時被調用一次。(注:這裏的調用一次,是對於構造函數而言。而doFilter會對匹配的請求做持續的處理。)

6> 攔截器可以獲取IOC容器中的各個bean,而過濾器就不行,所以我們可以在攔截器裏注入一個service,可以調用業務邏輯。

 

二、兩者的執行順序

網上找了一張整體的流程圖,給出地址:點擊打開原圖片

之後根據這張圖,我們把過濾器和攔截器,摘出來,畫出一張專一詳解過濾器、攔截器,各函數執行順序的示意圖:

話不多說,都在圖上了,請自行觀摩。

 

三、過濾器代碼demo

你在web.xml中分別配置firstTestFilter、secondTestFilter兩個過濾器。

    <filter>
        <filter-name>firstTestFilter</filter-name>
        <filter-class>com.demo.Filter.FirstTestFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>firstTestFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <filter>
        <filter-name>secondTestFilter</filter-name>
        <filter-class>com.demo.Filter.SecondTestFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>secondTestFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

 

分別創建FirstTestFilter、SecondTestFilter兩個實現了Filter的過濾器類。

FirstTestFilter類:

package com.demo.Filter;

import javax.servlet.*;
import java.io.IOException;

/**
 * @author :xch
 * date:Create in 2018/7/16 13:48
 * description:
 */
public class FirstTestFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("我是第一個Filter,執行filterChain.doFilter(request,response)之前。");
        filterChain.doFilter(request,response);
        System.out.println("我是第一個Filter,執行filterChain.doFilter(request,response)之後。");
    }

    @Override
    public void destroy() {

    }
}

 

SecondTestFilter類:

 

package com.demo.Filter;

import javax.servlet.*;
import java.io.IOException;

/**
 * @author :xch
 * date:Create in 2018/7/16 13:48
 * description:
 */
public class SecondTestFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("我是第二個Filter,執行filterChain.doFilter(request,response)之前。");
        filterChain.doFilter(request,response);
        System.out.println("我是第二個Filter,執行filterChain.doFilter(request,response)之後。");
    }

    @Override
    public void destroy() {

    }
}

注:chain.doFilter將請求轉發給過濾器鏈的下一個filter , 如果下面沒有filter,那就是你請求的資源。

 

四、攔截器代碼demo

在spring-mvc的配置文件中配置公共的攔截器:

<mvc:interceptors>
        <!-- 對所有請求都攔截,公共攔截器 -->
        <bean name="testInterceptor" class="com.demo.interceptor.TestInterceptor" />
</mvc:interceptors>

 

公共攔截器的實現類TestInterceptor:

package com.demo.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author :xch
 * date:Create in 2018/7/16 14:06
 * description:
 */
public class TestInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        System.out.println("我是測試的攔截器函數:preHandle");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
        System.out.println("我是測試的攔截器函數:postHandle");
    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
        System.out.println("我是測試的攔截器函數:afterCompletion");
    }
}

 

代碼部分結束,我們啓動一下項目,隨便發送一個請求,這個請求接口會打印信息:“我是TestController類函數:test”。

看一下控制檯的打印信息:

打印順序完全正確,也驗證了圖例的正確性。

 

---------------------------------------------------------------------------不關注我“象話”嗎?

如有疑惑,請評論留言。

如有錯誤,也請評論留言。

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