Filter和Interceptor
阿新 • • 發佈:2018-12-11
1. Filter(過濾器)和 Interceptor(攔截器)的區別
- 規範不同:
Filter
是Servlet
規範規定的,依賴於Servlet
容器;Interceptor
是Spring
規定的,依賴於Spring
框架。 - 實現原理不同:
Filter
基於函式回撥;Interceptor
基於java反射。 - 使用範圍不同:
Filter
依賴於Servlet
容器,只能用於Web
程式;Interceptor
既可用於Web
程式,也可以用於Application
、Swing
等程式中。 - 使用的資源不同:
Interceptor
是Spring
的一個元件,歸Spring
管理,配置在Spring
檔案中,可以使用Spring
Service
物件、資料來源、事務管理等,通過IoC
注入到Interceptor
既可;Filter
則不能。 - 深度不同:
Filter
只在Servlet
前後起作用,Interceptor
能夠深入到方法前後,異常丟擲前後等。在Spring
中應該優先使用Interceptor
。
2. 多個過濾器與多個攔截器的程式碼執行順序
如果一個專案中同時有多個Filter
,並且有多個Interceptor
,那麼它們的呼叫順序是什麼樣的呢?
Filter1.java
package com.tao.springstarter.web.filter;
import org.springframework. web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class Filter1 extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
// 在DispatcherServlet之前執行
System.out.println("進入 Filter1 doFilterInternal()");
// 呼叫下一個filter
filterChain.doFilter(request, response);
// 在試圖頁面返回給客戶端之前執行
System.out.println("退出 Filter1 doFilterInternal()");
}
}
Filter2.java
package com.tao.springstarter.web.filter;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class Filter2 extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
// 在DispatcherServlet之前執行
System.out.println("進入 Filter2 doFilterInternal()");
// 呼叫下一個filter
filterChain.doFilter(request, response);
// 在試圖頁面返回給客戶端之前執行
System.out.println("退出 Filter2 doFilterInternal()");
}
}
web.xml
中配置Filter1
和Filter2
<!-- 註冊Filter -->
<filter>
<filter-name>Filter1</filter-name>
<filter-class>com.tao.springstarter.web.filter.Filter1</filter-class>
</filter>
<filter-mapping>
<filter-name>Filter1</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>Filter2</filter-name>
<filter-class>com.tao.springstarter.web.filter.Filter2</filter-class>
</filter>
<filter-mapping>
<filter-name>Filter2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Interceptor1.java
package com.tao.springstarter.web.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Interceptor1 implements HandlerInterceptor {
/**
* 在DispatcherServlet之前執行
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("執行 Interceptor1 preHandle()");
return true;
}
/**
* 在Controller執行之後執行
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("執行 Interceptor1 postHandle()");
}
/**
* 在頁面渲染完成返回給客戶端之前執行
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("執行 Interceptor1 afterCompletion()");
}
}
Interceptor2.java
package com.tao.springstarter.web.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Interceptor2 implements HandlerInterceptor {
/**
* 在DispatcherServlet之前執行
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("執行 Interceptor2 preHandle()");
return true;
}
/**
* 在Controller執行之後執行
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("執行 Interceptor2 postHandle()");
}
/**
* 在頁面渲染完成返回給客戶端之前執行
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("執行 Interceptor2 afterCompletion()");
}
}
spring-servlet.xml
中配置Interceptor1
和Interceptor2
<mvc:interceptors>
<!-- 公共攔截器Interceptor1, 對所有請求都攔截 -->
<bean name="interceptor1" class="com.tao.springstarter.web.interceptor.Interceptor1"/>
<!-- 特定攔截器Interceptor2 -->
<mvc:interceptor>
<!-- 對/test進行攔截 -->
<mvc:mapping path="/test"/>
<!-- 特定請求的攔截器只能有一個 -->
<bean name="interceptor2" class="com.tao.springstarter.web.interceptor.Interceptor2"/>
</mvc:interceptor>
</mvc:interceptors>
測試用的TestController
:
package com.tao.springstarter.web.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class TestController {
@RequestMapping("/test")
@ResponseBody
public String filterAndInterceptor1() {
System.out.println("呼叫 TestController#filterAndInterceptor1()");
return "filterAndInterceptor1";
}
@RequestMapping("/haha")
@ResponseBody
public String filterAndInterceptor2() {
System.out.println("呼叫 TestController#filterAndInterceptor2()");
return "filterAndInterceptor2";
}
}
請求http://localhost:8080/ss/test
請求http://localhost:8080/ss/haha
可以看到此時Interceptor2
沒有起作用。
其最終的執行流程就如下圖所示: