Springboot 過濾器和攔截器詳解及使用場景


一、過濾器和攔截器的區別

 

 

1、過濾器和攔截器觸發時機不一樣過濾器是在請求進入容器后,但請求進入servlet之前行預處理的。請求結束返回也是,是在servlet處理完后,返回給前端之前。

 

2、攔截器可以獲取IOC容器中的各個bean,而過濾器就不行,因為攔截器是spring提供並管理的,spring的功能可以被攔截器使用,在攔截器里注入一個service,可以調用業務邏輯。而過濾器是JavaEE標准,只需依賴servlet api ,不需要依賴spring。

 

3、過濾器的實現基於回調函數。而攔截器(代理模式)的實現基於反射

 

4、Filter是依賴於Servlet容器,屬於Servlet規范的一部分,而攔截器則是獨立存在的,可以在任何情況下使用。

 

5、Filter的執行由Servlet容器回調完成,而攔截器通常通過動態代理(反射)的方式來執行。

 

6、Filter的生命周由Servlet容器管理,而攔截器則可以通過IoC容器來管理,因此可以通過注入等方式來獲取其他Bean的實例,因此使用會更方便。

 

過濾器和攔截器非常相似,但是它們有很大的區別

最簡單明了的區別就是**過濾器可以修改request,而攔截器不能

過濾器需要在servlet容器中實現,攔截器可以適用於javaEE,javaSE等各種環境

攔截器可以調用IOC容器中的各種依賴,而過濾器不能

過濾器只能在請求的前后使用,而攔截器可以詳細到每個方法**

區別很多,大家可以去查下

 

總的來說

過濾器就是篩選出你要的東西,比如requeset中你要的那部分

攔截器在做安全方面用的比較多,比如終止一些流程

網上有一張圖片很不錯,這里拷過來給大家看一下

 

 

過濾器(Filter) :可以拿到原始的http請求,但是拿不到你請求的控制器和請求控制器中的方法的信息。

 

攔截器(Interceptor):可以拿到你請求的控制器和方法,卻拿不到請求方法的參數。

 

切片(Aspect): 可以拿到方法的參數,但是卻拿不到http請求和響應的對象

 

 

二、過濾器

 

兩種方式: 

1、使用spring boot提供的FilterRegistrationBean注冊Filter 

2、使用原生servlet注解定義Filter 

兩種方式的本質都是一樣的,都是去FilterRegistrationBean注冊自定義Filter

 

方式一: (使用spring boot提供的FilterRegistrationBean注冊Filter )

①、先定義Filter:

 

 
 
 
package com.corwien.filter;
import javax.servlet.*;
import java.io.IOException;
public class MyFilter implements Filter {
@Override public void init(FilterConfig filterConfig) throws ServletException {
 
}
@Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { // do something 處理request 或response
// doFilter()方法中的servletRequest參數的類型是ServletRequest,需要轉換為HttpServletRequest類型方便調用某些方法
System.out.println("filter1"); // 調用filter鏈中的下一個filter
 
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
 
String ip = request.getRemoteAddr();
String url = request.getRequestURL().toString();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date d = new Date();
String date = sdf.format(d);
 
System.out.printf("%s %s 訪問了 %s%n", date, ip, url);
 
filterChain.doFilter(request, response);
}
@Override public void destroy() {
 
}
}
 
 
 

 

②、注冊自定義Filter

 

 
 
 
@Configuration
public class FilterConfig {
 
@Bean
public FilterRegistrationBean registrationBean() {
** FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new** **MyFilter());**
filterRegistrationBean.addUrlPatterns("/*");
return filterRegistrationBean;
}
}
 
 
 

 

方式一的①②步驟可以用下面這段代碼代替:

 

 
 
 
@Configuration public class FilterConfig {
 
@Bean public **FilterRegistrationBean** registFilter() {
**FilterRegistrationBean registration** **= new FilterRegistrationBean();
registration.setFilter(new** **LogCostFilter());**
registration.addUrlPatterns("/*");
registration.setName("LogCostFilter");
registration.setOrder(1); return registration;
}
 
}
 
 
 

 

 
 
 
public class LogCostFilter implements Filter {
@Override public void init(FilterConfig filterConfig) throws ServletException {
 
}
 
@Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { long start = System.currentTimeMillis();
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("Execute cost="+(System.currentTimeMillis()-start));
}
 
@Override public void destroy() {
 
}
 
 
 

 

方式二:(使用原生servlet注解定義Filter )

 

 
 
 
// 注入spring容器
@Component // 定義filterName 和過濾的url
@WebFilter(filterName = "my2Filter" ,urlPatterns = "/*") public class My2Filter implements Filter {
@Override public void init(FilterConfig filterConfig) throws ServletException {
 
}
@Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("filter2");
}
@Override public void destroy() {
 
}
}
 
 
 

 

這里直接用@WebFilter就可以進行配置,同樣,可以設置url匹配模式,過濾器名稱等。這里需要注意一點的是@WebFilter這個注解是Servlet3.0的規范,並不是Spring boot提供的。除了這個注解以外,我們還需在啟動類中加另外一個注解:@ServletComponetScan,指定掃描的包。

 

三、攔截器的配置

 

實現攔截器可以通過繼承 HandlerInterceptorAdapter類也可以通過實現HandlerInterceptor這個接口。另外,如果preHandle方法return true,則繼續后續處理。

 

首先我們實現攔截器類:

 

 
 
 
public class LogCostInterceptor implements HandlerInterceptor { long start = System.currentTimeMillis();
@Override public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
start = System.currentTimeMillis(); return true;
}
 
@Override public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
System.out.println("Interceptor cost="+(System.currentTimeMillis()-start));
}
 
@Override public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
}
}
 
 
 

 

我們還需要實現HandlerInterceptor這個接口,這個接口包括三個方法,preHandle是請求執行前執行的,postHandler是請求結束執行的,但只有preHandle方法返回true的時候才會執行,afterCompletion是視圖渲染完成后才執行,同樣需要preHandle返回true,該方法通常用於清理資源等工作。除了實現上面的接口外,我們還需對其進行配置:

 

 
 
 
@Configuration public class InterceptorConfig extends WebMvcConfigurerAdapter {
 
@Override public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LogCostInterceptor()).addPathPatterns("/**"); super.addInterceptors(registry);
}
}
 
 
 

 

這里我們繼承了WebMVCConfigurerAdapter,這里我們重寫了addInterceptors這個方法,進行攔截器的配置,主要配置項就兩個,一個是指定攔截器,第二個是指定攔截的URL

 

坑坑坑:

攔截器不生效常見問題:

1)是否有加@Configuration

2)攔截路徑是否有問題 ** 和 *

3)攔截器最后路徑一定要 “/**”, 如果是目錄的話則是 /*/

 

總結一下:創建攔截器需要兩步:

 

1、自定義攔截器

2、注冊攔截器

 

四、應用場景

 

攔截器是在DispatcherServlet這個servlet中執行的,因此所有的請求最先進入Filter,最后離開Filter。其順序如下。

 

Filter->Interceptor.preHandle->Handler->Interceptor.postHandle->Interceptor.afterCompletion->Filter

 

攔截器應用場景

 

攔截器本質上是面向切面編程(AOP),符合橫切關注點的功能都可以放在攔截器中來實現,主要的應用場景包括:

 

  • 登錄驗證,判斷用戶是否登錄。

  • 權限驗證,判斷用戶是否有權限訪問資源,如校驗token

  • 日志記錄,記錄請求操作日志(用戶ip,訪問時間等),以便統計請求訪問量。

  • 處理cookie、本地化、國際化、主題等。

  • 性能監控,監控請求處理時長等。

  • 通用行為:讀取cookie得到用戶信息並將用戶對象放入請求,從而方便后續流程使用,還有如提取Locale、Theme信息等,只要是多個處理器都需要的即可使用攔截器實現)

 

過濾器應用場景

 

1)過濾敏感詞匯(防止sql注入)

2)設置字符編碼

3)URL級別的權限訪問控制

4)壓縮響應信息

 

 

看完三件事❤️

 

如果你覺得這篇內容對你還蠻有幫助,我想邀請你幫我三個小忙:

 

  1. 點贊,轉發,有你們的 『點贊和評論』,才是我創造的動力。

  2. 關注公眾號 『 java爛豬皮 』,不定期分享原創知識。

  3. 同時可以期待后續文章ing🚀

 

 

作者:Corwien

出處: https://segmentfault.com/a/1190000037755221


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM