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