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

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

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

瀏覽:94日期: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容器工廠(chǎng)創(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容器工廠(chǎng),定制Web容器通用參數(shù):

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

通過(guò)特定Web容器工廠(chǎng)進(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)文章:
主站蜘蛛池模板: 广东青藤环境科技有限公司-水质检测 | b2b网站大全,b2b网站排名,找b2b网站就上地球网 | 阳光模拟试验箱_高低温试验箱_高低温冲击试验箱_快速温变试验箱|东莞市赛思检测设备有限公司 | 彭世修脚_修脚加盟_彭世修脚加盟_彭世足疗加盟_足疗加盟连锁_彭世修脚技术培训_彭世足疗 | 有源电力滤波装置-电力有源滤波器-低压穿排电流互感器|安科瑞 | 汽车整车综合环境舱_军标砂尘_盐雾试验室试验箱-无锡苏南试验设备有限公司 | DNA亲子鉴定_DNA基因检测中心官方预约平台-严选好基因网 | 土壤养分检测仪|土壤水分|土壤紧实度测定仪|土壤墒情监测系统-土壤仪器网 | 南京雕塑制作厂家-不锈钢雕塑制作-玻璃钢雕塑制作-先登雕塑厂 | OpenI 启智 新一代人工智能开源开放平台 | 运动木地板厂家,篮球场木地板品牌,体育场馆木地板安装 - 欧氏运动地板 | 北京普辉律师事务所官网_北京律师24小时免费咨询|法律咨询 | 隧道风机_DWEX边墙风机_SDS射流风机-绍兴市上虞科瑞风机有限公司 | 水厂污泥地磅|污泥处理地磅厂家|地磅无人值守称重系统升级改造|地磅自动称重系统维修-河南成辉电子科技有限公司 | 济南侦探调查-济南调查取证-山东私家侦探-山东白豹调查咨询公司 密集架|电动密集架|移动密集架|黑龙江档案密集架-大量现货厂家销售 | 江苏远邦专注皮带秤,高精度皮带秤,电子皮带秤研发生产 | 重庆中专|职高|技校招生-重庆中专招生网| 注塑机-压铸机-塑料注塑机-卧式注塑机-高速注塑机-单缸注塑机厂家-广东联升精密智能装备科技有限公司 | 仿真茅草_人造茅草瓦价格_仿真茅草厂家_仿真茅草供应-深圳市科佰工贸有限公司 | YAGEO国巨电容|贴片电阻|电容价格|三星代理商-深圳市巨优电子有限公司 | China plate rolling machine manufacturer,cone rolling machine-Saint Fighter | 翰香原枣子坊加盟费多少钱-正宗枣核糕配方培训利润高飘香 | 最新电影-好看的电视剧大全-朝夕电影网 | 宝元数控系统|对刀仪厂家|东莞机器人控制系统|东莞安川伺服-【鑫天驰智能科技】 | 冷藏车厂家|冷藏车价格|小型冷藏车|散装饲料车厂家|程力专用汽车股份有限公司销售十二分公司 | 物联网卡_物联网卡购买平台_移动物联网卡办理_移动联通电信流量卡通信模组采购平台? | 医学动画公司-制作3d医学动画视频-医疗医学演示动画制作-医学三维动画制作公司 | SDI车窗夹力测试仪-KEMKRAFT方向盘测试仪-上海爱泽工业设备有限公司 | 锤式粉碎机,医药粉碎机,锥式粉碎机-无锡市迪麦森机械制造有限公司 | 对照品_中药对照品_标准品_对照药材_「格利普」高纯中药标准品厂家-成都格利普生物科技有限公司 澳门精准正版免费大全,2025新澳门全年免费,新澳天天开奖免费资料大全最新,新澳2025今晚开奖资料,新澳马今天最快最新图库 | 天津电机维修|水泵维修-天津晟佳机电设备有限公司 | 柔软云母板-硬质-水位计云母片组件-首页-武汉长丰云母绝缘材料有限公司 | 水轮机密封网 | 水轮机密封产品研发生产厂家| 安驭邦官网-双向万能直角铣头,加工中心侧铣头,角度头[厂家直销] 闸阀_截止阀_止回阀「生产厂家」-上海卡比阀门有限公司 | 密度电子天平-内校-外校电子天平-沈阳龙腾电子有限公司 | 食品质构分析仪-氧化诱导分析仪-瞬态法导热系数仪|热冰百科 | 耐高温风管_耐高温软管_食品级软管_吸尘管_钢丝软管_卫生级软管_塑料波纹管-东莞市鑫翔宇软管有限公司 | 飞利浦LED体育场灯具-吸顶式油站灯-飞利浦LED罩棚灯-佛山嘉耀照明有限公司 | 山东商品混凝土搅拌楼-环保型搅拌站-拌合站-分体仓-搅拌机厂家-天宇 | 阀门智能定位器_电液动执行器_气动执行机构-赫尔法流体技术(北京)有限公司 | 包装盒厂家_纸盒印刷_礼品盒定制-济南恒印包装有限公司 |