springboot中如何嵌入servlet容器以及容器启动过程

  最近在学习springboot,抽空记录一下,加强记忆。

springboot兼容Tomcat,jetty,undertow容器,默认兼容Tomcat容器,因为spring-boot-starter-web包含tomcat,因此需要使用的时候,需要先把tomcat排除,再引入其他容器,如下:


	org.springframework.boot
	spring-boot-starter-web
	
		
			spring-boot-starter-tomcat
			org.springframework.boot
		
	


	spring-boot-starter-jetty
	org.springframework.boot

 现在分成2部分,容器注入方式和容器使用

  1. ServletWebServerFactoryConfiguration是配置类,里面的@Bean会被自动注入到spring容器中,通过@ConditionalOnClass来判断应该注入哪个servlet容器
    @Configuration(proxyBeanMethods = false)
    @ConditionalOnClass({ Servlet.class, Tomcat.class, UpgradeProtocol.class })//如果系统中存在tomcat相关类,引入tomcat内嵌servlet容器
    @ConditionalOnMissingBean(value = ServletWebServerFactory.class, search = SearchStrategy.CURRENT)
    static class EmbeddedTomcat {
    //自动注入TomcatServletWebServerFactory
    @Bean
    TomcatServletWebServerFactory tomcatServletWebServerFactory(ObjectProvider connectorCustomizers,ObjectProvider contextCustomizers,
    		ObjectProvider> protocolHandlerCustomizers) {
    	TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
    	factory.getTomcatConnectorCustomizers().addAll(connectorCustomizers.orderedStream().collect(Collectors.toList()));
    	factory.getTomcatContextCustomizers().addAll(contextCustomizers.orderedStream().collect(Collectors.toList()));
    	factory.getTomcatProtocolHandlerCustomizers().addAll(protocolHandlerCustomizers.orderedStream().collect(Collectors.toList()));
    	return factory;
    }
    
    
    @Configuration(proxyBeanMethods = false)
    @ConditionalOnClass({ Servlet.class, Server.class, Loader.class, WebAppContext.class })//如果系统中存在Jetty相关类,引入Jetty内嵌servlet容器
    @ConditionalOnMissingBean(value = ServletWebServerFactory.class, search = SearchStrategy.CURRENT)
    static class EmbeddedJetty {

    2.springBoot启动时通过SpringApplication.run方法,最终调用onRefresh()方法,取得TomcatServletWebServerFactory,启动容器

    @Override
    protected void onRefresh() {
    	super.onRefresh();
    	try {
    		createWebServer();//创建servlet容器
    	}
    	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();
    		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();
    }
    
    protected ServletWebServerFactory getWebServerFactory() {
    	// Use bean names so that we don't consider the hierarchy
    	//ServletWebServerFactory.class的实现类正是:TomcatServletWebServerFactory,JettyServletWebServerFactory,UndertowServletWebServerFactory
    	String[] beanNames = getBeanFactory().getBeanNamesForType(ServletWebServerFactory.class);
    	if (beanNames.length == 0) {
    		throw new ApplicationContextException("Unable to start ServletWebServerApplicationContext due to missing "
    				+ "ServletWebServerFactory bean.");
    	}
    	if (beanNames.length > 1) {
    		throw new ApplicationContextException("Unable to start ServletWebServerApplicationContext due to multiple "
    				+ "ServletWebServerFactory beans : " + StringUtils.arrayToCommaDelimitedString(beanNames));
    	}
    	return getBeanFactory().getBean(beanNames[0], ServletWebServerFactory.class);
    }

     

你可能感兴趣的:(java,springboot)