解讀過濾器(Filter)和攔截器(Interceptor)的使用
關于SpringMVC的完整執(zhí)行流程,可如下圖所示:

整體的流程如下所示:
Request請求-->filterInit--->dofilter--->dispatcherServlet---->InterceptorPrehandler--->Controller-------InterceptorPosthandler------>dispatcherServlet---InterceptorAftercomption-->filterDestroy。

關于過濾器和攔截器在web容器里面的先后順序,可參考如下所示:

下面重點介紹下兩者的區(qū)別和聯(lián)系。
1、定義介紹
1.1、過濾器Filter
1、定義
是 Servlet 規(guī)范規(guī)定的,在 Servlet 前執(zhí)行的,用于攔截和處理 HTTP 請求和響應。攔截的是request請求,基于回調(diào),攔截的是地址,粒度很大。
2、方法
通過實現(xiàn)Filter接口,分別是初始化方法,dofilter方法和銷毀方法,隨著容器的啟動和銷毀而初始化和銷毀,依賴于servlet容器。
過濾器攔截的是地址欄請求,過濾器實在進入容器后執(zhí)行的servlet之前后執(zhí)行,針對的在處理業(yè)務之前的操作。
chain.doFilter(request, response);這個方法的調(diào)用作為分水嶺。事實上調(diào)用Servlet的doService()方法是在這個方法中進行的。
3、位置
位于整個請求處理流程的最前端,因此在請求到達 Controller 層前,都會先被過濾器處理。可以攔截多個請求或響應,一個請求或響應也可以被多個過濾器攔截。
4、使用場景
可用于身份認證、授權、日志記錄和設置字符集(CharacterEncodingFilter)等場景。
1.2、攔截器Interceptor
1、介紹
基于Java的jdk動態(tài)代實現(xiàn)的,實現(xiàn)HandlerInterceptor接口,不依賴于servlet容器。
攔截器針對于controller方法,并且能獲取到所有的類,對類里面所有的方法實現(xiàn)攔截,粒度更小,攔截器中可以注入service,也可以調(diào)用業(yè)務邏輯
2、方法
實現(xiàn)HandlerInterceptor接口。重寫preHandle()、postHandle()、afterCompletion();
3、執(zhí)行順序

執(zhí)行結果如下:
/*
0:過濾器1的初始化方法
1:過濾器1,客戶端向Servlet發(fā)送的請求被我攔截到了
2:攔截器1的前置方法 preHandle
3:攔截器2的前置方法 preHandle
4: controller主方法
5:攔截器2的后置方法postHandle(在controller主方法執(zhí)行之后執(zhí)行)
6:攔截器1的后置方法postHandle(在controller主方法執(zhí)行之后執(zhí)行)
7:攔截器2的完成后方法afterCompletion(在DispatcherServlet處理完請求后,才會執(zhí)行)
8:攔截器1的完成后方法afterCompletion(在DispatcherServlet處理完請求后,才會執(zhí)行)
9:過濾器1,Servlet向客戶端發(fā)送的響應被我攔截到了
10:過濾器的銷毀方法
*/
2、實現(xiàn)方式
2.1、過濾器實現(xiàn)方式
1、通過@WebFilter注解(Servlet 3.0+)
@WebFilter(urlPatterns = "/*", filterName = "myFilter")
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// 初始化代碼
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
// 前置處理
System.out.println("Before Filter");
// 執(zhí)行后續(xù)過濾器或Servlet
chain.doFilter(request, response);
// 后置處理
System.out.println("After Filter");
}
@Override
public void destroy() {
// 銷毀代碼
}
}2、xml配置:
<filter>
<filter-name>filterDemo1</filter-name>
<filter-class>com.thit.filters.Filter1</filter-class>
</filter>
<filter-mapping>
<filter-name>filterDemo1</filter-name>
<url-pattern>/*</url-pattern>
<!-- /*是對所有的文件進行攔截 -->
</filter-mapping>多個Filter的執(zhí)行順序:
- 注解方式:按類名字母順序執(zhí)行
- web.xml方式:按
<filter-mapping>定義的順序執(zhí)行
2.2、攔截器實現(xiàn)方式
1:實現(xiàn)WebMvcConfigurer接口(Spring 5+推薦)
//攔截器1
public class LoginInterceptor implements HandlerInterceptor{
//預處理1.程序先執(zhí)行preHandle()方法,如果該方法的返回值為true,則程序會繼續(xù)向下執(zhí)行處理器中的方法,否則將不再向下執(zhí)行。
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
// TODO Auto-generated method stub
System.out.println("1:攔截器1,程序進入preHandle方法");
User u=(User) request.getSession().getAttribute("user");
if(u==null) {
System.out.println("在進入方法之前判斷session的用戶是否為空!");
System.out.println("地址:"+request.getContextPath());
//http://localhost:8080/login
response.sendRedirect(request.getContextPath()+"/login");
return false;
}
return true;
}
//后處理 2.在業(yè)務處理器(即控制器Controller類)處理完請求后,會執(zhí)行postHandle()方法,然后會通過DispatcherServlet向客戶端返回響應。
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
// TODO Auto-generated method stub
System.out.println("2:攔截器1,程序進入postHandle方法");
}
//完工之后 3.在DispatcherServlet處理完請求后,才會執(zhí)行afterCompletion()方法。
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
// TODO Auto-generated method stub
System.out.println("3:攔截器1,程序進入afterCompletion方法");
}
}@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyInterceptor())
.addPathPatterns("/**") // 攔截所有路徑
.excludePathPatterns("/login"); // 排除登錄路徑
// 可以添加多個攔截器
registry.addInterceptor(new AnotherInterceptor())
.addPathPatterns("/admin/**");
}
}2:XML配置
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<mvc:exclude-mapping path="/login"/>
<bean class="com.example.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>3、兩者聯(lián)系與區(qū)別
3.1、聯(lián)系

3.2、區(qū)別


4、總結
兩者都是AOP編程思想的實現(xiàn),都能夠?qū)崿F(xiàn)權限控制和日志記錄等問題的處理,但是兩者粒度不同攔截對象不一樣。
- 1、適用范圍不同:
Filter是servlet的規(guī)范,只能用于web程序,但是攔截器可以用于application等程序。
- 2、規(guī)范不同:
Filter是servlet的規(guī)范。但是Interceptor是Spring容器支撐,有Spring框架支持。
- 3、使用資源不一樣:
Spring的攔截器由于依賴Spring,也是Spring的一個組件,因此能夠在攔截器中使用Spring的任何資源和對象。
例如Service對象,數(shù)據(jù)源,事務管理等,通過ioc注入攔截器即可,而filter不能.
- 4、粒度不同:
Filter只能在servlet的前后起作用,而攔截器能在方法前后異常前后執(zhí)行,更加靈活,粒度更小,Spring框架程序優(yōu)先使用攔截器。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
- 深度解析Spring?Boot攔截器Interceptor與過濾器Filter的區(qū)別與實戰(zhàn)指南
- Spring Boot攔截器Interceptor與過濾器Filter深度解析(區(qū)別、實現(xiàn)與實戰(zhàn)指南)
- Spring Boot攔截器Interceptor與過濾器Filter深度解析(區(qū)別、實現(xiàn)與實戰(zhàn)指南)
- Spring Boot攔截器Interceptor與過濾器Filter詳細教程(示例詳解)
- Spring中過濾器(Filter)和攔截器(Interceptor)的區(qū)別和聯(lián)系解析
- Java中過濾器 (Filter) 和 攔截器 (Interceptor)的使用
- 淺談SpringMVC的攔截器(Interceptor)和Servlet 的過濾器(Filter)的區(qū)別與聯(lián)系 及SpringMVC 的配置文件
相關文章
淺析SpringBoot統(tǒng)一返回結果的實現(xiàn)
前后端開發(fā)過程中數(shù)據(jù)交互規(guī)范化是一件非常重要的事情,不僅可以減少前后端交互過程中出現(xiàn)的問題,也讓代碼邏輯更加具有條理,下面小編就和大家講講SpringBoot如何統(tǒng)一返回結果的吧2023-07-07
idea創(chuàng)建SpringBoot自動創(chuàng)建Lombok無效果的問題解決方案
這篇文章主要介紹了idea創(chuàng)建SpringBoot自動創(chuàng)建Lombok無效果的問題解決方案,感興趣的朋友跟隨小編一起看看吧2024-12-12
StackTraceElement獲取方法調(diào)用棧信息實例詳解
這篇文章主要介紹了StackTraceElement獲取方法調(diào)用棧信息實例詳解,分享了相關代碼示例,小編覺得還是挺不錯的,具有一定借鑒價值,需要的朋友可以參考下2018-02-02
SpringBoot使用itext填充pdf表單及導出pdf的流程
由于最近開發(fā)的項目需要用到打印單據(jù),就在網(wǎng)上找了一下方案,反反復復,都沒有找到合適的,借鑒了網(wǎng)上資源,使用itext5、itext7的工具包,所以本文介紹了SpringBoot使用itext填充pdf表單及導出pdf的流程,需要的朋友可以參考下2024-09-09
SpringBoot中使用攔截器攔截跳轉(zhuǎn)登錄的兩種實現(xiàn)方法
攔截器(Interceptor)是Spring框架提供的一種機制,用于在請求的生命周期中插入自定義邏輯,如身份驗證、日志記錄等,本文將詳細介紹兩種在SpringBoot中使用攔截器來控制用戶登錄并跳轉(zhuǎn)到指定頁面的方法,需要的朋友可以參考下2024-11-11

