Spring中過濾器(Filter)和攔截器(Interceptor)的區別和聯絡

2022-10-27 06:00:40

在我們日常的開發中,我們經常會用到Filter和Interceptor。有時同一個功能。Filter可以做,Interceptor也可以做。有時就需要考慮使用哪一個比較好。這篇文章主要介紹一下,二者的區別和聯絡。希望給大家進行選擇的時候,提供一些幫助

Filter 和 Interceptor 的區別

Filter

過濾器(Filter)是在請求進入Tomcat容器之後,請求進入Servlet之前執行。Filter是Servlet規範規定的,只能用於web程式中。

Interceptor

攔截器(Interceptor)是在Servlet和Controller控制器之間執行。Interceptor是SpringframeWork中規定的。

  • Interceptor是基於java的反射機制的,而Filter是基於函數回撥。
  • Interceptor不依賴與servlet容器,Filter依賴與servlet容器。
  • Interceptor只能對action請求起作用,而Filter則可以對幾乎所有的請求起作用。
  • Interceptor可以存取action上下文、值棧裡的物件,而Filter不能存取。
  • Interceptor以獲取IOC容器中的各個bean,而過濾器就不行,這點很重要,在攔截器裡注入一個service,可以呼叫業務邏輯。攔截器可以獲取ioc中的service bean實現業務邏輯。
Spring MVC中每個控制器中可以定義多個請求處理方法,我們把這種請求處理方法簡稱為Action

Filter的實現

自己的filter需要要實現javax.servlet.Filter.

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

public class Myfilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("Myfilter init");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("Myfilter doFilter before");
        filterChain.doFilter(servletRequest,servletResponse);
        System.out.println("Myfilter doFilter after");
    }

    @Override
    public void destroy() {
        System.out.println("Myfilter destroy");
    }
}

註冊Filter在web.xml中

<!-- 註冊過濾器 -->
    <filter>
        <filter-name>myfilter</filter-name>
        <filter-class>com.hardy.config.Myfilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>myfilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

Interceptor的實現

自己的Interceptor需要要實現org.springframework.web.servlet.HandlerInterceptor.

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 在攔截點(Controller方法處理之前)執行攔截 若返回的是false則中斷執行 反之亦然
        System.out.println("MyInterceptor preHandle");
        return HandlerInterceptor.super.preHandle(request, response, handler);
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // 在處理過程中(Controller方法處理完之後  DispatcherServlet進行檢視的渲染之前)執行攔截
        System.out.println("MyInterceptor postHandle");
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 在DispatcherServlet進行檢視的渲染後 返回前進行攔截
        System.out.println("MyInterceptor afterCompletion");
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}

註冊Interceptor在spring的組態檔中(application.xml)

    <!-- 設定攔截器 -->
    <mvc:interceptors>
        <mvc:interceptor>
            <!-- 攔截所有的mvc控制器(Controller) -->
            <mvc:mapping path="/**"/>
            <!-- 放行機制 指定對某個頁面不進行攔截 -->
            <!-- 攔截器只對action起作用 因此填入的不是頁面路徑 而是方法 -->
            <mvc:exclude-mapping path="/login"/>
            <!-- 指定使用哪個攔截器 -->
            <bean class="com.hardy.config.MyInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>