1. 概述
本文將比較 Java Servlet 中的 Filter 與 Spring MVC 中的 HandlerInterceptor,並探討在何種情況下使用其中一種可能優於另一種。
2. 過濾器
過濾器是Web服務器的一部分,而不是Spring框架的一部分。對於傳入的請求,我們可以使用過濾器來操縱甚至阻止請求到達任何Servlet。反之,我們也可以阻止響應到達客户端。
Spring Security 是使用過濾器進行身份驗證和授權的絕佳例子。要配置 Spring Security,我們只需要添加一個過濾器,即 DelegatingFilterProxy。Spring Security 就可以攔截所有傳入和傳出的流量。 這也是為什麼 Spring Security 可以用於 Spring MVC 之外的原因。
2.1. 創建過濾器
為了創建過濾器,首先創建一個實現 javax.servlet.Filter 接口的類:
@Component
public class LogFilter implements Filter {
private Logger logger = LoggerFactory.getLogger(LogFilter.class);
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
logger.info("Hello from: " + request.getLocalAddr());
chain.doFilter(request, response);
}
}接下來,我們覆蓋(override)doFilter 方法,在這個方法中,我們可以訪問或操作 ServletRequest、ServletResponse 或 FilterChain 對象。我們可以使用 FilterChain 對象允許或阻止請求。
最後,我們通過在組件上添加 @Component 註解,將 Filter 添加到 Spring 上下文中。Spring 會完成剩餘的工作。
3. HandlerInterceptor 攔截器
HandlerInterceptors (攔截器) 是 Spring MVC 框架的一部分,位於 DispatcherServlet(分發器)和我們的 Controller(控制器)之間。 我們可以在請求到達控制器之前攔截請求,以及在視圖渲染之前和之後攔截請求。
3.1. 創建 HandlerInterceptor
要創建一個 HandlerInterceptor,我們需要創建一個實現 org.springframework.web.servlet.HandlerInterceptor 接口的類。這使我們能夠覆蓋三個方法:
- preHandle() – 在調用目標處理程序之前執行
- postHandle() – 在調用目標處理程序之後,但在 DispatcherServlet 渲染視圖之前執行
- afterCompletion() – 在請求處理和視圖渲染完成後執行的回調
讓我們為三個方法在我們的測試攔截器中添加日誌記錄:
public class LogInterceptor implements HandlerInterceptor {
private Logger logger = LoggerFactory.getLogger(LogInterceptor.class);
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
logger.info("preHandle");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
throws Exception {
logger.info("postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
logger.info("afterCompletion");
}
}4. 關鍵差異與使用場景
下面是一個圖表,展示了 Filter 和 HandlerInterceptor 在請求/響應流程中的位置:
Filter 攔截請求在到達 DispatcherServlet 之前,使其成為執行粗粒度任務的理想選擇,例如:
- 身份驗證
- 日誌記錄和審計
- 圖像和數據壓縮
- 任何我們希望與 Spring MVC 解耦的功能
HandlerInterceptor,另一方面,在 DispatcherServlet 和我們的 Controller 之間攔截請求。 這在 Spring MVC 框架中完成,提供對 Handler 和 ModelAndView 對象的訪問。 這減少了重複,並允許進行更精細的功能,例如:
- 處理橫切關注點,例如應用程序日誌記錄
- 詳細的授權檢查
- 操作 Spring 應用程序上下文或模型
5. 結論
在本文中,我們探討了 Filter 和 HandlerInterceptor 之間的差異。
關鍵要點是,使用 Filter 時,我們可以在請求到達控制器和 Spring MVC 之外之前對其進行操作。 否則,HandlerInterceptor 是處理應用程序特定橫向關注點的理想選擇。 通過提供對目標 Handler 和 ModelAndView 對象的訪問權限,我們能夠獲得更精細的控制。