从源代码层面理解spring boot的默认web容器以及它们之间的关系。
结论本文的源代码基于spring boot2.6.6项目的pom.xml。当spring-boot-starter-web存在时,项目启动时会自动启动一个Tomcat。自动配置类servletwebserverfactor yautoconfiguration查找系统中的所有web容器。我们专注于tomcat。构建TomcatServletWebServerFactory的bean。在SpringBoot的启动过程中,将调用核心刷新方法,并在内部执行onRefresh()方法。onRefresh()方法是一个模板方法,它将执行onRefresh()方法,该方法将执行ServletWebServerApplicationContext子类。OnRefresh()方法调用getWebServer来启动web容器。
spring-boot-starter-web里面有什么?在spring-boot-starter-web的starter中,其实间接引入了spring-boot-starter-tomcat的starter,而这个Spring -Boot-starter -tomcat也引入了tomcat-embed-core dependency,所以只要我们的项目依赖spring-boot-starter-web,就相当于依赖Tomcat。
自动配置类:Spring -boot -auto configuration -2 . 6 . 6 . jar的包中spring.factories文件中的servletwebserverfactoryautoconfiguration,配置了大量的自动配置类,包括自动配置tomcat的自动配置类:servletwebserverfactoryautoconfiguration。
自动配置类的代码如下//full mode @ configuration(proxybean methods = false)//配置类解析顺序@ auto configure order(ordered . highest _ precedent)//注释:表示应该有ServletRequest类(server API)@ conditionalon class(servlet request . class)//项目的应用类型为SpringMVC(启动时获取的SpringBoot应用类型)@ ConditionalOnWebApplication(type = type . servlet)//读取配置文件@ enableConfigurationProperties(server properties . class)//导入具体加载配置类和具体的web实现EmbeddedTomcat.class,ServletWebServerFactoryConfiguration。嵌入式Jetty.class,ServletWebServerFactoryConfiguration。EmbeddedUndertow.class })公共类ServletWebServerFactoryAutoConfiguration {......} servlet request Tomcat -embed -core -9 . 0 . 60 . jar中存在的一个类,所以@ conditional class(servlet request . classes)会得到满足。在spring-boot-starter-web中,间接引入了spring-web、spring-webmvc等依赖项,因此满足@ ConditionalOnWebApplication(type = type . servlet)条件。以上两个条件都满足,那么spring回去解析这个配置类,在解析的过程中会发现他导入了三个类!我们关注嵌入式Tomcat。另外两个的内部条件注释不满足!@ configuration(proxybean methods = false)//Tomcat内部的类中必须有@ conditional class({ servlet . class,tomcat.class,upgradeprorotocol.class})。//如果程序员已经自定义了ServletWebServerFactory的bean,那么这个Bean就不会被加载。@ ConditionalOnMissingBean(value = servletwebserverfactory . class,search = SearchStrategy。CURRENT)静态类embedded Tomcat { @ Bean tomcatservletweb server factory tomcatservletweb server factory(object provider & lt;TomcatConnectorCustomizer & gt连接器定制器,ObjectProvider & ltTomcatContextCustomizer & gtcontextCustomizers,ObjectProvider & ltTomcatProtocolHandlerCustomizer & lt;?& gt& gtprotocolHandlerCustomizers){ TomcatServletWebServerFactory = new TomcatServletWebServerFactory();//调用OrderedStream()时,会转到Spring容器,找到TomcatConnectorCustomizer类型的Bean。默认没有bean,程序员可以自己定义。这个Bean可以设置一些tomcat配置,例如端口、协议...//TomcatConnectorCustomizer:factory。GetToCatConnectorCustomizers()用于配置Tomcat中的连接器组件。。addAll(connector customizers . ordered stream()。collect(collectors . to list());// TomcatContextCustomizer:是工厂。GetToCatContextCustomizers()。AddAll (ContextCustomizers。OrderedStream()。收藏(收藏者。tolist()))用于配置Tomcat中的上下文组件;//TomcatProtocolHandlerCustomizer:是用于配置Tomcat中ProtocolHandler组件的factory . gettomcatprotocolhandlercustomizers()。。addAll(protocolhandlercustomizers . ordered stream()。collect(collectors . to list());返厂;}}}对于另一个EmbeddedJetty和EmbeddedUndertow,逻辑也差不多,就是判断项目依赖关系中是否存在Jetty和Undertow的依赖关系。如果有,在Spring容器中将有一个JettyServletWebServerFactory类型的Bean或一个dowservletwebserverfactory类型的Bean。
tomServletWebServerFactory的作用:获取WebServer对象TomcatServletWebServerFactory。他实现了servletwebserverfactory的接口。ServletWebServerFactory接口内部只有一个方法来获取WebServer对象。
web服务器有启动、停止、获取端口等方法。,而且你会发现WebServer其实指的是Tomcat,Jetty,Undertow。
TomcatServletWebServerFactory用于生成对应的Tomcat WebServer对象,具体来说就是TomcatWebServer对象,生成TomcatWebServer对象时会启动Tomcat。在源代码中,Tomcat将在调用TomcatServletWebServerFactory对象的getWebServer()方法时启动。公共web服务器get web server(ServletContextInitializer...initializer){ if(this . disablebean registry){ registry . disable registry();}//构建tomcat对象Tomcat Tomcat = new Tomcat();//设置相关属性文件basedir = (this.basedir!= null)?this . base directory:create tempdir(" Tomcat ");Tomcat . setbasedir(basedir . getabsolutepath());for (LifecycleListener侦听器:this . serverlifecyclelisteners){ Tomcat . getserver()。addLifecycleListener(监听器);}连接器connector =新连接器(this . protocol);connector . setthrowonfailure(true);tomcat.getService()。addConnector(连接器);customizeConnector(连接器);tomcat.setConnector(连接器);tomcat.getHost()。setAutoDeploy(false);configure engine(Tomcat . getengine());for(Connector additional Connector:this . additional Tomcat connectors){ Tomcat . get service()。add connector(additional connector);} prepareContext(tomcat.getHost()、initializers//Start tomcat,这个方法里面有this . Tomcat . Start();返回getTomcatWebServer(Tomcat);}
SpringBoot启动tomcatSpringBoot的启动过程中,会调用核心刷新方法,内部会执行onRefresh()方法。onRefresh()方法是一个模板方法,它将执行onRefresh()方法,该方法将执行ServletWebServerApplicationContext子类。受保护的void onRefresh() {// template方法,先调用其父类,通常是空方法super . onRefresh();Try {//创建web容器Create web server();} catch(Throwable ex){ throw new ApplicationContextException("无法启动web服务器",ex);}}这个方法会调用createWebServer()方法。
//核心两行代码PrivateVoid Create web Server () {......//获取web容器,错误多或无时报错servletwebserverfactory = getwebserverfactory();//调用这个容器的getWebServer方法,上面的方法启动tomcat!this . web server = factory . get web server(getself initializer());......}getWebServerFactory控件项目组拥有且只能拥有一个web容器!受保护的ServletWebServerFactory getwebserverfactory(){//使用Bean名称,以便我们不考虑层次结构//获取ServletWebServerFactory类型的所有Bean。TomcatServletWebServerFactory,JettyServletWebServerFactory,Undertowservletwebserverfactory都是他得到的子类!string[]bean names = getbean factory()。getBeanNamesForType(servletwebserverfactory . class);//不存在,如果(bean names . length = = 0){ throw new applicationcontextexception("由于缺少servletwebserveapplicationcontext bean,无法启动servletwebserverfactory bean,");}//有多个,请报错!if(bean names . length & gt;1){ throw new ApplicationContextException("由于多个ServletWebServerApplicationContext bean:"+string utils . arraytocommadelimitedstring(bean names)),无法启动ServletWebServerApplicationContext;}//返回唯一的web容器!返回getBeanFactory()。getBean(beanNames[0],servletwebserverfactory . class);}
获取tomcat的配置自动配置类servletwebserverfactor yauto configuration。除了导入三个web容器,BeanPostProcessorsRegistrar也是导入。BeanPostProcessorsRegistrar实现了ImportBeanDefinitionRegistrar,所以他会在spring启动时调用registerBeanDefinitions方法。registerBeanDefinitions将注册一个bean:webserverfactorycustomizerbeanpost处理器。Void RegisterBeandefinitions(导入类数据的批注元数据,Beandefinition注册表){//bean factory,一个Aware回调以赋值if(this . bean factory = = null){ return;}//注册Bean web serverfactorycomizer Bean后处理器。registerSyntheticBeanIfMissing(注册表," web serverfactorycustomizerbeanpostprocessor ",web serverfactorycustomizerbeanpostprocessor . class,web serverfactorycustomizerbeanpostprocessor::new);//Register error page Registry BeanPostProcessor registersyntheticbeanfmissing(Registry," error page Registry BeanPostProcessor ",ErrorPageRegistrarBeanPostProcessor . class,ErrorPageRegistrarBeanPostProcessor::new);} web serverfactorycustomizerBeanPostProcessor实现了beanpostprocessor,所以他会在启动时调用postprocessbeforeininitial ization方法。private void postprocessbefore initial ization(web ServerFactory web server factory){//web Serverfactory customizer,server factory的Find bean lambda safe . callbacks(web serverfactorycustomizer . class,get customizers())//类。使用记录器(web serverfactorycustomizerbeanpost处理器。class)//调用customize方法并将其传入web server factory . invoke((customizer)->;customizer . customize(web server factory));} WebServerFactoryCustomizer类的customize方法会在postprocessbeforeininitial ization中调用,系统中唯一的实现就是servletwebserverfactorycustomizer的customize方法。Customize将配置中的内容设置为可配置的ServletWebServerFactory对象。他的实现TomcatServletWebServerFactory将在启动时具有价值!@ override public void customize(configurableservletwebserver factory){ property mapper map = property mapper . get()。alwaysApplyingWhenNonNull();map . from(this . server properties::get port)。to(factory::set port);map . from(this . server properties::get address)。to(factory::set address);map . from(this . server properties . get servlet()::get context path)。to(factory::setContextPath);map . from(this . server properties . get servlet()::getApplicationDisplayName)。to(factory::set display name);map . from(this . server properties . get servlet()::isRegisterDefaultServlet)。to(factory::setRegisterDefaultServlet);map . from(this . server properties . get servlet()::getSession)。to(factory::setSession);map . from(this . server properties::get SSL)。to(factory::setSsl);map . from(this . server properties . get servlet()::get JSP)。to(factory::set JSP);map . from(this . server properties::get compression)。to(factory::set compression);map . from(this . server properties::get http 2)。to(factory::sethttp 2);map . from(this . server properties::getserver header)。to(factory::setserver header);map . from(this . server properties . get servlet()::get context parameters)。to(factory::setInitParameters);map . from(this . server properties . get shut down())。to(factory::set shut down);for(weblistener registrar registrar:this . weblistener registrars){ registrar . register(factory);}如果(!collection utils . isempty(this . cookiesamesitesuppliers)){ factory . setcookiesamesitesuppliers(this . cookiesamesitesuppliers);}}
servletwebserverfactorycustomizer此Bean在哪里?它是在我们的自动配置类ServletWebServerActorYautoConfiguration中定义的。@ bean public ServletWebServerFactoryCustomizer ServletWebServerFactoryCustomizer(server properties server properties,ObjectProvider & ltWebListenerRegistrar & gtwebListenerRegistrars,ObjectProvider & ltCookieSameSiteSupplier & gtcookieSameSiteSuppliers){ return new ServletWebServerFactoryCustomizer(server properties,weblistenerregistrars . ordered stream()。collect(Collectors.toList()),cookiesamesitesuppliers . ordered stream()。collect(collectors . to list());}就是这样。本文介绍了tomcat与Spring boot集成的基本原理。关于tomcat与Spring boot集成的更多信息,请搜索主机频道zhujipindao之前的文章。或者继续浏览下面的相关文章。希望大家支持主机频道zhujipindao。以后多来com!
评论前必须登录!
注册