12.1、環境搭建 創建名為spring_mvc_interceptor的新module,過程參考9.1節和9.5節 12.1.1、頁面請求示例 <a th:href="@{/test/hello}">測試攔截器</a> 12.1.2、控制器方法示例 @RequestMapping("/test/h ...
12.1、環境搭建
創建名為spring_mvc_interceptor的新module,過程參考9.1節和9.5節
12.1.1、頁面請求示例
<a th:href="@{/test/hello}">測試攔截器</a>
12.1.2、控制器方法示例
@RequestMapping("/test/hello")
public String testHello(){
return "success";
}
12.2、攔截器的入門示例
12.2.1、創建攔截器
package online.liaojy.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @author liaojy
* @date 2023/11/7 - 20:57
*/
// SpringMVC 中的攔截器要實現 HandlerInterceptor 介面
public class AAAInterceptor implements HandlerInterceptor {
// preHandle()方法在控制器方法執行之前執行
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("AAAInterceptor-->preHandle()");
// 返回true表示不攔截,即執行控制器方法
// 返回false表示攔截,即不再執行控制器方法
return true;
}
// postHandle()方法在控制器方法執行之後執行
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("AAAInterceptor-->postHandle()");
}
// afterCompletion()方法在渲染完視圖之後執行
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("AAAInterceptor-->afterCompletion()");
}
}
12.2.2、配置攔截器
與自定義的過濾器一樣,自定義的攔截器也要配置後才能生效;
過濾器是伺服器中的組件,所以配置到 web.xml 中;
攔截器是 springmvc 中的組件,因此要配置到 springmvc 的配置文件中。
<mvc:interceptors>
<bean class="online.liaojy.interceptor.AAAInterceptor"></bean>
</mvc:interceptors>
12.2.3、測試效果
因為在配置攔截器時,沒有指定要攔截的路徑,所以訪問任何DispatcherServlet處理的資源時,攔截器都會執行。
12.3、攔截器的註解配置
除了使用 bean 標簽通過全限定類名來配置攔截器,還可以通過 ref 標簽引用已存在的 bean 組件來配置攔截器
12.3.1、將攔截器標識為bean組件
因為攔截器不屬於持久層、業務層和控制層,所以應該用 @Component 註解將其標識為一個 bean 組件
@Component
12.3.2、通過ref標簽引用配置攔截器
<mvc:interceptors>
<ref bean="AAAInterceptor"></ref>
</mvc:interceptors>
12.4、攔截器的進階示例
通過上述的方式來配置攔截器,會對 DispatcherServlet 所處理的所有請求都進行攔截;
在實際情況中,可能只需要攔截部分請求,或排除部分請求的攔截。
12.4.1、精確的攔截配置
<mvc:interceptors>
<mvc:interceptor>
<!--通過mvc:mapping設置要攔截的請求,可以設置多個;用通配符時,/*表示只攔截一級路徑的,/**才表示攔截任意的-->
<mvc:mapping path="/**"/>
<!--通過mvc:exclude-mapping設置要排除攔截的請求,可以設置多個 -->
<mvc:exclude-mapping path="/abc"/>
<!--設置實行精確攔截規則的攔截器-->
<bean class="online.liaojy.interceptor.AAAInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
12.4.2、測試效果
如上圖所示,攔截了一級路徑的請求
如上圖所示,攔截了二級路徑的請求
如上圖所示,沒有攔截/abc的請求
註意:為實現演示效果,本例已在springmvc配置文件中設置了關於/abc請求的視圖控制器
<mvc:view-controller path="/abc" view-name="success"></mvc:view-controller>
12.5、多個攔截器的執行順序
12.5.1、創建另一個攔截器
package online.liaojy.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @author liaojy
* @date 2023/11/9 - 7:27
*/
public class BBBInterceptor implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("BBBInterceptor-->preHandle()");
return true;
}
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("BBBInterceptor-->postHandle()");
}
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("BBBInterceptor-->afterCompletion()");
}
}
12.5.2、配置多個攔截器
<mvc:interceptors>
<bean class="online.liaojy.interceptor.AAAInterceptor"></bean>
<bean class="online.liaojy.interceptor.BBBInterceptor"></bean>
</mvc:interceptors>
12.5.3、情況一
-
如果每個攔截器的preHandle()都返回true
-
此時多個攔截器的執行順序和攔截器在SpringMVC的配置文件的配置順序有關
-
preHandle()會按照配置的順序執行,而postHandle()和afterCompletion()會按照配置的反序執行
註意:此時 AAAInterceptor 和 BBBInterceptor 攔截器的 preHandle() 方法返回值都是 true
12.5.4、情況二
-
如果某個攔截器的preHandle()返回了false
-
返回false的攔截器和它之前的攔截器的preHandle()都會執行
-
所有postHandle()都不執行
-
返回false的攔截器之前的攔截器的afterCompletion()會執行
註意:此時 AAAInterceptor 攔截器的 preHandle() 方法返回值為true,而 BBBInterceptor 攔截器的為 false
12.5.5、執行順序流程圖
12.6、相關拓展
12.6.1、攔截器與過濾器的區別
-
過濾器是 Tomcat 伺服器中的對象,攔截器是 SpringMVC 框架中的對象;
-
過濾器實現的是 Java 中的 Filter 介面,攔截器實現的是 SpringMVC 中的 HandleInterceptor 介面;
-
過濾器配置在 web.xml 中,攔截器配置在 SpringMVC 配置文件中;
-
過濾器在攔截器之前執行;
-
過濾器是一個執行時間點;攔截器是三個執行時間點;
-
過濾器除了對動態資源進行過濾之外,還可以對靜態資源(HTML、CSS、JS、圖片等)進行過濾;
-
攔截器側重對控制器方法進行攔截處理,如果一個請求不能被DispatcherServlet接收,那這個請求也不會被攔截器處理。
12.6.2、攔截器的應用場景
-
許可權校驗:用戶在訪問某資源時,可以使用攔截器對用戶請求進行攔截,
判斷當前用戶有沒有登錄,如果沒有登錄則強制回到登錄頁面進行登錄。 -
性能監控:如果想統計用戶訪問某個控制器方法的時間,可以使用攔截器對控制器方法進行前置攔截和後置攔截,
在前置攔截器裡面記錄用戶訪問資源的起始時間,在後置攔截器裡面記錄用戶訪問資源的結束時間,
兩個時間之差就是當前用戶訪問控制器方法是總時長。 -
日誌記錄:記錄請求資源的日誌信息,比如請求方式、請求參數、請求響應等,都可以通過攔截器來實現信息記錄。
本文來自博客園,作者:Javaer1995,轉載請註明原文鏈接:https://www.cnblogs.com/Javaer1995/p/17811857.html