电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

SpringBoot啟動(dòng)嵌入式Tomcat的實(shí)現(xiàn)步驟

瀏覽:96日期:2023-02-20 08:35:21
目錄Spring Boot中Web容器相關(guān)接口WebServerServletWebServerFactoryWebServerFactoryCustomizerBeanPostProcessor創(chuàng)建、啟動(dòng)嵌入式Web容器createWebServergetWebServer注冊(cè)ServletServlet注解ServletRegistrationBean動(dòng)態(tài)注冊(cè)定制Web容器ConfigurableServletWebServerFactoryTomcatServletWebServerFactory

Spring Boot在內(nèi)部啟動(dòng)了一個(gè)嵌入式Web容器。Tomcat是組件化設(shè)計(jì),所以就是啟動(dòng)這些組件。

Tomcat獨(dú)立部署模式是通過(guò)startup腳本啟動(dòng),Tomcat中的Bootstrap和Catalina會(huì)負(fù)責(zé)初始化類(lèi)加載器,并解析server.xml和啟動(dòng)這些組件。

內(nèi)嵌模式,Bootstrap和Catalina的工作由Spring Boot代勞,Spring Boot調(diào)用Tomcat API啟動(dòng)這些組件。

Spring Boot中Web容器相關(guān)接口WebServer

為支持各種Web容器,Spring Boot抽象出嵌入式Web容器,定義WebServer接口:

SpringBoot啟動(dòng)嵌入式Tomcat的實(shí)現(xiàn)步驟

Web容器比如Tomcat、Jetty去實(shí)現(xiàn)該接口

SpringBoot啟動(dòng)嵌入式Tomcat的實(shí)現(xiàn)步驟

ServletWebServerFactory

創(chuàng)建Web容器,返回的就是上面提到的WebServer。

public interface ServletWebServerFactory { WebServer getWebServer(ServletContextInitializer... initializers);}

ServletContextInitializer入?yún)⒈硎維ervletContext的初始化器,用于ServletContext中的一些配置:

public interface ServletContextInitializer { void onStartup(ServletContext servletContext) throws ServletException;}

getWebServer會(huì)調(diào)用ServletContextInitializer#onStartup,即若想在Servlet容器啟動(dòng)時(shí)做一些事情,比如注冊(cè)自己的Servlet,可以實(shí)現(xiàn)一個(gè)ServletContextInitializer,在Web容器啟動(dòng)時(shí),Spring Boot會(huì)把所有實(shí)現(xiàn)ServletContextInitializer接口的類(lèi)收集起來(lái),統(tǒng)一調(diào)其onStartup。

WebServerFactoryCustomizerBeanPostProcessor

一個(gè)BeanPostProcessor,為定制化嵌入式Web容器,在postProcessBeforeInitialization過(guò)程中去尋找Spring容器中WebServerFactoryCustomizer類(lèi)型的Bean,并依次調(diào)用WebServerFactoryCustomizer接口的customize方法做一些定制化。

public interface WebServerFactoryCustomizer<T extends WebServerFactory> { void customize(T factory);}創(chuàng)建、啟動(dòng)嵌入式Web容器

Spring的ApplicationContext,其抽象實(shí)現(xiàn)類(lèi)AbstractApplicationContext#refresh

SpringBoot啟動(dòng)嵌入式Tomcat的實(shí)現(xiàn)步驟

用來(lái)新建或刷新一個(gè)ApplicationContext,在refresh中會(huì)調(diào)用onRefresh,AbstractApplicationContext的子類(lèi)可以重寫(xiě)onRefresh實(shí)現(xiàn)Context刷新邏輯。

因此重寫(xiě) ServletWebServerApplicationContext#onRefresh 創(chuàng)建嵌入式Web容器:

SpringBoot啟動(dòng)嵌入式Tomcat的實(shí)現(xiàn)步驟

重寫(xiě)onRefresh方法,調(diào)用createWebServer創(chuàng)建和啟動(dòng)Tomcat。

createWebServer

private void createWebServer() { // WebServer是Spring Boot抽象出來(lái)的接口,具體實(shí)現(xiàn)類(lèi)就是不同Web容器 WebServer webServer = this.webServer; ServletContext servletContext = this.getServletContext();// 若Web容器尚未創(chuàng)建 if (webServer == null && servletContext == null) {// 通過(guò)Web容器工廠創(chuàng)建ServletWebServerFactory factory = this.getWebServerFactory();// 傳入一個(gè)'SelfInitializer'this.webServer = factory.getWebServer(new ServletContextInitializer[]{this.getSelfInitializer()}); } else if (servletContext != null) {try { this.getSelfInitializer().onStartup(servletContext);} catch (ServletException var4) { ...} } this.initPropertySources();}getWebServer

以Tomcat為例,主要調(diào)用Tomcat的API去創(chuàng)建各種組件:

public WebServer getWebServer(ServletContextInitializer... initializers) { // 1.實(shí)例化一個(gè)Tomcat【Server組件】 Tomcat tomcat = new Tomcat();// 2. 創(chuàng)建一個(gè)臨時(shí)目錄 File baseDir = this.baseDirectory != null ? this.baseDirectory : this.createTempDir('tomcat'); tomcat.setBaseDir(baseDir.getAbsolutePath());// 3.初始化各種組件 Connector connector = new Connector(this.protocol); tomcat.getService().addConnector(connector); this.customizeConnector(connector); tomcat.setConnector(connector); tomcat.getHost().setAutoDeploy(false); this.configureEngine(tomcat.getEngine());// 4. 創(chuàng)建定制版的'Context'組件 this.prepareContext(tomcat.getHost(), initializers); return this.getTomcatWebServer(tomcat);}

prepareContext的Context指Tomcat的Context組件,為控制Context組件行為,Spring Boot自定義了TomcatEmbeddedContext類(lèi),繼承Tomcat的StandardContext:

SpringBoot啟動(dòng)嵌入式Tomcat的實(shí)現(xiàn)步驟

注冊(cè)Servlet

有@RestController,為什么還要自己去注冊(cè)Servlet給Tomcat?可能有些場(chǎng)景需要注冊(cè)你自己寫(xiě)的一個(gè)Servlet提供輔助功能,與主程序分開(kāi)。

Sprong Boot 不注冊(cè)Servlet 給Tomcat 直接用 @Controller 就能實(shí)現(xiàn)Servlet功能是為啥呢?因?yàn)镾prong Boot默認(rèn)給我們注冊(cè)了DispatcherSetvlet。

Servlet注解

在Spring Boot啟動(dòng)類(lèi)上加上 @ServletComponentScan 注解后,使用@WebServlet、@WebFilter、@WebListener標(biāo)記的Servlet、Filter、Listener就可以自動(dòng)注冊(cè)到Servlet容器。

SpringBoot啟動(dòng)嵌入式Tomcat的實(shí)現(xiàn)步驟

SpringBoot啟動(dòng)嵌入式Tomcat的實(shí)現(xiàn)步驟

在Web應(yīng)用的入口類(lèi)上加上@ServletComponentScan,并且在Servlet類(lèi)上加上@WebServlet,這樣Spring Boot會(huì)負(fù)責(zé)將Servlet注冊(cè)到內(nèi)嵌的Tomcat中。

ServletRegistrationBean

Spring Boot提供了

ServletRegistrationBean FilterRegistrationBean ServletListenerRegistrationBean

分別用來(lái)注冊(cè)Servlet、Filter、Listener。假如要注冊(cè)一個(gè)Servlet:

SpringBoot啟動(dòng)嵌入式Tomcat的實(shí)現(xiàn)步驟

返回一個(gè)ServletRegistrationBean,并將它當(dāng)作Bean注冊(cè)到Spring,因此你需要把這段代碼放到Spring Boot自動(dòng)掃描的目錄中,或者放到**@Configuration**標(biāo)識(shí)的類(lèi)中。Spring會(huì)把這種類(lèi)型的Bean收集起來(lái),根據(jù)Bean里的定義向Tomcat注冊(cè)Servlet。

動(dòng)態(tài)注冊(cè)

可以創(chuàng)建一個(gè)類(lèi)去實(shí)現(xiàn)ServletContextInitializer接口,并把它注冊(cè)為一個(gè)Bean,Spring Boot會(huì)負(fù)責(zé)調(diào)用這個(gè)接口的onStartup。

實(shí)現(xiàn)ServletContextInitializer接口的類(lèi)會(huì)被spring管理,而不是被Servlet容器管理。

@Componentpublic class MyServletRegister implements ServletContextInitializer { @Override public void onStartup(ServletContext servletContext) { // Servlet 3.0規(guī)范新的APIServletRegistration myServlet = servletContext.addServlet('HelloServlet', HelloServlet.class);myServlet.addMapping('/hello');myServlet.setInitParameter('name', 'Hello Servlet'); }}

ServletRegistrationBean也是通過(guò)ServletContextInitializer實(shí)現(xiàn)的,它實(shí)現(xiàn)了ServletContextInitializer接口。注意到onStartup方法的參數(shù)是我們熟悉的ServletContext,可以通過(guò)調(diào)用它的addServlet方法來(lái)動(dòng)態(tài)注冊(cè)新的Servlet,這是Servlet 3.0以后才有的功能。

通過(guò) ServletContextInitializer 接口可以向 Web 容器注冊(cè) Servlet,實(shí)現(xiàn) ServletContextInitializer 接口的Bean被speing管理,但是在什么時(shí)機(jī)觸發(fā)其onStartup()方法的呢?通過(guò) Tomcat 中的 ServletContainerInitializer 接口實(shí)現(xiàn)者,如TomcatStarter,創(chuàng)建tomcat時(shí)設(shè)置了該類(lèi),在tomcat啟動(dòng)時(shí)會(huì)觸發(fā)ServletContainerInitializer實(shí)現(xiàn)者的onStartup()方法,在這個(gè)方法中觸發(fā)ServletContextInitializer接口的onStartup()方法,如注冊(cè)DispatcherServlet。

DispatcherServletRegistrationBean實(shí)現(xiàn)了ServletContextInitializer接口,它的作用就是向Tomcat注冊(cè)DispatcherServlet,那它是在什么時(shí)候、如何被使用的呢?prepareContext方法調(diào)用了另一個(gè)私有方法configureContext,這個(gè)方法就包括了往Tomcat的Context添加ServletContainerInitializer對(duì)象:

context.addServletContainerInitializer(starter, NO_CLASSES);

其中有DispatcherServletRegistrationBean。

定制Web容器

如何在Spring Boot中定制Web容器。在Spring Boot 2.0中可通過(guò)如下方式:

ConfigurableServletWebServerFactory

通用的Web容器工廠,定制Web容器通用參數(shù):

@Componentpublic class MyGeneralCustomizer implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> { public void customize(ConfigurableServletWebServerFactory factory) {factory.setPort(8081);factory.setContextPath('/hello'); }}TomcatServletWebServerFactory

通過(guò)特定Web容器工廠進(jìn)一步定制。

給Tomcat增加一個(gè)Valve,這個(gè)Valve的功能是向請(qǐng)求頭里添加traceid,用于分布式追蹤。

class TraceValve extends ValveBase { @Override public void invoke(Request request, Response response) throws IOException, ServletException {request.getCoyoteRequest().getMimeHeaders().addValue('traceid').setString('1234xxxxabcd');Valve next = getNext();if (null == next) { return;}next.invoke(request, response); }}

跟方式一類(lèi)似,再添加一個(gè)定制器:

@Componentpublic class MyTomcatCustomizer implementsWebServerFactoryCustomizer<TomcatServletWebServerFactory> { @Override public void customize(TomcatServletWebServerFactory factory) {factory.setPort(8081);factory.setContextPath('/hello');factory.addEngineValves(new TraceValve() ); }}

到此這篇關(guān)于SpringBoot啟動(dòng)嵌入式Tomcat的實(shí)現(xiàn)步驟的文章就介紹到這了,更多相關(guān)SpringBoot啟動(dòng)嵌入式Tomcat內(nèi)容請(qǐng)搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

標(biāo)簽: Spring
相關(guān)文章:
主站蜘蛛池模板: 深圳美安可自动化设备有限公司,喷码机,定制喷码机,二维码喷码机,深圳喷码机,纸箱喷码机,东莞喷码机 UV喷码机,日期喷码机,鸡蛋喷码机,管芯喷码机,管内壁喷码机,喷码机厂家 | 理化生实验室设备,吊装实验室设备,顶装实验室设备,实验室成套设备厂家,校园功能室设备,智慧书法教室方案 - 东莞市惠森教学设备有限公司 | 蜜蜂职场文库_职场求职面试实用的范文资料大全 | 全温恒温摇床-水浴气浴恒温摇床-光照恒温培养摇床-常州金坛精达仪器制造有限公司 | 包装盒厂家_纸盒印刷_礼品盒定制-济南恒印包装有限公司 | 双段式高压鼓风机-雕刻机用真空泵-绍兴天晨机械有限公司 | 【铜排折弯机,钢丝折弯成型机,汽车发泡钢丝折弯机,线材折弯机厂家,线材成型机,铁线折弯机】贝朗折弯机厂家_东莞市贝朗自动化设备有限公司 | CXB船用变压器-JCZ系列制动器-HH101船用铜质开关-上海永上船舶电器厂 | 济南侦探调查-济南调查取证-山东私家侦探-山东白豹调查咨询公司 密集架|电动密集架|移动密集架|黑龙江档案密集架-大量现货厂家销售 | 皮带机-带式输送机价格-固定式胶带机生产厂家-河南坤威机械 | 成人纸尿裤,成人尿不湿,成人护理垫-山东康舜日用品有限公司 | 电伴热系统施工_仪表电伴热保温箱厂家_沃安电伴热管缆工业技术(济南)有限公司 | 齿式联轴器-弹性联轴器-联轴器厂家-江苏诺兴传动联轴器制造有限公司 | 深圳活动策划公司|庆典策划|专业公关活动策划|深圳艺典文化传媒 重庆中专|职高|技校招生-重庆中专招生网 | 深圳公司注册-工商注册公司-千百顺代理记账公司 | SPC工作站-连杆综合检具-表盘气动量仪-内孔缺陷检测仪-杭州朗多检测仪器有限公司 | 垃圾处理设备_餐厨垃圾处理设备_厨余垃圾处理设备_果蔬垃圾处理设备-深圳市三盛环保科技有限公司 | 锂电池砂磨机|石墨烯砂磨机|碳纳米管砂磨机-常州市奥能达机械设备有限公司 | 山东PE给水管厂家,山东双壁波纹管,山东钢带增强波纹管,山东PE穿线管,山东PE农田灌溉管,山东MPP电力保护套管-山东德诺塑业有限公司 | 郑州墨香品牌设计公司|品牌全案VI设计公司 | 快干水泥|桥梁伸缩缝止水胶|伸缩缝装置生产厂家-广东广航交通科技有限公司 | 水厂自动化|污水处理中控系统|水利信息化|智慧水务|智慧农业-山东德艾自动化科技有限公司 | 永嘉县奥阳陶瓷阀门有限公司 | IPO咨询公司-IPO上市服务-细分市场研究-龙马咨询 | 热闷罐-高温罐-钢渣热闷罐-山东鑫泰鑫智能热闷罐厂家 | 东莞市踏板石餐饮管理有限公司_正宗桂林米粉_正宗桂林米粉加盟_桂林米粉加盟费-东莞市棒子桂林米粉 | 浙江美尔凯特智能厨卫股份有限公司| 济南电缆桥架|山东桥架-济南航丰实业有限公司 | 万濠影像仪(万濠投影仪)百科-苏州林泽仪器 | 上海刑事律师|刑事辩护律师|专业刑事犯罪辩护律师免费咨询-[尤辰荣]金牌上海刑事律师团队 | 爆破器材运输车|烟花爆竹运输车|1-9类危险品厢式运输车|湖北江南专用特种汽车有限公司 | 上海宿田自动化设备有限公司-双面/平面/单面贴标机 | 美甲贴片-指甲贴片-穿戴美甲-假指甲厂家--薇丝黛拉 | 新能源汽车电机定转子合装机 - 电机维修设备 - 睿望达 | 水质监测站_水质在线分析仪_水质自动监测系统_多参数水质在线监测仪_水质传感器-山东万象环境科技有限公司 | 电动打包机_气动打包机_钢带捆扎机_废纸打包机_手动捆扎机 | 尾轮组_头轮组_矿用刮板_厢式刮板机_铸石刮板机厂家-双驰机械 | 模型公司_模型制作_沙盘模型报价-中国模型网 | TYPE-C厂家|TYPE-C接口|TYPE-C防水母座|TYPE-C贴片-深圳步步精 | 钢托盘,钢制托盘,立库钢托盘,金属托盘制造商_南京飞天金属制品实业有限公司 | 考勤系统_考勤管理系统_网络考勤软件_政企|集团|工厂复杂考勤工时统计排班管理系统_天时考勤 |