類似以前SpringMVC的攔截器,但也有一些區別
SpringBoot的攔截器有兩種方式:
第一種方式:過時的方式,適用於SpringBoot1.x的方式
package org.dreamtech.springboot.interceptor; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; @SuppressWarnings("deprecation") public class CustomWebMvcConfigurer extends WebMvcConfigurerAdapter { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoginIntercepter()).addPathPatterns("/test/*/**"); super.addInterceptors(registry); } }
第二種方式:基於Java8與Spring5的方式
原理:在WebMvcConfigurer接口中定義了默認方法,利用Java8新特性:接口中可以寫方法
package org.dreamtech.springboot.interceptor; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class CustomWebMvcConfigurer implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/login/*/**"); WebMvcConfigurer.super.addInterceptors(registry); } }
LoginInterceptor:只是實現了三個基本方法,分別打印一句話,了解執行順序:
package org.dreamtech.springboot.interceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; public class LoginInterceptor implements HandlerInterceptor { /** * 攔截之前調用(進入Controller之前) */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("[ preHandle LoginInterceptor ]"); return HandlerInterceptor.super.preHandle(request, response, handler); } /** * 調用方法之后,視圖渲染之前 */ @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("[ postHandle LoginInterceptor ]"); HandlerInterceptor.super.postHandle(request, response, handler, modelAndView); } /** * 完成攔截之后,用於清理資源 */ @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("[ afterCompletion LoginInterceptor ]"); HandlerInterceptor.super.afterCompletion(request, response, handler, ex); } }
Controller:
package org.dreamtech.springboot.controller; import java.util.HashMap; import java.util.Map; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class DemoController { @RequestMapping("/login/account") private Object account() { Map<String, Object> modelMap = new HashMap<String, Object>(); modelMap.put("money", 1000); System.out.println("[ account DemoController ]"); return modelMap; } }
訪問localhost:8080/login/account打印情況如下:
[ preHandle LoginInterceptor ] [ account DemoController ] [ postHandle LoginInterceptor ] [ afterCompletion LoginInterceptor ]
如果沒有以上打印,要注意這幾點:
1.是否有@Configuration注解
2.是否將攔截路徑寫成/xxx/*/**,如果是/xxx/*/*就會攔截失敗
同樣地,我們可以添加多個攔截器
registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/login/*/**"); registry.addInterceptor(new TestInterceptor()).addPathPatterns("/test/*/**"); registry.addInterceptor(new DemoInterceptor()).addPathPatterns("/demo/*/**");
或者鏈式調用:攔截所有路徑,但不包括/login
registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**").excludePathPatterns("/login");
多個攔截器的調用順序:可以理解為包裹的方式
package org.dreamtech.springboot.interceptor; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class CustomWebMvcConfigurer implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/login/*/**"); registry.addInterceptor(new DemoInterceptor()).addPathPatterns("/login/*/**"); WebMvcConfigurer.super.addInterceptors(registry); } }
DemoInterceptor和LoginInterceptor內容基本一致
最終的打印:
[ preHandle LoginInterceptor ] [ preHandle DemoInterceptor ] [ account DemoController ] [ postHandle DemoInterceptor ] [ postHandle LoginInterceptor ] [ afterCompletion DemoInterceptor ] [ afterCompletion LoginInterceptor ]
最后:
Filter和Interceptor的區別:
1.Filter基於Servlet,而Interceptor不依賴於Servlet容器
2.Filter只在容器被初始化的時候被調用一次,Interceptor次數沒有限制
3.Interceptor基於AOP思想,Filter基於doFilter方法
兩者的執行順序:
過濾前->攔截前->Controller->攔截后->過濾后