當自定義 filter 時候,要把你的類實現 Filter 接口,或繼承它的子類。然後通過 FilterRegistrationBean 註冊到 filterChain 中。
你可能沒有注意這個細節,就算不做後面那一步,你的 Filter 類也能夠自動添加到 filterChain 中。
這是怎麼做到的呢?在 ServletContextInitializerBeans 中,有這麼一個方法:
被標的兩行,在初始過程中有特殊的行爲:只要類實現 Servlet 或 Filter 接口,如果沒有找到 register bean 就會自動爲其創建一個 register bean,後面就會具有 servlet 或 filter 的行爲。
這個細節有什麼用?
如果你在寫一個框架,並且框架中寫了一個 Filter, 而不加思索地在這個類上加了 @Service 或 @Component 註解,那麼它就變成了一個不可繞過的 filter. 對於框架使用者,就會很痛苦,不想用這個 filter 也不行,甚至想重寫它的行爲也做不到!因此,爲了可擴展和兼容性,使你的框架變得更友好,最好是把它變成 bean 的半成品,不加 @Service 或 @Component 註解,後面在 configuration 中通過 @Bean 的方式定義這個 bean, 以實現可控的初始化。在定義 @Bean 的時候,可以通過 @ConditionOnMissingBean 這種註解,給客戶以自定義的能力。
// 不加 @Component
public MyFilter implement Filter {
//...
}
@Configuration
public MyConfig {
@ConditionOnMissingBean("myFilterBean")
@Bean
public MyFilter myFilterBean(){
return new MyFilter();
}
@ConditionOnMissingBean("myFilter")
@Bean
public FilterRegistrationBean<MyFilter> myFilter(MyFilter myFilterBean) {
FilterRegistrationBean<MyFilter> registration = new FilterRegistrationBean<>(myFilterBean);
registration.addUrlPatterns("/*");
registration.setName("myFilter");
registration.setOrder(1);
return registration;
}
}