文章目录
前言
基于版本2.0.5.RELEASE
springboot使用主启动类启动,DispatcherServlet怎么配置到内置tomcat的?
在主启动类启动时会先生成主启动类的beanDefinition,然后解析主启动类上的注解,其中有EnableAutoConfiguration注解,EnableAutoConfiguration上有@Import注解,解析@Import注解的时候会使用SPI机制将所有spring.factories内的配置类读取,并生成beanDefinition,其中一个配置类DispatcherServletAutoConfiguration将DispatcherServlet注入spring容器,将DispatcherServletRegistrationBean注入spring容器,而DispatcherServletRegistrationBean间接实现了ServletContextInitializer接口,最终会被调用,将DispatcherServlet设置到ServletContext里,并设置loadOnStartup和urlMapping属性
在什么阶段设置的?
spring上下文执行refresh方法内的onRefresh方法的时候
一、ServletWebServerApplicationContext.onfresh
@Override
protected void onRefresh() {
super.onRefresh();
try {
createWebServer();
}
catch (Throwable ex) {
throw new ApplicationContextException("Unable to start web server", ex);
}
}
private void createWebServer() {
WebServer webServer = this.webServer;
ServletContext servletContext = getServletContext();
if (webServer == null && servletContext == null) {
ServletWebServerFactory factory = getWebServerFactory();
// 调用spring容器里所有ServletContextInitializer接口实现类的onStartup方法
// 其中有DispatcherServletAutoConfiguration配置类配置的DispatcherServletRegistrationBean类
// 配置DispatcherServlet到tomcat上下文
this.webServer = factory.getWebServer(getSelfInitializer());
}
else if (servletContext != null) {
try {
getSelfInitializer().onStartup(servletContext);
}
catch (ServletException ex) {
throw new ApplicationContextException("Cannot initialize servlet context", ex);
}
}
initPropertySources();
}
二、RegistrationBean
@Override
public final void onStartup(ServletContext servletContext) throws ServletException {
String description = getDescription();
if (!isEnabled()) {
logger.info(StringUtils.capitalize(description) + " was not registered (disabled)");
return;
}
register(description, servletContext);
}
三、DynamicRegistrationBean
@Override
protected final void register(String description, ServletContext servletContext) {
D registration = addRegistration(description, servletContext);
if (registration == null) {
logger.info(
StringUtils.capitalize(description) + " was not registered " + "(possibly already registered?)");
return;
}
configure(registration);
}
四、ServletRegistrationBean
@Override
protected ServletRegistration.Dynamic addRegistration(String description, ServletContext servletContext) {
String name = getServletName();
return servletContext.addServlet(name, this.servlet);
}
@Override
protected void configure(ServletRegistration.Dynamic registration) {
super.configure(registration);
String[] urlMapping = StringUtils.toStringArray(this.urlMappings);
if (urlMapping.length == 0 && this.alwaysMapUrl) {
urlMapping = DEFAULT_MAPPINGS;
}
// 配置servlet相关的属性(loadonStartup、urlMapping)
if (!ObjectUtils.isEmpty(urlMapping)) {
registration.addMapping(urlMapping);
}
registration.setLoadOnStartup(this.loadOnStartup);
if (this.multipartConfig != null) {
registration.setMultipartConfig(this.multipartConfig);
}
}