一文詳解Springboot中filter的原理與注冊
1、filter
先看下web服務器的filter所處的位置。filter是一個前后連接的鏈,前面處理完成之后傳遞給下一個filter處理。

1.1 filter的接口定義
public interface Filter {
//初始化方法,整個生命周期中只執(zhí)行一次。
//在init方法成功(失敗如拋異常等)執(zhí)行完前,不能提供過濾服務。
//參數(shù)FilterConfig用于獲取初始化參數(shù)
public void init(FilterConfig filterConfig) throws ServletException;
//執(zhí)行過濾任務的方法,參數(shù)FilterChain表示過濾器鏈,doFilter方法中只有執(zhí)行chain.doFilter()后才能調用下一個過濾器的doFilter方法
//才能將請求交經(jīng)下一個Filter或Servlet執(zhí)行
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException;
//銷毀方法,當移出服務時由web容器調用。整個生命周期中destroy方法只會執(zhí)行一次
//destroy方法可用于釋放持有的資源,如內存、文件句柄等
public void destroy();
}
filter的入?yún)⑹莚equest和response,filter一般是用來做一些預處理工作,比如做一些檢查,驗證等工作。
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注解可以調整filter的順序
2.3 通過servletContext 注冊
@Autowired ServletContext servletContext; servletContext.addFilter()
3、原理
3.1 ServletContext
Web容器在啟動時會為每個web應用創(chuàng)建一個ServletContext對象,而這個ServletContext對象就代表當前這個web應用。
一個ServletContext對象代表一個web應用,web應用中所有的Servlet和其他資源都共享一個ServletContext對象,
如果有必要我們就可以通過ServletContext對象進行Servlet之間的通訊。
ServletContext,是一個全局的儲存信息的空間,服務器開始,其就存在,服務器關閉,其才釋放。request,一個用戶可有多個;session,一個用戶一個;而servletContext,所有用戶共用一個。

ApplicationContext 是ServletContext的實現(xiàn)類,可以看到里面有相應的注冊的方法
在程序中獲取ServletContext
3.1.1 使用自動注入
@Autowired private ServletContext servletContext;
3.1.2 request獲取servletContext
ServletContext servletContext = request.getServletContext();
3.1.3 實現(xiàn) ServletContextListener
@Component
public class TestListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println(sce);
}
}
3.2 ServletRegistrationBean
看下Filter的定義,可以看到和webfilter注解內容一樣
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、總結
filter 作為web服務器中的重要的一部分,一般常用來做一些前置處理和對調用請求的中斷
filter的注冊幾種方式總結,在開發(fā)中一般靈活使用,沒有特殊的請求,常規(guī)都夠用
了解原理是為了更好的理解,filter的過濾鏈式Spring Security的重要切入點,理解了filter再理解其他的框架就不難了,甚至可以自己簡單寫出一個列斯的框架
到此這篇關于一文詳解Springboot中filter的原理與注冊的文章就介紹到這了,更多相關Springboot filter內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

