Filter
過濾器作為web.xml中重要的一部分,有着相當高的出場率,SpringBoot會默認注冊幾個Filter
ApplicationContextHeaderFilter
CharacterEncodingFilter
如果添加了Security依賴的話會加入SpringSecurityFilterChain
如果加入Actuator依賴的話就會加入WebRequestTraceFilter
實現自己的Filter
JavaConfig注冊Bean
我們如果自己要實現自己的Filter的話,需要實現Filter並實現其中的方法
同時要利用JavaConfig的方法來配置,一般情況下需要編寫@Bean注解的返回值為FilterRegistrationBean的方法來實現JavaBean的注冊
具體實現如下
需要注意的是此方法需要在被@Configuration注解的配置類中
@WebFilter+@ServletComponentScan
如果覺得Java代碼的方式比較繁瑣的話可以采用注解方式注冊Filter,具體實現方式是在Filter實現類加入@WebFilter注解
例如
然后在SpringBootApplication類上添加@ServletComponentScan
Filter的注冊原理
我們采用JavaConfig的形式實現了Filter的注冊,通過向上追溯得知FilterRegistrationBean的層級結構如下
ServletContextInitializer
RegistrationBean
AbstractFilterRegistrationBean
FilterRegistrationBean
經查閱SpringBoot文檔發現針對ServletContextInitializer的描述如下
Interface used to configure a Servlet 3.0+
context
programmatically. UnlikeWebApplicationInitializer
, classes that implement this interface (and do not implementWebApplicationInitializer
) will not be detected bySpringServletContainerInitializer
and hence will not be automatically bootstrapped by the Servlet container.This interface is primarily designed to allow
ServletContextInitializer
s to be managed by Spring and not the Servlet container.For configuration examples see
WebApplicationInitializer
.
既然是由SpringBoot進行管理而不是由Servlet容器管理,那么基本可以確定是由SpringBoot進行管理
在org.springframework.boot.context.embedded.tomcat包中我們找到了答案
TomcatEmbeddedServletContainerFactory的一直向上繼承了AbstractConfigurableEmbeddedServletContainer
並且維護了一個私有的List<ServletContextInitializer>變量,我們不難猜出,正是因為FilterRegistrationBean繼承了ServletContextInitializer而實現了Filter的注冊
為了進一步驗證我們的猜測,在注冊Filter的JavaConfig代碼中打了斷點跟蹤一下
可以看到在啟動過程中會獲取類型為ServletContextInitializer的Bean
繼續向下看在SpringBoot內嵌的Tomcat中的TomcatStarter類中也同樣實現了ServletContextInitializer
並且在實現方法中執行了AbstractFilterRegistrationBean實現的onStartup方法
至此Filter注冊成功
Servlet和Listener
Servlet與Listener的支持與Filter大同小異,同樣也是支持兩種方法進行注冊
JavaConfig的話不同的是Servlet需要的是ServletRegistrationBean,而Listener需要的是ServletListenerRegistrationBean
注解的話則分別是通過@WebServlet、@WebListener進行注解
至於注冊管理過程則基本與Filter相同