要說在 Spring Boot 中註冊過濾器有三種方式,你都能想到哪些呢?今天鬆哥就來和你們聊一聊 Spring Boot 中註冊過濾器的三種方式!java
其實原本是想和你們聊 Spring Security 過濾器鏈的問題的,結果看源碼看着看着就跑題了,索性就先和你們聊一聊 Spring Boot 中註冊過濾器的三種方式,算是給 後面的 Spring Security 打一點基礎。git
經過 @WebFilter 註解來標記一個過濾器,這種方式相信你們很容易想到。這是將 Servlet 中的那一套東西直接拿到 Spring Boot 上用。github
具體作法就是經過 @WebFilter 註解來標記一個 Filter,以下:api
@WebFilter(urlPatterns = "/*") public class MyFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("-----doFilter-----"); chain.doFilter(request, response); } }
在 @WebFilter 註解中能夠配置過濾器的攔截規則。這個註解要生效,還須要咱們在項目啓動類上配置 @ServletComponentScan 註解,以下:ide
@SpringBootApplication @ServletComponentScan public class FilterdemoApplication { public static void main(String[] args) { SpringApplication.run(FilterdemoApplication.class, args); } }
@ServletComponentScan 註解雖然名字帶了 Servlet,可是實際上它不單單能夠掃描項目中的 Servlet 容器,也能夠掃描 Filter 和 Listener。this
這是咱們在 Spring Boot 中使用過濾器的第一種方式,在實際項目中,這種方式使用較少,由於這種方式有一個很大的弊端就是沒法指定 Filter 的優先級,若是存在多個 Filter 時,沒法經過 @Order 指定優先級。url
第二種方式就是將過濾器配置成 Bean,註冊到 Spring 容器中去。這種方法再也不須要 @ServletComponentScan 註解,只要一個 Bean 便可,以下:spa
@Component public class MyFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("-----doFilter-----"); chain.doFilter(request, response); } }
這種方式看起來很方便,一個註解將 Filter 歸入到 Spring 容器中便可。並且這種方式還有一個優點,就是若是存在多個 Filter,能夠經過 @Order 註解指定多個 Filter 的優先級,像下面這樣:code
@Component @Order(-1) public class MyFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("-----doFilter-----"); chain.doFilter(request, response); } }
雖然解決了優先級問題,可是你們發現這種方式好像沒有辦法設置 Filter 的攔截規則!是的,直接定義 Bean 的話,默認的攔截規則就是 /*
即攔截全部請求,開發者沒法進行自定義配置。blog
那麼有沒有辦法即配置攔截規則,又配置優先級呢?接下來介紹的第三種方案能夠魚與熊掌兼得。
第三種方案仍是將 Filter 封裝成一個 Bean,但這個 Bean 是 FilterRegistrationBean,經過 FilterRegistrationBean 咱們既能夠配置 Filter 的優先級,也能夠配置 Filter 的攔截規則。
通常在項目中,咱們都是使用 FilterRegistrationBean 來配置過濾器,一塊兒來看一個案例:
@Configuration public class FilterConfiguration { @Bean FilterRegistrationBean<MyFilter> myFilterFilterRegistrationBean() { FilterRegistrationBean<MyFilter> bean = new FilterRegistrationBean<>(); bean.setFilter(new MyFilter()); bean.setOrder(-1); bean.setUrlPatterns(Arrays.asList("/*")); return bean; } @Bean FilterRegistrationBean<MyFilter2> myFilterFilterRegistrationBean2() { FilterRegistrationBean<MyFilter2> bean = new FilterRegistrationBean<>(); bean.setFilter(new MyFilter2()); bean.setOrder(-2); bean.setUrlPatterns(Arrays.asList("/hello")); return bean; } }
FilterRegistrationBean 究竟是什麼來頭呢?這裏也和你們分享下。
Spring Boot 爲了方便你們向 Servlet 容器中註冊 Servlet、Filter 以及 Listener,提供了一個 Bean 註冊的抽象類 RegistrationBean,以下:
public abstract class RegistrationBean implements ServletContextInitializer, Ordered { private int order = Ordered.LOWEST_PRECEDENCE; private boolean enabled = true; @Override public final void onStartup(ServletContext servletContext) throws ServletException { String description = getDescription(); if (!isEnabled()) { logger.info(StringUtils.capitalize(description) + " was not registered (disabled)"); return; } register(description, servletContext); } protected abstract String getDescription(); protected abstract void register(String description, ServletContext servletContext); public void setEnabled(boolean enabled) { this.enabled = enabled; } public boolean isEnabled() { return this.enabled; } public void setOrder(int order) { this.order = order; } @Override public int getOrder() { return this.order; } }
RegistrationBean 有衆多的實現類,咱們以前使用的 FilterRegistrationBean 只是其中之一:
實現類的做用一目瞭然:
今天就和小夥伴們分享一下 Spring Boot 中過濾器的三種註冊方式,順帶和你們分享了一下 FilterRegistrationBean 的繼承體系,小夥伴們能夠根據 FilterRegistrationBean 的繼承體系中的實現類,自行嘗試一下 Servlet 和 Listener 的註冊方式~本文案例下載地址:https://github.com/lenve/javaboy-code-samples
好啦,若是你們以爲有收穫的話,記得點個在看鼓勵下鬆哥哦~