javascript
SpringBoot拦截器与过滤器
一、攔截器與過濾器
在講Spring boot之前,我們先了解一下過濾器和攔截器。這兩者在功能方面很類似,但是在具體技術實現方面,差距還是比較大的。在分析兩者的區別之前,我們先理解一下AOP的概念,AOP不是一種具體的技術,而是一種編程思想。在面向對象編程的過程中,我們很容易通過繼承、多態來解決縱向擴展。但是對于橫向的功能,比如,在所有的service方法中開啟事務,或者統一記錄日志等功能,面向對象的是無法解決的。所以AOP——面向切面編程其實是面向對象編程思想的一個補充。而我們今天講的過濾器和攔截器都屬于面向切面編程的具體實現。而兩者的主要區別包括以下幾個方面:
-
Filter是依賴于Servlet容器,屬于Servlet規范的一部分,而攔截器則是獨立存在的,可以在任何情況下使用。
-
Filter的執行由Servlet容器回調完成,而攔截器通常通過動態代理的方式來執行。
-
Filter的生命周期由Servlet容器管理,而攔截器則可以通過IoC容器來管理,因此可以通過注入等方式來獲取其他Bean的實例,因此使用會更方便。
二、過濾器的配置
現在我們通過過濾器來實現記錄請求執行時間的功能,其實現如下:
public class LogCostFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {long start = System.currentTimeMillis();filterChain.doFilter(servletRequest,servletResponse);System.out.println("Execute cost="+(System.currentTimeMillis()-start));}@Overridepublic void destroy() {} }這段代碼的邏輯比較簡單,就是在方法執行前先記錄時間戳,然后通過過濾器鏈完成請求的執行,在返回結果之間計算執行的時間。這里需要主要,這個類必須繼承Filter類,這個是Servlet的規范,這個跟以前的Web項目沒區別。但是,有了過濾器類以后,以前的web項目可以在web.xml中進行配置,但是spring boot項目并沒有web.xml這個文件,那怎么配置?在Spring boot中,我們需要FilterRegistrationBean來完成配置。其實現過程如下:
@Configuration public class FilterConfig {@Beanpublic FilterRegistrationBean registFilter() {FilterRegistrationBean registration = new FilterRegistrationBean();registration.setFilter(new LogCostFilter());registration.addUrlPatterns("/*");registration.setName("LogCostFilter");registration.setOrder(1);return registration;}}這樣配置就完成了,需要配置的選項主要包括實例化Filter類,然后指定url的匹配模式,設置過濾器名稱和執行順序,這個過程和在web.xml中配置其實沒什么區別,只是形式不同而已。現在我們可以啟動服務器訪問任意URL:
可以看到上面的配置已經生效了。除了通過 FilterRegistrationBean 來配置以外,還有一種更直接的辦法,直接通過注解就可以完成了:
這里直接用@WebFilter就可以進行配置,同樣,可以設置url匹配模式,過濾器名稱等。這里需要注意一點的是@WebFilter這個注解是Servlet3.0的規范,并不是Spring boot提供的。除了這個注解以外,我們還需在配置類中加另外一個注解:@ServletComponetScan,指定掃描的包。
@SpringBootApplication @MapperScan("com.pandy.blog.dao") @ServletComponentScan("com.pandy.blog.filters") public class Application {public static void main(String[] args) throws Exception {SpringApplication.run(Application.class, args);} }
現在,我們再來訪問一下任意URL:
可以看到,我們配置的兩個過濾器都生效了。細心的讀者會發現,第二個Filter我們并沒有指定執行的順序,但是卻在第一個Filter之前執行。這里需要解釋一下,@WebFilter這個注解并沒有指定執行順序的屬性,其執行順序依賴于Filter的名稱,是根據Filter類名(注意不是配置的filter的名字)的字母順序倒序排列,并且@WebFilter指定的過濾器優先級都高于FilterRegistrationBean配置的過濾器。
三、springboot攔截器的配置
上面我們已經介紹了過濾器的配置方法,接下來我們再來看看如何配置一個攔截器。其實spring boot攔截器的配置方式和springMVC差不多,只有一些小的改變需要注意下就ok了。下面主要介紹兩種常用的攔截器:
關鍵代碼:path.matches(Const.NO_INTERCEPTOR_PATH 就是基于正則匹配的url。
/*** @author BianP* @explain 常量類*/ public class Const {public static final String SUCCESS = "SUCCESS";public static final String ERROR = "ERROR";public static final String FIALL = "FIALL";/**********************對象和個體****************************/public static final String SESSION_USER = "loginedAgent"; // 用戶對象public static final String SESSION_LOGINID = "sessionLoginID"; // 登錄IDpublic static final String SESSION_USERID = "sessionUserID"; // 當前用戶對象ID編號public static final String SESSION_USERNAME = "sessionUserName"; // 當前用戶對象ID編號public static final Integer PAGE = 10; // 默認分頁數public static final String SESSION_URL = "sessionUrl"; // 被記錄的urlpublic static final String SESSION_SECURITY_CODE = "sessionVerifyCode"; // 登錄頁驗證碼// 時間 緩存時間public static final int TIMEOUT = 1800;// 秒public static final String ON_LOGIN = "/logout.htm";public static final String LOGIN_OUT = "/toLogout";// 不驗證URL anon:不驗證/authc:受控制的public static final String NO_INTERCEPTOR_PATH =".*/((.css)|(.js)|(images)|(login)|(anon)).*"; }①創建注解:
②創建攔截器:
public class AuthorityInterceptor extends HandlerInterceptorAdapter{@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 如果不是映射到方法直接通過if (!(handler instanceof HandlerMethod)) {return true;}// ①:START 方法注解級攔截器HandlerMethod handlerMethod = (HandlerMethod) handler;Method method = handlerMethod.getMethod();// 判斷接口是否需要登錄LoginRequired methodAnnotation = method.getAnnotation(LoginRequired.class);// 有 @LoginRequired 注解,需要認證if (methodAnnotation != null) {// 這寫你攔截需要干的事兒,比如取緩存,SESSION,權限判斷等System.out.println("====================================");return true;}return true;} }-
一定要加@Configuration 這個注解,在啟動的時候在會被加載。
-
有一些教程是用的“WebMvcConfigurerAdapter”,不過在spring5.0版本后這個類被丟棄了WebMvcConfigurerAdapter ,雖然還可以用,但是看起來不好。
-
也有一些教程使用的WebMvcConfigurationSupport,我使用后發現,classpath:/META/resources/,classpath:/resources/,classpath:/static/,classpath:/public/)不生效。具體可以原因,大家可以看下源碼因為:WebMvcAutoConfiguration上有個條件注解: @ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
所以還是建議使用WebMvcConfigurer。
其實springMVC很多東西,都可以搬到springboot中來使用,只需要把配置文件的模式,改成 對應@Configuration 類就好了。
文章轉自
文章轉自
總結
以上是生活随笔為你收集整理的SpringBoot拦截器与过滤器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: springboot MVC视图解析流程
- 下一篇: SpringBoot文件上传源码解析