1.攔截器介紹
Web開發中,可以用Filter(過濾器)和 HandlerInterceptor(攔截器) 來過濾web請求,都能對客戶端發來的請求進行處理。
過濾器:是一個服務器端的組件,它可以截取用戶端的請求和響應信息,並對這些信息過濾。
Spring MVC 中的攔截器(Interceptor)類似於 Servlet 開發中的過濾器 Filter,它主要用於攔截用戶請求並作相應的處理,它也是 AOP 編程思想的體現,底層通過動態代理模式完成。聽說:只有經過DispatcherServlet 的請求,纔會走攔截器鏈,我們自定義的Servlet 請求是不會被攔截的
參考 Spring:過濾器filter、攔截器interceptor、和AOP的區別與聯繫
- 原理
- Filter:過濾器是基於函數回調。
- HandlerInterceptor:攔截器是基於java的反射機制,使用代理模式
- 作用域不同
- Filter:過濾器依賴於servlet容器,只能在 servlet容器,web環境下使用。跟Spring沒有關係
- HandlerInterceptor:攔截器依賴於spring容器,可以在spring容器中調用,不管此時Spring處於什麼環境
- 過濾內容
- Filter:過濾器可以對幾乎所有的請求起作用(可以保護資源)
- HandlerInterceptor:攔截器只能對action起作用
- 細粒度的不同
- Filter:過濾器的控制比較粗,只能在請求進來時進行處理,對請求和響應進行包裝
- HandlerInterceptor:攔截器提供更精細的控制,可以在controller對請求處理之前或之後被調用,也可以在渲染視圖呈現給用戶之後,以及request全部結束之後,都可以攔截到
- 中斷
- Filter:過濾器比較複雜,需要處理請求和響應對象來引發中斷,需要額外的動作,比如將用戶重定向到錯誤頁面
- HandlerInterceptor:不能通過攔截器修改request內容,但是可以通過拋出異常或者
preHandle
方法內返回 false 進行中斷來暫停request執行
- 小結
- 如果過濾器和攔截器同時存在:執行順序:過濾前-攔截前-Action處理-攔截後-過濾後
- 替代:過濾器能做的,攔截器基本上都能做
2.新建攔截器 參考 Spring Boot 2.X(九):Spring MVC - 攔截器(Interceptor)
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
public class TokenInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
// 在業務處理器處理請求之前被調用。預處理,可以進行編碼、安全控制、權限校驗等處理
// 進行邏輯判斷,如果ok就返回true,不行就返回false,返回false就不會處理請求
System.out.println("this is before handler");
Boolean flag = false;
if (flag) {
return true;
} else {
return false;
}
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
// 在業務處理器處理請求執行完成後,生成視圖之前執行。
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
// 在 DispatcherServlet 完全處理完請求後被調用,可用於清理資源等
}
}
3.配置攔截器
import java.util.ArrayList;
import java.util.List;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
/*
* 攔截器配置
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
List<String> excludePath = new ArrayList<>();
// 排除攔截路徑
excludePath.add("/test");
excludePath.add("/user");
// 註冊自定義攔截器,添加攔截路徑和排除攔截路徑
registry.addInterceptor(new TokenInterceptor())
.addPathPatterns("/**")
.excludePathPatterns(excludePath);
}
}
4.測試攔截器