一文詳解Springboot中filter的原理與注冊(cè)
1、filter
先看下web服務(wù)器的filter所處的位置。filter是一個(gè)前后連接的鏈,前面處理完成之后傳遞給下一個(gè)filter處理。
1.1 filter的接口定義
public interface Filter { //初始化方法,整個(gè)生命周期中只執(zhí)行一次。 //在init方法成功(失敗如拋異常等)執(zhí)行完前,不能提供過濾服務(wù)。 //參數(shù)FilterConfig用于獲取初始化參數(shù) public void init(FilterConfig filterConfig) throws ServletException; //執(zhí)行過濾任務(wù)的方法,參數(shù)FilterChain表示過濾器鏈,doFilter方法中只有執(zhí)行chain.doFilter()后才能調(diào)用下一個(gè)過濾器的doFilter方法 //才能將請(qǐng)求交經(jīng)下一個(gè)Filter或Servlet執(zhí)行 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException; //銷毀方法,當(dāng)移出服務(wù)時(shí)由web容器調(diào)用。整個(gè)生命周期中destroy方法只會(huì)執(zhí)行一次 //destroy方法可用于釋放持有的資源,如內(nèi)存、文件句柄等 public void destroy(); }
filter的入?yún)⑹莚equest和response,filter一般是用來做一些預(yù)處理工作,比如做一些檢查,驗(yàn)證等工作。
1.2 自定義filter
public class LoginFilter implements Filter { @Override public void destroy() { System.out.println("filter destroy method"); } @Override public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain filterChain) throws IOException, ServletException { System.out.println("filter doFilter method "); // 繼續(xù)傳遞下去 filterChain.doFilter(arg0,arg1); } @Override public void init(FilterConfig arg0) throws ServletException { System.out.println("filter init method"); } }
2、springboot中filter注冊(cè)幾種方式
2.1 手動(dòng)注冊(cè)
@Configuration public class FilterConfig { @Bean public FilterRegistrationBean indexFilterRegistration() { FilterRegistrationBean registration = new FilterRegistrationBean(new LoginFilter()); registration.addUrlPatterns("/"); return registration; } }
2.2 注解注冊(cè)
2.2.1 在filter上增加注解@WebFilter
@WebFilter(urlPatterns = "/",filterName = "filter1") @Order(1) public class LoginFilter implements Filter { @Override public void destroy() { System.out.println("filter destroy method"); } @Override public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain filterChain) throws IOException, ServletException { System.out.println("filter doFilter method 1 "); filterChain.doFilter(arg0,arg1); } @Override public void init(FilterConfig arg0) throws ServletException { System.out.println("filter init method"); } }
2.2.2 在啟動(dòng)類上增加注解@ServletComponentScan
@SpringBootApplication @ServletComponentScan public class FilterTestApplication { public static void main(String[] args) { SpringApplication.run(FilterTestApplication.class, args); } }
注:
@ServletComponentScan 會(huì)掃描所有的帶有@WebFilter的類,并且注冊(cè)為servlet。
如果啟動(dòng)類不添加此注解,在filter上添加Component注解也可以注冊(cè)為filter
order注解可以調(diào)整filter的順序
2.3 通過servletContext 注冊(cè)
@Autowired ServletContext servletContext; servletContext.addFilter()
3、原理
3.1 ServletContext
Web容器在啟動(dòng)時(shí)會(huì)為每個(gè)web應(yīng)用創(chuàng)建一個(gè)ServletContext對(duì)象,而這個(gè)ServletContext對(duì)象就代表當(dāng)前這個(gè)web應(yīng)用。
一個(gè)ServletContext對(duì)象代表一個(gè)web應(yīng)用,web應(yīng)用中所有的Servlet和其他資源都共享一個(gè)ServletContext對(duì)象,
如果有必要我們就可以通過ServletContext對(duì)象進(jìn)行Servlet之間的通訊。
ServletContext,是一個(gè)全局的儲(chǔ)存信息的空間,服務(wù)器開始,其就存在,服務(wù)器關(guān)閉,其才釋放。request,一個(gè)用戶可有多個(gè);session,一個(gè)用戶一個(gè);而servletContext,所有用戶共用一個(gè)。
ApplicationContext 是ServletContext的實(shí)現(xiàn)類,可以看到里面有相應(yīng)的注冊(cè)的方法
在程序中獲取ServletContext
3.1.1 使用自動(dòng)注入
@Autowired private ServletContext servletContext;
3.1.2 request獲取servletContext
ServletContext servletContext = request.getServletContext();
3.1.3 實(shí)現(xiàn) ServletContextListener
@Component public class TestListener implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent sce) { System.out.println(sce); } }
3.2 ServletRegistrationBean
看下Filter的定義,可以看到和webfilter注解內(nèi)容一樣
public class ServletRegistrationBean<T extends Servlet> extends DynamicRegistrationBean<ServletRegistration.Dynamic> { private static final String[] DEFAULT_MAPPINGS = new String[]{"/*"}; private T servlet; private Set<String> urlMappings; private boolean alwaysMapUrl; private int loadOnStartup; private MultipartConfigElement multipartConfig; ...... }
在開發(fā)中一般使用他的子類FilterRegistrationBean,使用上面2.1 手動(dòng)注冊(cè)
4、總結(jié)
filter 作為web服務(wù)器中的重要的一部分,一般常用來做一些前置處理和對(duì)調(diào)用請(qǐng)求的中斷
filter的注冊(cè)幾種方式總結(jié),在開發(fā)中一般靈活使用,沒有特殊的請(qǐng)求,常規(guī)都?jí)蛴?/p>
了解原理是為了更好的理解,filter的過濾鏈?zhǔn)絊pring Security的重要切入點(diǎn),理解了filter再理解其他的框架就不難了,甚至可以自己簡(jiǎn)單寫出一個(gè)列斯的框架
到此這篇關(guān)于一文詳解Springboot中filter的原理與注冊(cè)的文章就介紹到這了,更多相關(guān)Springboot filter內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
BiConsumer接口中的方法andThen?accept使用詳解
這篇文章主要為大家介紹了BiConsumer接口中的方法andThen?accept使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07基于Eclipse 的JSP/Servlet的開發(fā)環(huán)境的搭建(圖文)
本文將會(huì)詳細(xì)地展示如何搭建JSP的開發(fā)環(huán)境。本次教程使用的是最新版的Eclipse 2018-09編輯器和最新版的Apache Tomcat v9.0,步驟詳細(xì),內(nèi)容詳盡,適合零基礎(chǔ)學(xué)者作為學(xué)習(xí)參考2018-12-12Java使用Queryable-pageable實(shí)現(xiàn)分頁效果
這篇文章主要為大家介紹了Java如何使用Queryable-pageable從而實(shí)現(xiàn)分頁效果,文中的示例代碼簡(jiǎn)潔易懂,感興趣的小伙伴可以動(dòng)手嘗試一下2022-06-06java實(shí)現(xiàn)微信公眾平臺(tái)自定義菜單的創(chuàng)建示例
這篇文章主要介紹了java實(shí)現(xiàn)微信公眾平臺(tái)自定義菜單的創(chuàng)建示例,需要的朋友可以參考下2014-04-04Java的CyclicBarrier循環(huán)屏障解析
這篇文章主要介紹了Java的CyclicBarrier循環(huán)屏障解析,CyclicBarrier和CountDownLatch一樣,是一個(gè)同步工具類,它允許一組線程相互等待直到達(dá)到某個(gè)common?barrier?point,在程序中CyclicBarrier是非常有用的,它適用于一組線程必須互相等待的情況,需要的朋友可以參考下2023-12-12java對(duì)象克隆實(shí)現(xiàn)方法詳解
這篇文章主要給大家介紹了關(guān)于java對(duì)象克隆實(shí)現(xiàn)的相關(guān)資料,克隆就是復(fù)制一個(gè)對(duì)象的副本,Java支持我們對(duì)一個(gè)對(duì)象進(jìn)行克隆,通常用在裝飾模式和原型模式中,需要的朋友可以參考下2023-06-06Java如何比較兩個(gè)對(duì)象并獲取不相等的字段詳解
這篇文章主要給大家介紹了關(guān)于Java如何比較兩個(gè)對(duì)象并獲取不相等的字段以及JAVA判斷(獲?。﹥蓚€(gè)相同對(duì)象不同的數(shù)據(jù)的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用java具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2021-11-11