一、使用場景
比如對特定的URL檢查用戶是否登錄,打印處理用戶請求耗時的時間等,可以用攔截器來實現。
二、攔截器使用
定義攔截器,需要實現 HandlerInterceptor 接口,接口中有3個方法
- preHandle:在DispatcherServlet處理請求執行之前被調用
- postHandle:在DispatcherServlet處理請求執行完成后,生成視圖之前被調用(還未渲染頁面)
- afterCompletion:在DispatcherServlet處理請求執行完成后,且已生成視圖被調用,可以用於清除資源(已渲染了頁面)
)2.1 創建自定義攔截器 MyInterceptor 類
@Slf4j public class MyInterceptor implements HandlerInterceptor { /** * 定義攔截器:需要實現 HandlerInterceptor 接口 * * HandlerInterceptor接口中有3個方法 * 1.preHandle:在業務處理器處理請求之前被調用 * 2.postHandle:在業務處理器處理請求執行完成后,生成視圖之前執行(還未渲染頁面)) * 3.afterCompletion:在DispatcherServlet完全處理完請求后被調用,可用於清理資源等。返回處理(已經渲染了頁面) */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { HandlerMethod handlerMethod = (HandlerMethod) handler; Method method = handlerMethod.getMethod(); String methodName = method.getName(); log.info("===攔截到了方法:{},在該方法執行之前執行===", methodName); // 判斷用戶有沒有登陸,一般登陸后的用戶都有一個對應的token String token = request.getParameter("token"); if (StringUtils.isEmpty(token)) { log.info("用戶沒有登陸,沒有執行權限......請登陸"); return false; } // 通過方法,可以獲取該方法上的自定義注解,然后通過注解來判斷該方法是否要被攔截 // @UnInterceptor 自定義注解,不被攔截 UnInterceptor unInterceptor = method.getAnnotation(UnInterceptor.class); if (null == unInterceptor) { return false; } return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { log.info("執行完方法之后進行(Controller方法調用之后),但是此時還沒有進行視圖渲染"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { log.info("整個請求都處理完畢,DispatcherServlet也渲染了對應的視圖,此時可以做一些清理的工作等等"); } }
)2.2 創建攔截器配置類,實現 WebMvcConfigurer 接口,對所有請求由 MyInterceptor 類進行攔截
@Configuration public class MyInterceptorConfig implements WebMvcConfigurer { /** * 解決靜態資源被攔截問題 * * @param registry */ @Override public void addInterceptors(InterceptorRegistry registry) { // 實現WebMvcConfigurer不會導致靜態資源被攔截 registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**"); } }
)2.3 創建controller類,接收請求
@Controller @RequestMapping("/interceptor") public class InterceptorController { @GetMapping("/test") public String test() { return "hello"; } @UnInterceptor @GetMapping("/test1") @ResponseBody public String test1() { return "不被攔截"; } }
)2.4 創建 hello.html 頁面,用於頁面返回渲染
三、測試
)3.1 對於 token 校驗測試。在 MyInterceptor 類中的 preHandle 方法中注釋 @UnInterceptor 校驗的代碼,
訪問 localhost:8080/interceptor/test 時,會被攔截,由於沒有帶token值,執行 preHandle 方法時返回false,不會繼續往下執行
通過 postman 表單請求設置 token 值,再次請求
測試結果如下,可以看到 MyInterceptor 類中,三個方法都已執行,且返回了 hello.html 中的頁面
)3.2 對於自定義注解校驗測試。在 MyInterceptor 類中的 preHandle 方法中注釋token校驗的代碼,放開 @UnInterceptor 的校驗代碼,
訪問 localhost:8080/interceptor/test1 可以看到 MyInterceptor 類中,三個方法都已執行