ServletContextInitializer添加 servlet filter listener
https://www.cnblogs.com/pomer-huang/p/9639322.html
springboot 2.1.3.RELEASE添加filter,servlet源码学习
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
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