HandlerInterceptor 接口詳解
1. 接口方法說明
方法 | 作用 | 執行時機 | 返回值/注意事項 |
---|---|---|---|
preHandle | 請求處理前攔截 | 在控制器方法執行前調用 | 返回 false 中斷后續流程;返回 true 繼續執行 |
postHandle | 控制器方法執行后攔截 | 在控制器方法返回結果后,視圖渲染前調用 | 無返回值,不可中斷流程 |
afterCompletion | 請求完全結束后攔截 | 在視圖渲染完成后調用(無論是否成功) | 無返回值,用于資源清理 |
2. 完整示例代碼
2.1 自定義攔截器A(返回 false)
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;@Component
public class InterceptorA implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {System.out.println("InterceptorA.preHandle: 開始攔截請求");// 返回 false 中斷請求流程return false;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {System.out.println("InterceptorA.postHandle: 此處不會執行(因 preHandle 返回 false)");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {System.out.println("InterceptorA.afterCompletion: 請求已中斷,但此方法仍會被調用");}
}
2.2 自定義攔截器B(正常流程)
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;@Component
public class InterceptorB implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {System.out.println("InterceptorB.preHandle: 正常攔截");return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {System.out.println("InterceptorB.postHandle: 控制器方法執行后");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {System.out.println("InterceptorB.afterCompletion: 請求完成");}
}
2.3 注冊攔截器配置
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 WebConfig implements WebMvcConfigurer {@Autowiredprivate InterceptorA interceptorA;@Autowiredprivate InterceptorB interceptorB;@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 注冊順序:A 先于 Bregistry.addInterceptor(interceptorA).addPathPatterns("/**");registry.addInterceptor(interceptorB).addPathPatterns("/**");}
}
2.4 控制器示例
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class DemoController {@GetMapping("/test")public String test() {System.out.println("控制器方法執行:此請求將被攔截器A中斷");return "Hello World";}
}
3. 輸出結果分析(訪問 /test
)
InterceptorA.preHandle: 開始攔截請求
InterceptorA.afterCompletion: 請求已中斷,但此方法仍會被調用
- 攔截器A的
preHandle
返回false
后:- 攔截器B的
preHandle
不會被調用。 - 控制器方法不會執行。
- 攔截器B的
postHandle
和afterCompletion
也不會執行。 - 攔截器A的
afterCompletion
仍會被調用(因已進入攔截器鏈)。
- 攔截器B的
4. 常見處理場景示例
在攔截器中可實現以下功能:
- 日志記錄:記錄請求時間、URL、IP 等(如示例中的
System.out.println
)。 - 權限校驗:檢查用戶登錄狀態或角色權限。
- 性能監控:計算接口響應時間。
- 請求參數預處理:統一處理請求參數(如解密、格式化)。
5. 攔截器執行順序總結表
階段 | 執行順序規則 | 示例(A注冊在 B 前) |
---|---|---|
preHandle | 按注冊順序依次執行 | A → B |
postHandle | 按注冊逆序依次執行 | B → A |
afterCompletion | 按注冊逆序依次執行 | B → A |
注意:若某個
preHandle
返回false
,后續攔截器和控制器方法均被跳過,但已執行的攔截器的afterCompletion
仍會執行。