一文詳解Springboot中filter的原理與注冊
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方法
//才能將請求交經(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方法只會執(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注冊幾種方式
2.1 手動注冊
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean indexFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean(new LoginFilter());
registration.addUrlPatterns("/");
return registration;
}
}
2.2 注解注冊
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 在啟動類上增加注解@ServletComponentScan
@SpringBootApplication
@ServletComponentScan
public class FilterTestApplication {
public static void main(String[] args) {
SpringApplication.run(FilterTestApplication.class, args);
}
}
注:
@ServletComponentScan 會掃描所有的帶有@WebFilter的類,并且注冊為servlet。
如果啟動類不添加此注解,在filter上添加Component注解也可以注冊為filter
order注解可以調(diào)整filter的順序
2.3 通過servletContext 注冊
@Autowired ServletContext servletContext; servletContext.addFilter()
3、原理
3.1 ServletContext
Web容器在啟動時(shí)會為每個(gè)web應(yīng)用創(chuàng)建一個(gè)ServletContext對象,而這個(gè)ServletContext對象就代表當(dāng)前這個(gè)web應(yīng)用。
一個(gè)ServletContext對象代表一個(gè)web應(yīng)用,web應(yīng)用中所有的Servlet和其他資源都共享一個(gè)ServletContext對象,
如果有必要我們就可以通過ServletContext對象進(jìn)行Servlet之間的通訊。
ServletContext,是一個(gè)全局的儲存信息的空間,服務(wù)器開始,其就存在,服務(wù)器關(guān)閉,其才釋放。request,一個(gè)用戶可有多個(gè);session,一個(gè)用戶一個(gè);而servletContext,所有用戶共用一個(gè)。

ApplicationContext 是ServletContext的實(shí)現(xiàn)類,可以看到里面有相應(yīng)的注冊的方法
在程序中獲取ServletContext
3.1.1 使用自動注入
@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 手動注冊
4、總結(jié)
filter 作為web服務(wù)器中的重要的一部分,一般常用來做一些前置處理和對調(diào)用請求的中斷
filter的注冊幾種方式總結(jié),在開發(fā)中一般靈活使用,沒有特殊的請求,常規(guī)都夠用
了解原理是為了更好的理解,filter的過濾鏈?zhǔn)絊pring Security的重要切入點(diǎn),理解了filter再理解其他的框架就不難了,甚至可以自己簡單寫出一個(gè)列斯的框架
到此這篇關(guān)于一文詳解Springboot中filter的原理與注冊的文章就介紹到這了,更多相關(guān)Springboot filter內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
BiConsumer接口中的方法andThen?accept使用詳解
這篇文章主要為大家介紹了BiConsumer接口中的方法andThen?accept使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07
基于Eclipse 的JSP/Servlet的開發(fā)環(huán)境的搭建(圖文)
本文將會詳細(xì)地展示如何搭建JSP的開發(fā)環(huán)境。本次教程使用的是最新版的Eclipse 2018-09編輯器和最新版的Apache Tomcat v9.0,步驟詳細(xì),內(nèi)容詳盡,適合零基礎(chǔ)學(xué)者作為學(xué)習(xí)參考2018-12-12
Java使用Queryable-pageable實(shí)現(xiàn)分頁效果
這篇文章主要為大家介紹了Java如何使用Queryable-pageable從而實(shí)現(xiàn)分頁效果,文中的示例代碼簡潔易懂,感興趣的小伙伴可以動手嘗試一下2022-06-06
java實(shí)現(xiàn)微信公眾平臺自定義菜單的創(chuàng)建示例
這篇文章主要介紹了java實(shí)現(xiàn)微信公眾平臺自定義菜單的創(chuàng)建示例,需要的朋友可以參考下2014-04-04
Java的CyclicBarrier循環(huán)屏障解析
這篇文章主要介紹了Java的CyclicBarrier循環(huán)屏障解析,CyclicBarrier和CountDownLatch一樣,是一個(gè)同步工具類,它允許一組線程相互等待直到達(dá)到某個(gè)common?barrier?point,在程序中CyclicBarrier是非常有用的,它適用于一組線程必須互相等待的情況,需要的朋友可以參考下2023-12-12

