HandlerInterceptor
允許客製化 handler
處理器執行鏈的工作流程介面。我們可以自訂攔截器用於攔截handlers 處理器(你可以理解為controller 層的介面),從而可以添加一些共同的重複性的處理行為(例如介面鑑權,介面日誌記錄,效能監控等),而不用修改每一個handler 的實作。
注意,此是根據 SpringBoot 2.3.12.RELEASE
版本講解。
HandlerInterceptor 介面只有三個預設空實作方法,在低版本中這三個方法不是預設方法,而是抽象方法。
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, @Nullable ModelAndView modelAndView) throws Exception { } default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception { } }
這三個方法的執行順序圖如下:
preHandle
前置處理,攔截一個處理器(handler)的執行,preHandle 方法會在 HandlerMapping
確定一個適當的處理器物件之後,但在 HandlerAdapter
呼叫處理器之前被呼叫。可以簡單理解為 controller 介面被呼叫之前執行。
Intercepter 是鍊式的,就是一個接著一個執行。如果此方法傳回 true,則會執行下一個攔截器或直接執行處理器。如果此方法傳回 false 或拋出例外則終止執行鏈,也不再呼叫處理器。
注意,此方法如果不回傳 true,那麼 postHandle
和 afterCompletion
就不會被執行。
那這個方法有什麼用呢?其實可以做一些介面被呼叫前的預處理,例如使用者權限校驗。
package com.chenpi; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.lang.Nullable; import org.springframework.stereotype.Component; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerInterceptor; /** * @Description 用户权限验证拦截 * @Author 陈皮 * @Date 2021/6/27 * @Version 1.0 */ @Component public class UserPermissionInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { if (handler instanceof HandlerMethod) { HandlerMethod handlerMethod = (HandlerMethod) handler; // 获取用户权限校验注解 UserAuthenticate userAuthenticate = handlerMethod.getMethod().getAnnotation(UserAuthenticate.class); if (null == userAuthenticate) { userAuthenticate = handlerMethod.getMethod().getDeclaringClass() .getAnnotation(UserAuthenticate.class); } if (userAuthenticate != null && userAuthenticate.permission()) { // 验证用户信息 UserContext userContext = userContextManager.getUserContext(request); if (null == userContext) { return false; } } } return true; } }
postHandle
後置處理,會在 HandlerAdapter
呼叫處理器之後,但在 DispatcherServlet
渲染視圖之前被調用。可以在此對 ModelAndView
做一些額外的處理。可以簡單理解為 controller 介面被呼叫之後執行。
注意,此方法在執行鏈中的執行順序是倒著執行的,也就是先宣告的攔截器後執行。
afterCompletion 完成之後,在請求處理完之後被執行,也就是渲染完視圖之後。一般用於做一些資源的清理工作,配合 preHandle 計算介面執行時間等。
注意,和 postHandle 一樣,此方法在執行鏈中的執行順序也是倒著執行的,也就是先宣告的攔截器後執行。
@Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) { // 请求完后,清除当前线程的用户信息 UserContextHolder.removeUserContext(); }
注意,我們自訂的攔截器要透過 WebMvcConfigurer
的實作類別進行註冊,才能生效。
package com.yzj.ehr.common.config; import com.yzj.ehr.common.context.UserContextResolver; import org.springframework.stereotype.Component; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import com.yzj.ehr.common.interceptor.UserPermissionInterceptor; /** * @Description 注册拦截器 * @Author 陈皮 * @Date 2021/6/27 * @Version 1.0 */ @Component public class WebAppConfigurer implements WebMvcConfigurer { private UserPermissionInterceptor userPermissionInterceptor; public WebAppConfigurer(final UserPermissionInterceptor userPermissionInterceptor) { this.userPermissionInterceptor = userPermissionInterceptor; } @Override public void addInterceptors(InterceptorRegistry registry) { // 匹配所有接口,排除/base/test接口 registry.addInterceptor(userPermissionInterceptor).addPathPatterns("/**") .excludePathPatterns("/base/test"); } }
以上是SpringBoot攔截器怎麼用的詳細內容。更多資訊請關注PHP中文網其他相關文章!