Spring 全家桶之 Spring Web MVC(七)- Interceptor
highlight: a11y-light
一起養成寫作習慣!這是我參與「掘金日新計劃 · 4 月更文挑戰」的第11天,點選檢視活動詳情。
一、攔截器
Spring MVC提供了攔截器機制,允許在執行目標方法前進行一些攔截工作,或者在目標方法執行之後進行一些其他處理
Spring MVC 中的攔截器是HandlerInterceptor介面,該介面包含了三個方法
- preHandler:這個方法在業務處理器處理請求之前被呼叫,在該方法中對使用者請求進行處理,如果需要該攔截器對請求進行攔截處理後還要呼叫其他攔截器,或者是業務處理器進行處理,則返回True既放行請求,如果不需要再呼叫其他元件就返回false,既不放行請求 - postHandler:這個方法在業務處理器處理完成請求後呼叫,但是DispatcherServlet向客戶端返回響應前被呼叫,在該方法中對使用者請求request進行處理 - afterCompletion:這個方法在DispatcherServlet完全處理請求後被呼叫,可以在該方法中進行一些資源清理的操作
二、自定義攔截器
拷貝spring-mvc-ajax專案,並重命名為spring-mvc-handler,刪除除了配置之外的類及檔案。
攔截器的正常流程
新建一個HandlerInterceptorSamplerController,在該Controller中定義interceptor方法,測試自定義的攔截器,並返回success頁面 ```java @Controller public class HandlerInterceptorSamplerController {
@RequestMapping("/interceptor")
public String interceptor(){
System.out.println("interceptor方法被呼叫");
return "success";
}
}
在index.jsp頁面增加一個超連結
jsp
攔截該請求
新增interceptor包,新建一個自定義的攔截器ZuluInterceptor,自定義攔截器必須實現HandlerInterceptor介面,在攔截器中的每個方法中添加了日誌列印
java
public class ZuluInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println(this.getClass().getName() + " preHandler方法運行了");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println(this.getClass().getName() + " postHandle方法運行了");
System.out.println(modelAndView.getViewName());
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println(this.getClass().getName() + " afterCompletion方法運行了");
}
}
在Spring MVC 配置檔案中註冊攔截器,配置這個攔截器攔截哪些請求
xml
啟動應用,點選首頁的超連結
根據控制檯的輸出,自定義的攔截器被成功呼叫
因此攔截器的正常流程是:攔截器preHandler方法 -> 目標方法 -> 攔截器的postHandler方法 -> 頁面渲染 -> 攔截器的afterCompletion方法
攔截器的異常流程
異常流程1 - preHandler返回false
在ZuluInterceptor攔截器的preHandler方法返回false,再次啟動,點選首頁的超連結 控制檯只輸出了preHandler方法的執行資訊,因此只要preHandler返回false,既不放行就不會有以後的方法的執行。
異常流程2 - 其他異常
保持preHandler方法返回true,同時在Controller中的interceptor方法返回頁面前增加異常程式碼 ```java @RequestMapping("/interceptor") public String interceptor(){
System.out.println("interceptor方法被呼叫");
// 異常程式碼
int i = 10 / 0;
return "success";
} ``` 再次重新啟動應用,點選頁面的超連結 頁面出現有異常程式碼導致的報錯
此時控制檯執行了afterCompletion方法
三、多個攔截器執行順序
在interceptor包中拷貝ZuluInterceptor並重命名為DeltaInterceptor;在Spring MVC配置檔案中註冊新定義的攔截器
xml
<mvc:interceptors>
<!--第一種方式配置某個攔截器,預設是攔截所有請求的-->
<bean class="com.citi.interceptor.ZuluInterceptor"></bean>
<bean class="com.citi.interceptor.DeltaInterceptor"></bean>
</mvc:interceptors>
將Controller中的interceptor方法中的異常程式碼登出,重新啟動,點選頁面的插連線
根據控制檯的輸出可以確定,限制性了Zulu攔截器中的preHandler方法,接著執行Delta攔截器的preHandler方法,再執行目標方法,接著呼叫Delta攔截器的postHandler,再執行Zulu攔截器的postHandler,再執行Delta攔截器的afterCompletion方法,最後再執行Zulu攔截器的afterCompletion方法
攔截順序:
攔截器攔截順序是按照配置的先後順序,調整攔截器配置順序
xml
<mvc:interceptors>
<!--第一種方式配置某個攔截器,預設是攔截所有請求的-->
<bean class="com.citi.interceptor.DeltaInterceptor"></bean>
<bean class="com.citi.interceptor.ZuluInterceptor"></bean>
</mvc:interceptors>
再次啟動,點選首頁的超連結 根據控制檯輸出,配置檔案中先配置的Delta攔截器最先執行了
多個攔截器的異常流程:
保持Spring MVC配置檔案中Delta攔截器在前,Zulu攔截器在後的順序。如果Delta攔截器不放行,也就沒有後面所有的呼叫;如果Zulu攔截器不放行,會是什麼結果?
在Zulu攔截器中返回false,重新啟動應用,並點選首頁的超連結
根據控制檯的輸出可以確定,即是Zulu攔截器不放行,但是Delta的afterCompletion方法還是會執行。
已放行了的攔截器的afterCompletion方法總會執行
- 「在上海的兩年、在外企的一年、在掘金的半年」| 2022 年中總結
- 你有沒有掉進去過這些 Exception 的“陷阱“(Part C)
- Python From Zero to Hero(十)- 正則表示式
- Python DB-API 規範及 MySQL Connector/Python 實現
- Python From Zero to Hero(九)- 程序與執行緒(Part B)
- Python From Zero to Hero(九)- 程序與執行緒(Part A)
- Data Access 之 MyBatis Plus(三)- MPG程式碼生成器(Part B)
- 你有沒有掉進去過這些 Exception 的“陷阱“(Part B)
- Spring 全家桶之 Spring Boot 2.6.4( Ⅰ )- Caching(Part B)
- Spring 全家桶之 Spring Boot 2.6.4( Ⅰ )- Caching(Part A)
- Spring 全家桶之 Spring Boot 2.6.4(八)- 嵌入式 Servlet 容器(Part A)
- Spring 全家桶之 Spring Boot 2.6.4(七)- Exception
- Spring 全家桶之 Spring Boot 2.6.4(六)- Web Develop(Part C)
- Data Access 之 MyBatis Plus(五)- 自定義 BaseMapper
- Data Access 之 MyBatis Plus(四)- MyBatis Plus Plugin
- Spring 全家桶之 Spring Web MVC(九)- Exception
- Python From Zero to Hero(七)- Module & Package
- Spring 全家桶之 Spring Web MVC(七)- Interceptor
- 你有沒有使用過這些程式設計騷操作(一)- Lombok(Part B)
- Spring 全家桶之 Spring Boot 2.6.4(九)- 啟動流程解析