ServletContextInitializer add servlet filter listener springboot 2.1.3.RELEASE add a filter, servlet source code learning

ServletContextInitializer添加 servlet filter listener 

https://www.cnblogs.com/pomer-huang/p/9639322.html

 

 

springboot 2.1.3.RELEASE add filter, servlet source code learning

 

Servlet specification, to register Filter, Servlet by ServeltContext, Filter analysis here, the same logic Servlet

springboot2.0, we pass

FilterRegistrationBean will have to specify the filter to achieve ServeltContext registered filter

1
2
3
4
5
6
7
8
9
10
11
12
13
FilterRegistrationBean的实例化过程
 
public  FilterRegistrationBean(T filter, ServletRegistrationBean... servletRegistrationBeans) {
         super (servletRegistrationBeans);
         Assert.notNull(filter,  "Filter must not be null" );
         this .filter = filter;
}
 
super 的实例化
AbstractFilterRegistrationBean(ServletRegistrationBean... servletRegistrationBeans) {
         Assert.notNull(servletRegistrationBeans,  "ServletRegistrationBeans must not be null" );
         Collections.addAll( this .servletRegistrationBeans, servletRegistrationBeans);
}

Examples have found FilterRegistrationBean Filter process is to be saved to servletRegistrationBeans (a set) of

Reanalysis FilterRegistrationBean class

FilterRegistrationBean parent is a ServletContextInitializer, he has a method onStartup (ServletContext servletContext)
The result will eventually call
servletContext.addFilter(this.getOrDeduceName(filter), filter)
Now look at the call of local ServletContextInitializer.onStartup
1
2
3
4
5
6
7
8
9
10
11
12
springboot启动
new  SpringApplication(XXApplication. class ).run(XXApplication. class ,args)
调用
refreshContext(context); -> refresh(context); -> ((AbstractApplicationContext) applicationContext).refresh();
-> ServletWebServerApplicationContext.onRefresh(); -> createWebServer();
 
WebServer webServer =  this .webServer;
ServletContext servletContext = getServletContext();
if  (webServer ==  null  && servletContext ==  null ) {
     ServletWebServerFactory factory = getWebServerFactory();
     this .webServer = factory.getWebServer(getSelfInitializer());
}

Reanalysis getSelfInitializer method

1
2
3
4
prepareWebApplicationContext(servletContext);
         registerApplicationScope(servletContext);
         WebApplicationContextUtils.registerEnvironmentBeans(getBeanFactory(),servletContext);
         for  (ServletContextInitializer beans :getServletContextInitializerBeans()) {              
       //调用ServletContextInitializer的onStartup方法
1
beans.onStartup(servletContext); }
-> getServletContextInitializerBeans()
1
2
->  new  ServletContextInitializerBeans(getBeanFactory())
-> addAdaptableBeans(beanFactory)

 

1
2
3
4
5
6
7
8
addAdaptableBeans(ListableBeanFactory beanFactory) 代码如下:
MultipartConfigElement multipartConfig = getMultipartConfig(beanFactory);
//将servlet类的bean包装为ServletRegistrationBean
addAsRegistrationBean(beanFactory, Servlet. class , new  ServletRegistrationBeanAdapter(multipartConfig));
//将Filter的bean包装为FilterRegistrationBean
addAsRegistrationBean(beanFactory, Filter. class , new  FilterRegistrationBeanAdapter());
for  (Class<?> listenerType : ServletListenerRegistrationBean.getSupportedTypes())
{         
addAsRegistrationBean(beanFactory, EventListener. class ,(Class<EventListener>) listenerType, new  ServletListenerRegistrationBeanAdapter());
}

 Here the way, if the called DispatcherServlet Servlet bean instance, and the instance Seen set (Seen set is customized configuration example, the source can be viewed by ServletContextInitializerBeans.addServletContextInitializerBean inlet), the default value is set /

1
2
3
4
5
6
7
String url = (totalNumberOfSourceBeans !=  1 ) ?  "/"  + name +  "/"  "/" ;
if  (name.equals(DISPATCHER_SERVLET_NAME)) {
     url =  "/" // always map the main dispatcherServlet to "/"
}
ServletRegistrationBean<Servlet> bean =  new  ServletRegistrationBean<>(source,url); 
bean.setName(name);
bean.setMultipartConfig( this .multipartConfig);
return  bean;

 

Summary: When springboot start, will all FilterRegistrationBean, ServletRegistrationBean and a spring Servlet and Filter managed instance, by registering ServletContext Servlet and Filter

Servlet规范中,通过ServeltContext来注册Filter、Servlet,这里分析Filter,Servlet是相同逻辑

springboot2.0中,我们通过

FilterRegistrationBean将指定得filter来实现ServeltContext注册filter

1
2
3
4
5
6
7
8
9
10
11
12
13
FilterRegistrationBean的实例化过程
 
public  FilterRegistrationBean(T filter, ServletRegistrationBean... servletRegistrationBeans) {
         super (servletRegistrationBeans);
         Assert.notNull(filter,  "Filter must not be null" );
         this .filter = filter;
}
 
super 的实例化
AbstractFilterRegistrationBean(ServletRegistrationBean... servletRegistrationBeans) {
         Assert.notNull(servletRegistrationBeans,  "ServletRegistrationBeans must not be null" );
         Collections.addAll( this .servletRegistrationBeans, servletRegistrationBeans);
}

可知FilterRegistrationBean得实例化过程就是将Filter保存到servletRegistrationBeans(一个set)中

再分析FilterRegistrationBean类

FilterRegistrationBean的父类是一个ServletContextInitializer,他有一个方法onStartup(ServletContext servletContext)
其结果最终会调用
servletContext.addFilter(this.getOrDeduceName(filter), filter)
现在看看ServletContextInitializer.onStartup的调用地方
1
2
3
4
5
6
7
8
9
10
11
12
springboot启动
new  SpringApplication(XXApplication. class ).run(XXApplication. class ,args)
调用
refreshContext(context); -> refresh(context); -> ((AbstractApplicationContext) applicationContext).refresh();
-> ServletWebServerApplicationContext.onRefresh(); -> createWebServer();
 
WebServer webServer =  this .webServer;
ServletContext servletContext = getServletContext();
if  (webServer ==  null  && servletContext ==  null ) {
     ServletWebServerFactory factory = getWebServerFactory();
     this .webServer = factory.getWebServer(getSelfInitializer());
}

再分析getSelfInitializer方法

1
2
3
4
prepareWebApplicationContext(servletContext);
         registerApplicationScope(servletContext);
         WebApplicationContextUtils.registerEnvironmentBeans(getBeanFactory(),servletContext);
         for  (ServletContextInitializer beans :getServletContextInitializerBeans()) {              
       //调用ServletContextInitializer的onStartup方法
1
beans.onStartup(servletContext); }
-> getServletContextInitializerBeans()
1
2
->  new  ServletContextInitializerBeans(getBeanFactory())
-> addAdaptableBeans(beanFactory)

 

1
2
3
4
5
6
7
8
addAdaptableBeans(ListableBeanFactory beanFactory) 代码如下:
MultipartConfigElement multipartConfig = getMultipartConfig(beanFactory);
//将servlet类的bean包装为ServletRegistrationBean
addAsRegistrationBean(beanFactory, Servlet. class , new  ServletRegistrationBeanAdapter(multipartConfig));
//将Filter的bean包装为FilterRegistrationBean
addAsRegistrationBean(beanFactory, Filter. class , new  FilterRegistrationBeanAdapter());
for  (Class<?> listenerType : ServletListenerRegistrationBean.getSupportedTypes())
{         
addAsRegistrationBean(beanFactory, EventListener. class ,(Class<EventListener>) listenerType, new  ServletListenerRegistrationBeanAdapter());
}

 这里提一下,如果Servlet的bean实例名为dispatcherServlet,且该实例在seen集合中(seen集合为自定义配置的实例,通过ServletContextInitializerBeans.addServletContextInitializerBean入口可以查看源码),则设置默认值为  /

1
2
3
4
5
6
7
String url = (totalNumberOfSourceBeans !=  1 ) ?  "/"  + name +  "/"  "/" ;
if  (name.equals(DISPATCHER_SERVLET_NAME)) {
     url =  "/" // always map the main dispatcherServlet to "/"
}
ServletRegistrationBean<Servlet> bean =  new  ServletRegistrationBean<>(source,url); 
bean.setName(name);
bean.setMultipartConfig( this .multipartConfig);
return  bean;

 

总结:springboot启动时,会将所有的 FilterRegistrationBean、ServletRegistrationBean以及被spring管理的Servlet和Filter的实例,通过          ServletContext注册Servlet以及Filter

Guess you like

Origin www.cnblogs.com/kelelipeng/p/11494005.html