玩轉 SpringBoot 2 快速整合攔截器
概述
首先宣告一下,這裡所說的攔截器是 SpringMVC 的攔截器 HandlerInterceptor。使用SpringMVC 攔截器需要做如下操作:
- 建立攔截器類需要實現 HandlerInterceptor
- 在 xml 配置檔案中配置該攔截器,具體配置程式碼如下:
<mvc:interceptors>
<mvc:interceptor>
<!-- /test/** 這個是攔截路徑以/test開頭的所有的URL-->
<mvc:mapping path="/**"/><!—這個是攔截說有的路徑-->
<!-- 配置攔截器類路徑-->
<bean class="cn.ljk.springmvc.controller.MyInterceptor"></bean>
<!-- 配置不攔截器URL路徑-->
<mvc:exclude-mapping path="/fore/**"/>
</mvc:interceptor>
</mvc:interceptors>複製程式碼
因為在SpringBoot 中沒有 xml 檔案,所以SpringBoot 為我們提供 Java Config 的方式來配置攔截器。配置方式有2種:
- 繼承 WebMvcConfigurerAdapter (官方已經不建議使用)
- 實現 WebMvcConfigurer
接下來開始 SpringBoot 整合攔截器操作詳細介紹!
整合攔截器實戰操作
第一步:宣告攔截器類
通過實現 HandlerInterceptor 來完成。具體程式碼如下:
public class LoginInterceptor implements HandlerInterceptor{}複製程式碼
第二步:實現 HandlerInterceptor 3 個攔截方法
- preHandle:Controller邏輯執行之前進行攔截
- postHandle:Controller邏輯執行完畢但是檢視解析器還為進行解析之前進行攔截
- afterCompletion:Controller邏輯和檢視解析器執行完畢進行攔截
實際開發中 preHandle使用頻率比較高,postHandle 和 afterCompletion操作相對比較少。
在下面的程式碼中 preHandle 方法中定義攔截所有訪問專案 URL並進行日誌資訊記錄。postHandle 中在檢視解析前進行攔截,通過 Model 在次新增資料Request域中。
afterCompletion 暫時沒有想到使用場景,如果有使用過的場景可以在下面評論區中進行評論。
攔截器詳細程式碼如下:
public class LoginInterceptor implements HandlerInterceptor{
private Logger log = LoggerFactory.getLogger(LoginInterceptor.class);
//ControllerController邏輯執行之前
public boolean preHandle(HttpServletRequest request,HttpServletResponse response,Object handler) throws Exception {
log.info("preHandle....");
String uri = request.getRequestURI();
log.info("uri:"+ uri);
if (handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
log.info("攔截 Controller:"+ handlerMethod.getBean().getClass().getName());
log.info("攔截方法:"+handlerMethod.getMethod().getName());
}
return true;
}
//Controller邏輯執行完畢但是檢視解析器還為進行解析之前
@Override
public void postHandle(HttpServletRequest httpServletRequest,HttpServletResponse httpServletResponse,Object o,ModelAndView modelAndView) throws Exception {
log.info("postHandle....");
Map<String,Object>map=modelAndView.getModel();
map.put("msg","postHandle add msg");
}
//Controller邏輯和檢視解析器執行完畢
@Override
public void afterCompletion(HttpServletRequest httpServletRequest,Exception e) throws Exception {
log.info("afterCompletion....");
}
}複製程式碼
第三步:Java Config 的方式來配置攔截器
繼承 WebMvcConfigurerAdapter 方式
通過繼承 WebMvcConfigurerAdapter並重寫 addInterceptors方法,通過其引數 InterceptorRegistry將攔截器注入到 Spring的上下文中。
另外攔截路徑和不攔截的路徑通過InterceptorRegistry 的 addPathPatterns和 excludePathPatterns方法進行設定。
這種方式官方已經不建議使用,因為官方已將 WebMvcConfigurerAdapter 標記為@Deprecated 了。
@Deprecated
public abstract class WebMvcConfigurerAdapter implements WebMvcConfigurer {複製程式碼
繼承 WebMvcConfigurerAdapter 方式具體程式碼如下:
@Configuration
public class InterceptorConfigByExtendsWebMvcConfigurerAdapter extends WebMvcConfigurerAdapter{
@Bean
public LoginInterceptor loginInterceptor(){
return new LoginInterceptor();
}
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginInterceptor()).addPathPatterns("/**").excludePathPatterns("/*.html");
}
}複製程式碼
實現 WebMvcConfigurer 方式
通過實現 WebMvcConfigurer 介面並實現 addInterceptors方法,其他操作和繼承 WebMvcConfigurerAdapter方式一樣。具體程式碼如下:
@Configuration
public class InterceptorConfigByImplWebMvcConfigurer implements WebMvcConfigurer{
@Bean
public LoginInterceptor loginInterceptor(){
return new LoginInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginInterceptor()).addPathPatterns("/**").excludePathPatterns("/*.html");
}
}複製程式碼
測試
編寫普通Controller,具體程式碼如下:
@Controller
public class IndexController {
@GetMapping("/index")
public String index(ModelAndView modelAndView){
return "index";
}
}複製程式碼
在 src/main/resource 下的 templates目錄下建立 IndexController訪問頁面 index.ftl, 程式碼如下:
<h1>${msg}</h1>複製程式碼
由於我這裡使用的是 Freemarker當頁面使用,說以需要引入 Freemarker starter依賴,具體點如下:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>複製程式碼
通過遊覽器訪問 localhost:8080/sbe/index,具體訪問效果如下:
如上圖所示在檢視解析前通過 Model在次新增資料到 Request域中的msg 成功顯示出來了!
日誌輸出資訊如下:攔截地址和攔截Controller 和具體方法進行日誌輸出
2019-09-24 15:53:04.144 INFO 7732 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/sbe] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2019-09-24 15:53:04.145 INFO 7732 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2019-09-24 15:53:04.153 INFO 7732 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 8 ms
2019-09-24 15:53:04.155 INFO 7732 --- [nio-8080-exec-1] c.lijunkui.interceptor.LoginInterceptor : preHandle....
2019-09-24 15:53:04.155 INFO 7732 --- [nio-8080-exec-1] c.lijunkui.interceptor.LoginInterceptor : uri:/sbe/index
2019-09-24 15:53:04.155 INFO 7732 --- [nio-8080-exec-1] c.lijunkui.interceptor.LoginInterceptor : 攔截 Controller:cn.lijunkui.controller.IndexController
2019-09-24 15:53:04.155 INFO 7732 --- [nio-8080-exec-1] c.lijunkui.interceptor.LoginInterceptor : 攔截方法:index
2019-09-24 15:53:04.156 INFO 7732 --- [nio-8080-exec-1] c.lijunkui.interceptor.LoginInterceptor : postHandle....
2019-09-24 15:53:04.161 INFO 7732 --- [nio-8080-exec-1] c.lijunkui.interceptor.LoginInterceptor : afterCompletion....複製程式碼
小結
SpringBoot 2 整合攔截器和整合 Filter的操作很像,都是通過一個註冊類將其注入到Spring的上下文中,只不過Filter使用的是 FilterRegistrationBean 而 攔截器使用的是 InterceptorRegistry。
個人覺得比使用 xml 配置的方式更為簡單了,如果你還沒有在 SpringBoot 專案中使用過攔截器,趕快來操作一下吧!
程式碼示例
具體程式碼示例請在我的GitHub 倉庫 springbootexamples 中模組名為 spring-boot-2.x-interceptor 專案中進行檢視
GitHub:https://github.com/zhuoqianmingyue/springbootexamples