<div class="htmledit_views">html
<h1 style="margin:0px;padding:0px;color:rgb(51,51,51);font-size:24px;font-weight:normal;line-height:1.25;border-bottom-color:rgb(204,204,204);font-family:Arial, sans-serif;"> Filter</h1> <p style="margin-top:10px;margin-bottom:0px;padding-top:0px;padding-bottom:0px;color:rgb(51,51,51);font-family:Arial, sans-serif;font-size:14px;"> 過濾器做爲web.xml中重要的一部分,有着至關高的出場率,SpringBoot會默認註冊幾個Filter</p> <p style="margin-top:10px;margin-bottom:0px;margin-left:30px;padding-top:0px;padding-bottom:0px;color:rgb(51,51,51);font-family:Arial, sans-serif;font-size:14px;"> <strong>ApplicationContextHeaderFilter</strong></p> <p style="margin-top:10px;margin-bottom:0px;margin-left:30px;padding-top:0px;padding-bottom:0px;color:rgb(51,51,51);font-family:Arial, sans-serif;font-size:14px;"> <strong>CharacterEncodingFilter</strong></p> <p style="margin-top:10px;margin-bottom:0px;padding-top:0px;padding-bottom:0px;color:rgb(51,51,51);font-family:Arial, sans-serif;font-size:14px;"> 若是添加了Security依賴的話會加入<strong>SpringSecurityFilterChain</strong></p> <p style="margin-top:10px;margin-bottom:0px;padding-top:0px;padding-bottom:0px;color:rgb(51,51,51);font-family:Arial, sans-serif;font-size:14px;"> 若是加入Actuator依賴的話就會加入<strong>WebRequestTraceFilter</strong></p> <h3 style="margin:30px 0px 0px;padding:0px;color:rgb(51,51,51);font-size:16px;line-height:1.5;font-family:Arial, sans-serif;"> <strong>實現本身的Filter</strong></h3> <h4 style="margin:10px 0px 0px 30px;padding:0px;color:rgb(51,51,51);font-size:14px;line-height:1.42857;font-family:Arial, sans-serif;"> JavaConfig註冊Bean</h4> <p style="margin-top:10px;margin-bottom:0px;margin-left:30px;padding-top:0px;padding-bottom:0px;color:rgb(51,51,51);font-family:Arial, sans-serif;font-size:14px;"> 咱們若是本身要實現本身的Filter的話,須要實現Filter並實現其中的方法</p> <p style="margin-top:10px;margin-bottom:0px;margin-left:30px;padding-top:0px;padding-bottom:0px;color:rgb(51,51,51);font-family:Arial, sans-serif;font-size:14px;"> 同時要利用JavaConfig的方法來配置,通常狀況下須要編寫@Bean註解的返回值爲FilterRegistrationBean的方法來實現JavaBean的註冊</p> <p style="margin-top:10px;margin-bottom:0px;margin-left:30px;padding-top:0px;padding-bottom:0px;color:rgb(51,51,51);font-family:Arial, sans-serif;font-size:14px;"> 具體實現以下</p> <p style="margin-top:10px;margin-bottom:0px;margin-left:30px;padding-top:0px;padding-bottom:0px;color:rgb(51,51,51);font-family:Arial, sans-serif;font-size:14px;"> <span class="confluence-embedded-file-wrapper" style="display:inline-block;"><img class="confluence-embedded-image" src="http://wiki.vipkid.com.cn/download/attachments/8587168/image2017-3-2%2019%3A31%3A31.png?version=1&modificationDate=1488454484000&api=v2" alt="" style="margin:0px 2px;padding:0px;border:0px;display:block;"></span></p> <p style="margin-top:10px;margin-bottom:0px;margin-left:30px;padding-top:0px;padding-bottom:0px;color:rgb(51,51,51);font-family:Arial, sans-serif;font-size:14px;"> 須要注意的是此方法須要在被<span style="color:rgb(187,181,41);">@Configuration</span>註解的配置類中</p> <h4 style="margin:20px 0px 0px 30px;padding:0px;color:rgb(51,51,51);font-size:14px;line-height:1.42857;font-family:Arial, sans-serif;"> <span style="color:rgb(0,0,0);">@WebFilter+@ServletComponentScan</span></h4> <p style="margin-top:10px;margin-bottom:0px;margin-left:30px;padding-top:0px;padding-bottom:0px;color:rgb(51,51,51);font-family:Arial, sans-serif;font-size:14px;"> <span style="color:rgb(0,0,0);">若是以爲Java代碼的方式比較繁瑣的話能夠採用註解方式註冊Filter,具體實現方式是在Filter實現類加入@WebFilter註解</span></p> <p style="margin-top:10px;margin-bottom:0px;margin-left:30px;padding-top:0px;padding-bottom:0px;color:rgb(51,51,51);font-family:Arial, sans-serif;font-size:14px;"> <span style="color:rgb(0,0,0);">例如</span></p> <p style="margin-top:10px;margin-bottom:0px;margin-left:30px;padding-top:0px;padding-bottom:0px;color:rgb(51,51,51);font-family:Arial, sans-serif;font-size:14px;"> <span class="confluence-embedded-file-wrapper" style="display:inline-block;"><img class="confluence-embedded-image" src="http://wiki.vipkid.com.cn/download/attachments/8587168/image2017-3-3%2011%3A36%3A54.png?version=1&modificationDate=1488512224000&api=v2" alt="" style="margin:0px 2px;padding:0px;border:0px;display:block;"></span></p> <p style="margin-top:10px;margin-bottom:0px;margin-left:30px;padding-top:0px;padding-bottom:0px;color:rgb(51,51,51);font-family:Arial, sans-serif;font-size:14px;"> 而後在SpringBootApplication類上添加@ServletComponentScan</p> <h3 style="margin:30px 0px 0px;padding:0px;color:rgb(51,51,51);font-size:16px;line-height:1.5;font-family:Arial, sans-serif;"> Filter的註冊原理</h3> <p style="margin-top:10px;margin-bottom:0px;padding-top:0px;padding-bottom:0px;color:rgb(51,51,51);font-family:Arial, sans-serif;font-size:14px;"> 咱們採用JavaConfig的形式實現了Filter的註冊,經過向上追溯得知FilterRegistrationBean的層級結構以下</p> <p style="margin-top:10px;margin-bottom:0px;padding-top:0px;padding-bottom:0px;color:rgb(51,51,51);font-family:Arial, sans-serif;font-size:14px;"> ServletContextInitializer</p> <p style="margin-top:10px;margin-bottom:0px;margin-left:30px;padding-top:0px;padding-bottom:0px;color:rgb(51,51,51);font-family:Arial, sans-serif;font-size:14px;"> RegistrationBean</p> <p style="margin-top:10px;margin-bottom:0px;margin-left:60px;padding-top:0px;padding-bottom:0px;color:rgb(51,51,51);font-family:Arial, sans-serif;font-size:14px;"> AbstractFilterRegistrationBean</p> <p style="margin-top:10px;margin-bottom:0px;margin-left:90px;padding-top:0px;padding-bottom:0px;color:rgb(51,51,51);font-family:Arial, sans-serif;font-size:14px;"> FilterRegistrationBean</p> <p style="margin-top:10px;margin-bottom:0px;padding-top:0px;padding-bottom:0px;color:rgb(51,51,51);font-family:Arial, sans-serif;font-size:14px;"> 經查閱SpringBoot文檔發現針對ServletContextInitializer的描述以下</p> <blockquote style="margin:10px 0px 0px 19px;border-left:1px solid rgb(204,204,204);color:rgb(112,112,112);padding:10px 20px;font-family:Arial, sans-serif;font-size:14px;"> <p style="margin-top:0px;margin-bottom:0px;padding-top:0px;padding-bottom:0px;"> <span style="color:rgb(71,71,71);">Interface used to configure a Servlet 3.0+ </span><a title="class or interface in javax.servlet" href="https://docs.oracle.com/javaee/7/api/javax/servlet/ServletContext.html?is-external=true" class="external-link" style="color:rgb(53,114,176);text-decoration:none;" target="_blank"><code>context</code></a><span style="color:rgb(71,71,71);"> programmatically. Unlike </span><a title="class or interface in org.springframework.web" href="http://docs.spring.io/spring-framework/docs/4.3.6.RELEASE/javadoc-api/org/springframework/web/WebApplicationInitializer.html?is-external=true" class="external-link" style="color:rgb(53,114,176);text-decoration:none;" target="_blank"><code>WebApplicationInitializer</code></a><span style="color:rgb(71,71,71);">, classes that implement this interface (and do not implement </span><a title="class or interface in org.springframework.web" href="http://docs.spring.io/spring-framework/docs/4.3.6.RELEASE/javadoc-api/org/springframework/web/WebApplicationInitializer.html?is-external=true" class="external-link" style="color:rgb(53,114,176);text-decoration:none;" target="_blank"><code>WebApplicationInitializer</code></a><span style="color:rgb(71,71,71);">) will </span><strong>not</strong><span style="color:rgb(71,71,71);"> be detected by </span><a title="class or interface in org.springframework.web" href="http://docs.spring.io/spring-framework/docs/4.3.6.RELEASE/javadoc-api/org/springframework/web/SpringServletContainerInitializer.html?is-external=true" class="external-link" style="color:rgb(53,114,176);text-decoration:none;" target="_blank"><code>SpringServletContainerInitializer</code></a><span style="color:rgb(71,71,71);"> and hence will not be automatically bootstrapped by the Servlet container.</span></p> <p style="margin-top:10px;margin-bottom:0px;padding-top:0px;padding-bottom:0px;"> This interface is primarily designed to allow <a title="interface in org.springframework.boot.web.servlet" href="http://docs.spring.io/spring-boot/docs/1.5.1.RELEASE/api/org/springframework/boot/web/servlet/ServletContextInitializer.html" class="external-link" style="color:rgb(53,114,176);text-decoration:none;" target="_blank"><code>ServletContextInitializer</code></a>s to be managed by Spring and not the Servlet container.</p> <p style="margin-top:10px;margin-bottom:0px;padding-top:0px;padding-bottom:0px;"> For configuration examples see <a title="class or interface in org.springframework.web" href="http://docs.spring.io/spring-framework/docs/4.3.6.RELEASE/javadoc-api/org/springframework/web/WebApplicationInitializer.html?is-external=true" class="external-link" style="color:rgb(53,114,176);text-decoration:none;" target="_blank"><code>WebApplicationInitializer</code></a>.</p> </blockquote> <p style="margin-top:10px;margin-bottom:0px;padding-top:0px;padding-bottom:0px;color:rgb(51,51,51);font-family:Arial, sans-serif;font-size:14px;"> 既然是由SpringBoot進行管理而不是由Servlet容器管理,那麼基本能夠肯定是由SpringBoot進行管理</p> <p style="margin-top:10px;margin-bottom:0px;padding-top:0px;padding-bottom:0px;color:rgb(51,51,51);font-family:Arial, sans-serif;font-size:14px;"> 在org.springframework.boot.context.embedded.tomcat包中咱們找到了答案</p> <p style="margin-top:10px;margin-bottom:0px;padding-top:0px;padding-bottom:0px;color:rgb(51,51,51);font-family:Arial, sans-serif;font-size:14px;"> TomcatEmbeddedServletContainerFactory的一直向上繼承了AbstractConfigurableEmbeddedServletContainer</p> <p style="margin-top:10px;margin-bottom:0px;padding-top:0px;padding-bottom:0px;color:rgb(51,51,51);font-family:Arial, sans-serif;font-size:14px;"> 而且維護了一個私有的List<ServletContextInitializer>變量,咱們不難猜出,正是由於FilterRegistrationBean繼承了ServletContextInitializer而實現了Filter的註冊</p> <p style="margin-top:10px;margin-bottom:0px;padding-top:0px;padding-bottom:0px;color:rgb(51,51,51);font-family:Arial, sans-serif;font-size:14px;"> 爲了進一步驗證咱們的猜想,在註冊Filter的JavaConfig代碼中打了斷點跟蹤一下</p> <p style="margin-top:10px;margin-bottom:0px;padding-top:0px;padding-bottom:0px;color:rgb(51,51,51);font-family:Arial, sans-serif;font-size:14px;"> <span class="confluence-embedded-file-wrapper confluence-embedded-manual-size" style="display:inline-block;"><img class="confluence-embedded-image" height="400" src="http://wiki.vipkid.com.cn/download/attachments/8587168/image2017-3-3%2014%3A32%3A23.png?version=1&modificationDate=1488522753000&api=v2" alt="" style="margin:0px 2px;padding:0px;border:0px;display:block;"></span></p> <p style="margin-top:10px;margin-bottom:0px;padding-top:0px;padding-bottom:0px;color:rgb(51,51,51);font-family:Arial, sans-serif;font-size:14px;"> 能夠看到在啓動過程當中會獲取類型爲ServletContextInitializer的Bean</p> <p style="margin-top:10px;margin-bottom:0px;padding-top:0px;padding-bottom:0px;color:rgb(51,51,51);font-family:Arial, sans-serif;font-size:14px;"> 繼續向下看在SpringBoot內嵌的Tomcat中的TomcatStarter類中也一樣實現了ServletContextInitializer</p> <p style="margin-top:10px;margin-bottom:0px;padding-top:0px;padding-bottom:0px;color:rgb(51,51,51);font-family:Arial, sans-serif;font-size:14px;"> <span class="confluence-embedded-file-wrapper confluence-embedded-manual-size" style="display:inline-block;"><img class="confluence-embedded-image" height="250" src="http://wiki.vipkid.com.cn/download/attachments/8587168/QQ%E6%88%AA%E5%9B%BE20170303144047.png?version=2&modificationDate=1488523512000&api=v2" alt="" style="margin:0px 2px;padding:0px;border:0px;display:block;"></span><br></p> <p style="margin-top:10px;margin-bottom:0px;padding-top:0px;padding-bottom:0px;color:rgb(51,51,51);font-family:Arial, sans-serif;font-size:14px;"> </p> <p style="margin-top:10px;margin-bottom:0px;padding-top:0px;padding-bottom:0px;color:rgb(51,51,51);font-family:Arial, sans-serif;font-size:14px;"> 而且在實現方法中執行了AbstractFilterRegistrationBean實現的onStartup方法</p> <p style="margin-top:10px;margin-bottom:0px;padding-top:0px;padding-bottom:0px;color:rgb(51,51,51);font-family:Arial, sans-serif;font-size:14px;"> <span class="confluence-embedded-file-wrapper confluence-embedded-manual-size" style="display:inline-block;"><img class="confluence-embedded-image" height="250" src="http://wiki.vipkid.com.cn/download/attachments/8587168/QQ%E6%88%AA%E5%9B%BE20170303144047.png?version=2&modificationDate=1488523512000&api=v2" alt="" style="margin:0px 2px;padding:0px;border:0px;display:block;"></span></p> <p style="margin-top:10px;margin-bottom:0px;padding-top:0px;padding-bottom:0px;color:rgb(51,51,51);font-family:Arial, sans-serif;font-size:14px;"> 至此Filter註冊成功</p> <h1 style="margin:30px 0px 0px;padding:0px;color:rgb(51,51,51);font-size:24px;font-weight:normal;line-height:1.25;border-bottom-color:rgb(204,204,204);font-family:Arial, sans-serif;"> Servlet和Listener</h1> <p style="margin-top:10px;margin-bottom:0px;padding-top:0px;padding-bottom:0px;color:rgb(51,51,51);font-family:Arial, sans-serif;font-size:14px;"> Servlet與Listener的支持與Filter大同小異,一樣也是支持兩種方法進行註冊</p> <p style="margin-top:10px;margin-bottom:0px;padding-top:0px;padding-bottom:0px;color:rgb(51,51,51);font-family:Arial, sans-serif;font-size:14px;"> <span style="color:rgb(85,85,85);">JavaConfig的話不一樣的是Servlet須要的是ServletRegistrationBean,而Listener須要的是ServletListenerRegistrationBean</span></p> <p style="margin-top:10px;margin-bottom:0px;padding-top:0px;padding-bottom:0px;color:rgb(51,51,51);font-family:Arial, sans-serif;font-size:14px;"> <span style="color:rgb(85,85,85);">註解的話則分別是經過@WebServlet、@WebListener進行註解</span></p> <p style="margin-top:10px;margin-bottom:0px;padding-top:0px;padding-bottom:0px;color:rgb(51,51,51);font-family:Arial, sans-serif;font-size:14px;"> <span style="color:rgb(85,85,85);">至於註冊管理過程則基本與Filter相同</span></p> </div>java