SpringBoot中DispatchSevlet是如何放入内置Tomcat中的

SpringBoot的启动不同于外置Tomcat通过SpringServletContainerInitializer的方式,它使用TomcatStarter并在ServletWebServerApplicationContext中利用lambda表达式和匿名内部类进行Servlet、Filter的注册。

外置Tomcat时,在Tomcat启动时会去找spring-web中META-INF/service/javax.servlet.ServletContainerInitializer中配置的SpringServletContainerInitializer,然后运行其中的onStartup()方法;这是Servlet3开始支持的一种方式。

而SpringBoot是由SpringApplication的run方法作为入口,不会像上面那样去找配置。而是创建了一个类TomcatStarter

class TomcatStarter implements ServletContainerInitializer

所以Tomcat启动时会调用TomcatStarter的onStartup()方法

@Override
public void onStartup(Set<Class<?>> classes, ServletContext servletContext)
			throws ServletException {
		try {
			for (ServletContextInitializer initializer : this.initializers) {
				initializer.onStartup(servletContext);
			}
		}
	}

而initializer 在前面已经初始化了,比较难理解的是这里利用了lambda表达式以及匿名内部类,在ServletWebServerApplicationContext中

private void createWebServer() {
		WebServer webServer = this.webServer;
		ServletContext servletContext = getServletContext();
		if (webServer == null && servletContext == null) {
			ServletWebServerFactory factory = getWebServerFactory();
			//这里调用下面的方法getSelfInitializer()返回一个ServletContextInitializer实例
			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();
	}
private org.springframework.boot.web.servlet.ServletContextInitializer getSelfInitializer() {
		return this::selfInitialize;
	}
	
private void selfInitialize(ServletContext servletContext) throws ServletException {
		prepareWebApplicationContext(servletContext);
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
		ExistingWebApplicationScopes existingScopes = new ExistingWebApplicationScopes(
				beanFactory);
		WebApplicationContextUtils.registerWebApplicationScopes(beanFactory,
				getServletContext());
		existingScopes.restore();
		WebApplicationContextUtils.registerEnvironmentBeans(beanFactory,
				getServletContext());
		for (ServletContextInitializer beans : getServletContextInitializerBeans()) {
			beans.onStartup(servletContext);
		}
	}

以上代码相当于下面的代码

 private org.springframework.boot.web.servlet.ServletContextInitializer getSelfInitializer() {
     return (servletContext) -> {
        prepareWebApplicationContext(servletContext);
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
		ExistingWebApplicationScopes existingScopes = new ExistingWebApplicationScopes(
				beanFactory);
		WebApplicationContextUtils.registerWebApplicationScopes(beanFactory,
				getServletContext());
		existingScopes.restore();
		WebApplicationContextUtils.registerEnvironmentBeans(beanFactory,
				getServletContext());
		for (ServletContextInitializer beans : getServletContextInitializerBeans()) {
			beans.onStartup(servletContext);
		}
    }

通过这里就知道Spring Boot中Servlet,Filter是如何注册到容器中的ServletContext了

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值