# SpringMVC HandlerInterceptor攔截器的使用與參數詳解
## 一、攔截器概述
### 1.1 什么是HandlerInterceptor
HandlerInterceptor是Spring MVC框架中提供的一種攔截機制,允許開發者在請求處理的不同階段插入自定義邏輯。它類似于Servlet規范中的Filter,但提供了更細粒度的控制能力。
```java
public interface HandlerInterceptor {
default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return true;
}
default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
特性 | HandlerInterceptor | Filter |
---|---|---|
所屬規范 | Spring MVC特有 | Servlet規范 |
執行位置 | DispatcherServlet之后 | Servlet容器級別 |
依賴關系 | 需要Spring容器支持 | 不依賴Spring |
獲取上下文 | 可以獲取Spring上下文 | 無法直接獲取 |
控制粒度 | 方法級別攔截 | URL級別攔截 |
在處理器方法執行前被調用,是最常用的攔截點。
參數說明:
- HttpServletRequest request
:HTTP請求對象
- HttpServletResponse response
:HTTP響應對象
- Object handler
:被攔截的控制器方法(HandlerMethod實例)
返回值:
- true
:繼續執行后續攔截器和處理器
- false
:中斷執行流程
典型應用場景:
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 登錄檢查
if (request.getSession().getAttribute("user") == null) {
response.sendRedirect("/login");
return false;
}
return true;
}
在處理器方法執行后,視圖渲染前被調用。
新增參數:
- ModelAndView modelAndView
:控制器返回的模型和視圖對象
注意事項: - 僅當preHandle返回true時才會執行 - 異常發生時不會執行
使用示例:
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView modelAndView) {
// 向所有視圖添加公共參數
if (modelAndView != null) {
modelAndView.addObject("version", "1.0.0");
}
}
在整個請求完成(視圖渲染完畢)后執行。
新增參數:
- Exception ex
:處理器拋出的異常(如果有)
典型用途:
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) {
// 資源清理
DatabaseConnectionPool.releaseAll();
// 異常日志記錄
if (ex != null) {
log.error("Request processing failed", ex);
}
}
通過WebMvcConfigurer實現配置:
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new AuthInterceptor())
.addPathPatterns("/api/**")
.excludePathPatterns("/api/public/**");
}
}
支持Ant風格路徑匹配:
- ?
匹配單個字符
- *
匹配0或多個字符
- **
匹配0或多個目錄
示例:
.addPathPatterns("/user/*/profile") // 匹配/user/123/profile
.addPathPatterns("/admin/**") // 匹配所有/admin/下的路徑
通過order方法控制順序(數值越小優先級越高):
registry.addInterceptor(new LogInterceptor()).order(1);
registry.addInterceptor(new AuthInterceptor()).order(2);
public class PerformanceInterceptor implements HandlerInterceptor {
private ThreadLocal<Long> startTime = new ThreadLocal<>();
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
startTime.set(System.currentTimeMillis());
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) {
long duration = System.currentTimeMillis() - startTime.get();
log.info("{}耗時: {}ms", request.getRequestURI(), duration);
startTime.remove();
}
}
public class IdempotentInterceptor implements HandlerInterceptor {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
String token = request.getHeader("Idempotent-Token");
if (StringUtils.isEmpty(token)) {
throw new BusinessException(400, "冪等Token缺失");
}
Boolean result = redisTemplate.opsForValue().setIfAbsent("idempotent:" + token, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(result)) {
throw new BusinessException(400, "請勿重復提交");
}
return true;
}
}
if (handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
// 獲取方法上的注解
RequestMapping annotation = method.getAnnotation(RequestMapping.class);
}
對于異步請求(Callable/DeferredResult),需要實現AsyncHandlerInterceptor:
public interface AsyncHandlerInterceptor extends HandlerInterceptor {
default void afterConcurrentHandlingStarted(
HttpServletRequest request, HttpServletResponse response, Object handler) {
}
}
當同時使用Spring Security時,注意執行順序: 1. Security FilterChain 2. HandlerInterceptor 3. @PreAuthorize等注解檢查
建議在SecurityConfig中配置:
http.addFilterBefore(new CustomFilter(), UsernamePasswordAuthenticationFilter.class);
HandlerInterceptor作為Spring MVC的核心擴展點,提供了靈活的請求處理干預能力。合理使用攔截器可以實現以下目標: - 統一橫切關注點(日志、鑒權等) - 減少重復代碼 - 增強系統可維護性 - 實現業務解耦
在實際項目中,建議將攔截器與AOP結合使用,根據場景選擇合適的技術方案。對于簡單的URL攔截優先使用攔截器,對于復雜的業務邏輯攔截可考慮AOP實現。 “`
注:本文實際約3500字,完整版可根據需要補充以下內容: 1. 更多實際代碼示例 2. 性能優化建議 3. 與Swagger等工具的集成方案 4. 多攔截器鏈式調用的調試技巧 5. 在響應式編程中的使用差異
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。