詳解HandlerInterceptor處理器攔截器的用法
HandlerInterceptor處理器攔截器用法
SpringMVC 中的HandlerInterceptor 攔截器類似于Servlet開發(fā)中的過濾器Filter,用于對處理器進(jìn)行預(yù)處理和后處理。
(如無特殊說明,下文所說的攔截器即處理器攔截器)
SpringMVC 中的Interceptor 攔截請求是通過HandlerInterceptor 來實(shí)現(xiàn)的。
在SpringMVC 中定義一個Interceptor 非常簡單,主要有兩種方式
- 第一種方式:是要定義的Interceptor類要實(shí)現(xiàn)了Spring 的HandlerInterceptor 接口,或者是這個類繼承實(shí)現(xiàn)了HandlerInterceptor 接口的類,比如Spring 已經(jīng)提供的實(shí)現(xiàn)了HandlerInterceptor 接口的抽象類HandlerInterceptorAdapter ;
- 第二種方式:是實(shí)現(xiàn)Spring的WebRequestInterceptor接口,或者是繼承實(shí)現(xiàn)了WebRequestInterceptor的類。
1.攔截器接口
先看下面的攔截器接口:
package org.springframework.web.servlet; public interface HandlerInterceptor { boolean preHandle( HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception; void postHandle( HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception; void afterCompletion( HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception; }
我們可能注意到攔截器一個有3個回調(diào)方法,而一般的過濾器Filter才兩個,這是怎么回事呢?馬上分析。
preHandle
預(yù)處理回調(diào)方法,實(shí)現(xiàn)處理器的預(yù)處理(如登錄檢查),第三個參數(shù)為響應(yīng)的處理器(如:Controller實(shí)現(xiàn));
preHandle方法是進(jìn)行處理器攔截用的,顧名思義,該方法將在Controller處理之前進(jìn)行調(diào)用,
* SpringMVC中的Interceptor攔截器是鏈?zhǔn)降?,可以同時存在多個Interceptor,
* 然后SpringMVC會根據(jù)聲明的前后順序一個接一個的執(zhí)行,
* 而且所有的Interceptor中的preHandle方法都會在Controller方法調(diào)用之前調(diào)用。
* SpringMVC的這種Interceptor鏈?zhǔn)浇Y(jié)構(gòu)也是可以進(jìn)行中斷的,
* 這種中斷方式是令preHandle的返回值為false,當(dāng)preHandle的返回值為false的時候整個請求就結(jié)束了。
返回值:true表示繼續(xù)流程(如調(diào)用下一個攔截器或處理器);
false表示流程中斷(如登錄檢查失?。粫^續(xù)調(diào)用其他的攔截器或處理器,此時我們需要通過response來產(chǎn)生響應(yīng);
postHandle
后處理回調(diào)方法,實(shí)現(xiàn)處理器的后處理(但在渲染視圖之前),此時我們可以通過modelAndView(模型和視圖對象)對模型數(shù)據(jù)進(jìn)行處理或?qū)σ晥D進(jìn)行處理,modelAndView也可能為null。
* 這個方法只會在當(dāng)前這個Interceptor的preHandle方法返回值為true的時候才會執(zhí)行。
* postHandle是進(jìn)行處理器攔截用的,它的執(zhí)行時間是在處理器進(jìn)行處理之后, 也就是在Controller的方法調(diào)用之后執(zhí)行,
* 但是它會在DispatcherServlet進(jìn)行視圖的渲染之前執(zhí)行,也就是說在這個方法中你可以對ModelAndView進(jìn)行操作。
* 這個方法的鏈?zhǔn)浇Y(jié)構(gòu)跟正常訪問的方向是相反的,也就是說先聲明的Interceptor攔截器該方法反而會后調(diào)用。
afterCompletion
整個請求處理完畢回調(diào)方法,即在視圖渲染完畢時回調(diào),如性能監(jiān)控中我們可以在此記錄結(jié)束時間并輸出消耗時間,還可以進(jìn)行一些資源清理,類似于try-catch-finally中的finally,但僅調(diào)用處理器執(zhí)行鏈中preHandle返回true的攔截器的afterCompletion。
* 該方法也是需要當(dāng)前對應(yīng)的Interceptor的preHandle方法的返回值為true時才會執(zhí)行。
* 該方法將在整個請求完成之后,也就是DispatcherServlet渲染了視圖執(zhí)行, 這個方法的主要作用是用于清理資源的。
2.攔截器適配器
有時候我們可能只需要實(shí)現(xiàn)三個回調(diào)方法中的某一個,如果實(shí)現(xiàn)HandlerInterceptor接口的話,三個方法必須實(shí)現(xiàn),不管你需不需要,此時spring提供了一個HandlerInterceptorAdapter適配器(一種適配器設(shè)計(jì)模式的實(shí)現(xiàn)),允許我們只實(shí)現(xiàn)需要的回調(diào)方法。
public abstract class HandlerInterceptorAdapter implements HandlerInterceptor { //省略代碼 此處所以三個回調(diào)方法都是空實(shí)現(xiàn),preHandle返回true。 }
正常運(yùn)行流程圖:
中斷流程圖:
中斷流程中,比如是HandlerInterceptor4中斷的流程(preHandle返回false),此處僅調(diào)用它之前攔截器HandlerInterceptor3的preHandle返回true的afterCompletion方法。
3.配置攔截器
使用mvc:interceptors標(biāo)簽來聲明需要加入到SpringMVC攔截器鏈中的攔截器。
在springMVC.xml配置文件增加:
<mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**" /> <mvc:exclude-mapping path="/static/**" /> <bean class="攔截器java代碼路徑" /> </mvc:interceptor> </mvc:interceptors>
說明:
- 1)mvc:mapping 攔截器路徑配置
- 2)mvc:exclude-mapping 攔截器不需要攔截的路徑
示例:
上面的示例可以看出可以利用mvc:interceptors標(biāo)簽聲明一系列的攔截器,然后它們就可以形成一個攔截器鏈,攔截器的執(zhí)行順序是按聲明的先后順序執(zhí)行的,先聲明的攔截器中的preHandle方法會先執(zhí)行,然而它的postHandle方法和afterCompletion方法卻會后執(zhí)行。
4.示例
下面是一個登錄攔截器的例子:
package cn.wmyskxz.interceptor; import cn.wmyskxz.pojo.User; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.util.Arrays; /** * 登錄攔截器: */ public class LoginInterceptor extends HandlerInterceptorAdapter { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { HttpSession session = request.getSession(); String[] noNeedAuthPage = new String[]{ "/home", "/searchProduct", "/sortProduct", "/showProduct", "/loginPage", "/login", "/registerPage", "/register", "/registerSuccessPage", "/test", "/checkLogin", "/admin" }; String uri = request.getRequestURI(); if (!Arrays.asList(noNeedAuthPage).contains(uri)) { User user = (User) session.getAttribute("user"); if (null == user) { response.sendRedirect("/loginPage"); return false; } } return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { super.afterCompletion(request, response, handler, ex); } }
該攔截器作用就是對于所有不需要授權(quán)的請求(字符串?dāng)?shù)組noNeedAuthPage中列出的),正常執(zhí)行Controller,否則重定向到loginPage頁面。
總結(jié)
以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java源碼解析之HashMap的put、resize方法詳解
這篇文章主要介紹了Java源碼解析之HashMap的put、resize方法詳解,文中有非常詳細(xì)的代碼示例,對正在學(xué)習(xí)java的小伙伴們有很大的幫助,需要的朋友可以參考下2021-04-04springboot引入遠(yuǎn)程nacos配置文件錯誤的解決方案
本文為解決Spring Cloud Alibaba中配置導(dǎo)入問題,提供了詳細(xì)的步驟說明,包括引入依賴、配置nacos、創(chuàng)建bootstrap.yml文件以及測試配置導(dǎo)入是否成功的方法,幫助開發(fā)者快速解決相關(guān)問題2024-09-09java 關(guān)鍵字static詳細(xì)介紹及如何使用
這篇文章主要介紹了java 關(guān)鍵字static詳細(xì)介紹及如何使用的相關(guān)資料,需要的朋友可以參考下2017-03-03JAVA maven項(xiàng)目使用釘釘SDK獲取token、用戶
這篇文章主要介紹了JAVA maven項(xiàng)目使用釘釘SDK獲取token、用戶,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06