SpringBoot interceptor實踐總結
目錄
一interceptor是什麼
在軟體開發領域中,攔截器模式是一種軟體設計模式。
二interceptor的作用
你覺得 interceptor 解決了什麼問題呢?從實踐的經驗來看,攔截器核心提供了兩種能力:複用和擴充套件。
怎麼理解複用?
假設客戶端呼叫我們服務端介面,而服務端所有介面都會對 appId 進行校驗,這個 appId 是頒發給客戶端的,來標識客戶端身份。由於需要對 appId 進行校驗,所有的介面都需要加上 appId 校驗程式碼。
這樣是不是很不優雅?而且 appId 校驗程式碼是與業務無關的,直接寫在接口裡面是不是有很大的侵入性呢?使用攔截器,appId 校驗程式碼只需要做一次,業務程式碼更專注於業務邏輯,程式碼變得優雅。
怎麼理解擴充套件?
假設我們這塊有新的需求,需要對一些介面進行 token 認證,如何快速支援需求且對程式碼的侵入性小呢?新增 token 認證攔截器就好了;
過兩天說需要對一些介面列印請求日誌,我們這塊只需要新增日誌攔截器就好。
你看攔截器能如此快速、靈活解決業務需求,真是一個好東西哈。
三 interceptor的實現
實踐中我們這塊以 appId 攔截器和 token 認證攔截器來具體實現。SpringBoot 的攔截器實現和 SpringMVC 一致,通過配置把攔截器注入到 Spring 容器中去,只是配置方式不一樣,這塊以 SpringBoot 來實現。
3.1 攔截器類
@Component public class AppIdInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //業務邏輯。。。 System.out.println("AppIdInterceptor preHandle"); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("AppIdInterceptor postHandle"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("AppIdInterceptor afterCompletion"); } }
@Component
public class AuthenticateInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//業務邏輯。。。
System.out.println("AuthenticateInterceptor preHandle");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("AuthenticateInterceptor postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("AuthenticateInterceptor afterCompletion");
}
}
3.2 配置類
將 appId 攔截器和 token 認證攔截器加入到攔截器佇列。
@Configuration
public class InterceptorAdapter implements WebMvcConfigurer {
@Resource
private AppIdInterceptor appIdInterceptor;
@Resource
private AuthenticateInterceptor authenticateInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(appIdInterceptor).addPathPatterns("/**");
registry.addInterceptor(authenticateInterceptor).addPathPatterns("/api/getById");
}
}
addPathPatterns("/**") :表示攔截所有路徑;addPathPatterns("/api/getById") :只攔截 “/api/getById” 這個路徑。
是否需要考慮多個攔截器的載入順序呢?
我覺得是需要的,就拿上面的 appId 攔截器和 token 認證攔截器來說,appId 攔截器是攔截所有的,必須在前面;而 token 認證攔截器是部分介面需要的,應該在後面。
總結來說就是,越是具有普適性、覆蓋面廣的攔截器越應該先載入,反倒是那些定製化、覆蓋面小的攔截器應該後加載。
多個攔截器內部是怎樣的執行順序呢?
總結:
1 preHandle 按攔截器定義順序呼叫。
2 postHandler 按攔截器定義逆序呼叫。
3 afterCompletion按攔截器定義逆序呼叫。
4 postHandler 在攔截器鏈內所有攔截器返成功呼叫。
5 afterCompletion 只有 preHandle 返回 true 才呼叫。