攔截器
1.簡介
Spring MVC 中的攔截器(Interceptor)類似於 Servlet 開發中的過濾器 Filter,它主要用於攔截用戶請求並作相應的處理,它也是 AOP 編程思想的體現,底層通過動態代理模式完成。
2.定義實現類
攔截器有兩種實現方式:
1.實現 HandlerInterceptor 接口
2.繼承 HandlerInterceptorAdapter 抽象類(看源碼最底層也是通過 HandlerInterceptor 接口 實現)
3.HandlerInterceptor方法介紹
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
//進行邏輯判斷,如果ok就返回true,不行就返回false,返回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 {
}
preHandle:在業務處理器處理請求之前被調用。預處理,可以進行編碼、安全控制、權限校驗等處理;
postHandle:在業務處理器處理請求執行完成後,生成視圖之前執行。
afterCompletion:在 DispatcherServlet 完全處理完請求後被調用,可用於清理資源等。
4.應用場景
1.日誌記錄:記錄請求信息的日誌,以便進行信息監控、信息統計、計算PV(Page View)等;
2.登錄鑑權:如登錄檢測,進入處理器檢測檢測是否登錄;
3.性能監控:檢測方法的執行時間;
4.其他通用行爲。
5.與 Filter 過濾器的區別
1.攔截器是基於java的反射機制的,而過濾器是基於函數回調。
2.攔截器不依賴於servlet容器,而過濾器依賴於servlet容器。
3.攔截器只能對Controller請求起作用,而過濾器則可以對幾乎所有的請求起作用。
4.攔截器可以訪問action上下文、值棧裏的對象,而過濾器不能訪問。
5.在Controller的生命週期中,攔截器可以多次被調用,而過濾器只能在容器初始化時被調用一次。
6.攔截器可以獲取IOC容器中的各個bean,而過濾器不行。這點很重要,在攔截器裏注入一個service,可以調用業務邏輯。
具體實現
單個攔截器
1.新建攔截器
public class Test1Interceptor implements HandlerInterceptor{
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("執行preHandle方法-->01");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("執行postHandle方法-->02");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
System.out.println("執行afterCompletion方法-->03");
}
}
2.配置攔截器
@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {
/*
* 攔截器配置
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 註冊自定義攔截器,添加攔截路徑和排除攔截路徑
registry.addInterceptor(new Test1Interceptor()) // 添加攔截器
.addPathPatterns("/**") // 添加攔截路徑
.excludePathPatterns(// 添加排除攔截路徑
"/hello").order(0);//執行順序
super.addInterceptors(registry);
}
}
3.測試攔截器
@RestController
public class TestController {
@RequestMapping("/hello")
public String getHello() {
System.out.println("這裏是Hello");
return "hello world";
}
@RequestMapping("/test1")
public String getTest1() {
System.out.println("這裏是Test1");
return "test1 content";
}
@RequestMapping("/test2")
public String getTest2() {
System.out.println("這裏是Test2");
return "test2 content";
}
}
4.單個攔截器的執行流程
通過瀏覽器測試:
http://127.0.0.1:8080/hello
結果:
這裏是Hello
http://127.0.0.1:8080/test1 、http://127.0.0.1:8080/test2
結果:
執行preHandle方法-->01
這裏是Test1
執行postHandle方法-->02
執行afterCompletion方法-->03
多個攔截器
1.新建兩個攔截器
Test1Interceptor
public class Test1Interceptor implements HandlerInterceptor{
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("執行Test1Interceptor preHandle方法-->01");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("執行Test1Interceptor postHandle方法-->02");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
System.out.println("執行Test1Interceptor afterCompletion方法-->03");
}
}
Test2Interceptor
public class Test2Interceptor extends HandlerInterceptorAdapter{
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("執行Test2Interceptor preHandle方法-->01");
return true;
}
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("執行Test2Interceptor postHandle方法-->02");
}
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
System.out.println("執行Test2Interceptor afterCompletion方法-->03");
}
}
2.配置攔截器
@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {
/*
* 攔截器配置
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 註冊自定義攔截器,添加攔截路徑和排除攔截路徑
registry.addInterceptor(new Test1Interceptor()) // 添加攔截器1
.addPathPatterns("/**") // 添加攔截路徑
.excludePathPatterns(// 添加排除攔截路徑
"/hello")
.order(0);
registry.addInterceptor(new Test2Interceptor()) // 添加攔截器2
.addPathPatterns("/**") // 添加攔截路徑
.excludePathPatterns(// 添加排除攔截路徑
"/test1")
.order(1);
super.addInterceptors(registry);
}
}
3.測試攔截器
@RestController
public class TestController {
@RequestMapping("/hello")
public String getHello() {
System.out.println("這裏是Hello");
return "hello world";
}
@RequestMapping("/test1")
public String getTest1() {
System.out.println("這裏是Test1");
return "test1 content";
}
@RequestMapping("/test2")
public String getTest2() {
System.out.println("這裏是Test2");
return "test2 content";
}
}
4.多個攔截器的執行流程
通過瀏覽器測試:
http://127.0.0.1:8080/test2
結果:
執行Test1Interceptor preHandle方法-->01
執行Test2Interceptor preHandle方法-->01
這裏是Test2
執行Test2Interceptor postHandle方法-->02
執行Test1Interceptor postHandle方法-->02
執行Test2Interceptor afterCompletion方法-->03
執行Test1Interceptor afterCompletion方法-->03
通過示例,簡單的說多個攔截器執行流程就是先進後出。
簡單的 token 判斷示例
1.攔截器
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("執行Test1Interceptor preHandle方法-->01");
String token = request.getParameter("token");
if (StringUtils.isEmpty(token)) {
response.setContentType("text/html");
response.setCharacterEncoding("UTF-8");
response.getWriter().println("token不存在");
return false;
}
return true;
}
2.測試及結果
未傳token:
執行Test1Interceptor preHandle方法-->01
傳token:
執行Test1Interceptor preHandle方法-->01
頁碼:1
頁碼大小:10
執行Test1Interceptor postHandle方法-->02
執行Test1Interceptor afterCompletion方法-->03
示例代碼
非特殊說明,本文版權歸 朝霧輕寒 所有,轉載請註明出處.
原文標題:Spring Boot 2.X(九):Spring MVC - 攔截器(Interceptor)
原文地址:https://www.zwqh.top/article/info/18
如果文章對您有幫助,請掃碼關注下我的公衆號,文章持續更新中...