当前位置: 首页 > news >正文

undertow服务器初始化

springboot整合undertow服务器的源码从老生常谈的createWebServer方法谈起。spring会在生成所有bean后到创建web容器,此时会到容器找到ServletWebServerFactory接口bean,spring会根据引入的框架确定生成的ServletWebServerFactory,我们在maven中引入了undertow后,由UndertowServletWebServerFactory实现。

	private void createWebServer() {WebServer webServer = this.webServer;ServletContext servletContext = getServletContext();if (webServer == null && servletContext == null) {ServletWebServerFactory factory = getWebServerFactory();this.webServer = factory.getWebServer(getSelfInitializer());getBeanFactory().registerSingleton("webServerGracefulShutdown",new WebServerGracefulShutdownLifecycle(this.webServer));getBeanFactory().registerSingleton("webServerStartStop",new WebServerStartStopLifecycle(this, this.webServer));}else if (servletContext != null) {try {getSelfInitializer().onStartup(servletContext);}catch (ServletException ex) {throw new ApplicationContextException("Cannot initialize servlet context", ex);}}initPropertySources();}

UndertowServletWebServerFactory类的getWebServer会创建WebServer。

	public WebServer getWebServer(ServletContextInitializer... initializers) {Builder builder = this.delegate.createBuilder(this);DeploymentManager manager = createManager(initializers);return getUndertowWebServer(builder, manager, getPort());}

先用默认的配置构建Builder对象,再使用读取的配置。

Builder createBuilder(AbstractConfigurableWebServerFactory factory) {Ssl ssl = factory.getSsl();InetAddress address = factory.getAddress();int port = factory.getPort();Builder builder = Undertow.builder();if (this.bufferSize != null) {builder.setBufferSize(this.bufferSize);}if (this.ioThreads != null) {builder.setIoThreads(this.ioThreads);}if (this.workerThreads != null) {builder.setWorkerThreads(this.workerThreads);}if (this.directBuffers != null) {builder.setDirectBuffers(this.directBuffers);}if (ssl != null && ssl.isEnabled()) {new SslBuilderCustomizer(factory.getPort(), address, ssl, factory.getSslStoreProvider()).customize(builder);Http2 http2 = factory.getHttp2();if (http2 != null) {builder.setServerOption(UndertowOptions.ENABLE_HTTP2, http2.isEnabled());}}else {builder.addHttpListener(port, (address != null) ? address.getHostAddress() : "0.0.0.0");}builder.setServerOption(UndertowOptions.SHUTDOWN_TIMEOUT, 0);for (UndertowBuilderCustomizer customizer : this.builderCustomizers) {customizer.customize(builder);}return builder;}

之后再注册Servlet和Filter过滤器到容器中。

    public void deploy() {final DeploymentInfo deploymentInfo = originalDeployment.clone();if (deploymentInfo.getServletStackTraces() == ServletStackTraces.ALL) {UndertowServletLogger.REQUEST_LOGGER.servletStackTracesAll(deploymentInfo.getDeploymentName());}deploymentInfo.validate();final DeploymentImpl deployment = new DeploymentImpl(this, deploymentInfo, servletContainer);this.deployment = deployment;final ServletContextImpl servletContext = new ServletContextImpl(servletContainer, deployment);deployment.setServletContext(servletContext);handleExtensions(deploymentInfo, servletContext);final List<ThreadSetupHandler> setup = new ArrayList<>();setup.add(ServletRequestContextThreadSetupAction.INSTANCE);setup.add(new ContextClassLoaderSetupAction(deploymentInfo.getClassLoader()));setup.addAll(deploymentInfo.getThreadSetupActions());deployment.setThreadSetupActions(setup);deployment.getServletPaths().setWelcomePages(deploymentInfo.getWelcomePages());if (deploymentInfo.getDefaultEncoding() != null) {deployment.setDefaultCharset(Charset.forName(deploymentInfo.getDefaultEncoding()));}if(deploymentInfo.getDefaultRequestEncoding() != null) {deployment.setDefaultRequestCharset(Charset.forName(deploymentInfo.getDefaultRequestEncoding()));} else if (deploymentInfo.getDefaultEncoding() != null) {deployment.setDefaultRequestCharset(Charset.forName(deploymentInfo.getDefaultEncoding()));}if(deploymentInfo.getDefaultResponseEncoding() != null) {deployment.setDefaultResponseCharset(Charset.forName(deploymentInfo.getDefaultResponseEncoding()));} else if (deploymentInfo.getDefaultEncoding() != null) {deployment.setDefaultResponseCharset(Charset.forName(deploymentInfo.getDefaultEncoding()));}handleDeploymentSessionConfig(deploymentInfo, servletContext);deployment.setSessionManager(deploymentInfo.getSessionManagerFactory().createSessionManager(deployment));deployment.getSessionManager().setDefaultSessionTimeout(deploymentInfo.getDefaultSessionTimeout());try {deployment.createThreadSetupAction(new ThreadSetupHandler.Action<Void, Object>() {@Overridepublic Void call(HttpServerExchange exchange, Object ignore) throws Exception {final ApplicationListeners listeners = createListeners();listeners.start();deployment.setApplicationListeners(listeners);//now create the servlets and filters that we know about. We can still get more latercreateServletsAndFilters(deployment, deploymentInfo);//first initialize the temp dirinitializeTempDir(servletContext, deploymentInfo);//then run the SCI'sfor (final ServletContainerInitializerInfo sci : deploymentInfo.getServletContainerInitializers()) {final InstanceHandle<? extends ServletContainerInitializer> instance = sci.getInstanceFactory().createInstance();try {instance.getInstance().onStartup(sci.getHandlesTypes(), servletContext);} finally {instance.release();}}deployment.getSessionManager().registerSessionListener(new SessionListenerBridge(deployment, listeners, servletContext));for(SessionListener listener : deploymentInfo.getSessionListeners()) {deployment.getSessionManager().registerSessionListener(listener);}initializeErrorPages(deployment, deploymentInfo);initializeMimeMappings(deployment, deploymentInfo);listeners.contextInitialized();//runHttpHandler wrappedHandlers = ServletDispatchingHandler.INSTANCE;wrappedHandlers = wrapHandlers(wrappedHandlers, deploymentInfo.getInnerHandlerChainWrappers());wrappedHandlers = new RedirectDirHandler(wrappedHandlers, deployment.getServletPaths());if(!deploymentInfo.isSecurityDisabled()) {HttpHandler securityHandler = setupSecurityHandlers(wrappedHandlers);wrappedHandlers = new PredicateHandler(DispatcherTypePredicate.REQUEST, securityHandler, wrappedHandlers);}HttpHandler outerHandlers = wrapHandlers(wrappedHandlers, deploymentInfo.getOuterHandlerChainWrappers());wrappedHandlers = new PredicateHandler(DispatcherTypePredicate.REQUEST, outerHandlers, wrappedHandlers);wrappedHandlers = handleDevelopmentModePersistentSessions(wrappedHandlers, deploymentInfo, deployment.getSessionManager(), servletContext);MetricsCollector metrics = deploymentInfo.getMetricsCollector();if(metrics != null) {wrappedHandlers = new MetricsChainHandler(wrappedHandlers, metrics, deployment);}if( deploymentInfo.getCrawlerSessionManagerConfig() != null ) {wrappedHandlers = new CrawlerSessionManagerHandler(deploymentInfo.getCrawlerSessionManagerConfig(), wrappedHandlers);}final ServletInitialHandler servletInitialHandler = SecurityActions.createServletInitialHandler(deployment.getServletPaths(), wrappedHandlers, deployment, servletContext);HttpHandler initialHandler = wrapHandlers(servletInitialHandler, deployment.getDeploymentInfo().getInitialHandlerChainWrappers());initialHandler = new HttpContinueReadHandler(initialHandler);if(deploymentInfo.getUrlEncoding() != null) {initialHandler = Handlers.urlDecodingHandler(deploymentInfo.getUrlEncoding(), initialHandler);}deployment.setInitialHandler(initialHandler);deployment.setServletHandler(servletInitialHandler);deployment.getServletPaths().invalidate(); //make sure we have a fresh set of servlet pathsservletContext.initDone();return null;}}).call(null, null);} catch (Exception e) {throw new RuntimeException(e);}//any problems with the paths won't get detected until the data is initialize//so we force initialization heredeployment.getServletPaths().initData();for(ServletContextListener listener : deploymentInfo.getDeploymentCompleteListeners()) {listener.contextInitialized(new ServletContextEvent(servletContext));}state = State.DEPLOYED;}

WebServer接口的start()方法就会启动undertow服务器了,本质就是通过XNIO框架监听服务器端口号,接收请求并处理。处理请求时的io线程模型分数据处理线程和业务处理线程。

    public synchronized void start() {UndertowLogger.ROOT_LOGGER.infof("starting server: %s", Version.getFullVersionString());xnio = Xnio.getInstance(Undertow.class.getClassLoader());channels = new ArrayList<>();try {if (internalWorker) {worker = xnio.createWorker(OptionMap.builder().set(Options.WORKER_IO_THREADS, ioThreads).set(Options.CONNECTION_HIGH_WATER, 1000000).set(Options.CONNECTION_LOW_WATER, 1000000).set(Options.WORKER_TASK_CORE_THREADS, workerThreads).set(Options.WORKER_TASK_MAX_THREADS, workerThreads).set(Options.TCP_NODELAY, true).set(Options.CORK, true).addAll(workerOptions).getMap());}OptionMap socketOptions = OptionMap.builder().set(Options.WORKER_IO_THREADS, worker.getIoThreadCount()).set(Options.TCP_NODELAY, true).set(Options.REUSE_ADDRESSES, true).set(Options.BALANCING_TOKENS, 1).set(Options.BALANCING_CONNECTIONS, 2).set(Options.BACKLOG, 1000).addAll(this.socketOptions).getMap();OptionMap serverOptions = OptionMap.builder().set(UndertowOptions.NO_REQUEST_TIMEOUT, 60 * 1000).addAll(this.serverOptions).getMap();ByteBufferPool buffers = this.byteBufferPool;if (buffers == null) {buffers = new DefaultByteBufferPool(directBuffers, bufferSize, -1, 4);}listenerInfo = new ArrayList<>();for (ListenerConfig listener : listeners) {UndertowLogger.ROOT_LOGGER.debugf("Configuring listener with protocol %s for interface %s and port %s", listener.type, listener.host, listener.port);final HttpHandler rootHandler = listener.rootHandler != null ? listener.rootHandler : this.rootHandler;OptionMap socketOptionsWithOverrides = OptionMap.builder().addAll(socketOptions).addAll(listener.overrideSocketOptions).getMap();......if (listener.type == ListenerType.HTTP) {HttpOpenListener openListener = new HttpOpenListener(buffers, undertowOptions);HttpHandler handler = rootHandler;if (http2) {handler = new Http2UpgradeHandler(handler);}openListener.setRootHandler(handler);final ChannelListener<StreamConnection> finalListener;if (listener.useProxyProtocol) {finalListener = new ProxyProtocolOpenListener(openListener, null, buffers, OptionMap.EMPTY);} else {finalListener = openListener;}ChannelListener<AcceptingChannel<StreamConnection>> acceptListener = ChannelListeners.openListenerAdapter(finalListener);AcceptingChannel<? extends StreamConnection> server = worker.createStreamConnectionServer(new InetSocketAddress(Inet4Address.getByName(listener.host), listener.port), acceptListener, socketOptionsWithOverrides);server.resumeAccepts();channels.add(server);listenerInfo.add(new ListenerInfo("http", server.getLocalAddress(), openListener, null, server));} ......}

相关文章:

undertow服务器初始化

springboot整合undertow服务器的源码从老生常谈的createWebServer方法谈起。spring会在生成所有bean后到创建web容器&#xff0c;此时会到容器找到ServletWebServerFactory接口bean&#xff0c;spring会根据引入的框架确定生成的ServletWebServerFactory&#xff0c;我们在mave…...

LeetCode9:回文数

原题地址&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 题目描述&#xff1a; 给你一个整数 x &#xff0c;如果 x 是一个回文整数&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 回文数 是指正序&#xff08;从左向右&#xff09;和倒序&#xff…...

模板语法(2)

一、循环 在模板中可以用v-for指令来循环数组&#xff0c;对象等。 1. 循环数组 <script setup name"App">import { reactive } from "vue"const books reactive([{title: 三国演义,author: 罗贯中}, {title: 水浒传,author: 施耐庵}, {title: 西…...

从头学PHP之数组输出基本函数

上期我们讲到了数组&#xff0c;数组是个特殊的变量&#xff0c;在程序中的重要程度很高&#xff0c;大部分数据处理的时候会用到这种特殊的变量&#xff0c;那么现在让我们继续深入一下吧。 上期我们打印出了数组的值&#xff0c;用print_r()或者var_dump()这俩函数&#xff0…...

基于SSM+小程序的4S店客户管理系统(汽车2)

&#x1f449;文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1、项目介绍 4S店客户管理系统主要包括管理员、用户、门店三个权限角色 1、管理员实现了首页、个人中心、用户管理、门店管理、车展管理、汽车品牌管理、新闻头条管理、预约试驾管理、我的收藏管理、…...

ZYNQ AXI_Timer 中断

REVIEW 关于ZYNQ中断&#xff1a; ZYNQ PS_GPIO中断-CSDN博客 ZYNQ AXI_GPIO_INT-CSDN博客 ZYNQ 定时器中断-CSDN博客 在一些应用场景中&#xff0c;可能需要使用到多个定时器&#xff0c;除了选择使用 PS 侧其他定时器外&#xff0c;也可以使用 PL 侧逻辑定时器。 1. 今日摸鱼…...

UE5之5.4 第一人称示例代码阅读2 子弹发射逻辑

TP_WeaponComponent.h 看看头文件 暴露了attach weapon和fire给蓝图 这两个函数意义一看名字吧&#xff0c;就是捡起来枪的时候执行&#xff0c;一个就是发射子弹的时候执行 #pragma once#include "CoreMinimal.h" #include "Components/SkeletalMeshComponen…...

Python 实现日期计算与日历格式化输出(万年历)

目录 一、引言 二、需求分析 三、实现思路 四、代码实现 五、代码分析 六、测试与验证 七、总结与展望 在日常的编程中&#xff0c;我们经常会遇到与日期相关的问题&#xff0c;比如计算两个日期之间的天数差、确定某个特定日期是星期几以及格式化输出日历等。本文将详细…...

10.28.2024刷华为OD C题型

文章目录 HJ9HJ10HJ11HJ13HJ17 HJ9 HJ10 HJ11 HJ13 HJ17...

映射问题的解决办法(mybaitis)

最初我用的是注解来操控数据库&#xff08;注释掉的部分&#xff09; Mapper public interface ThreadMapper {// Select("SELECT * FROM thread LIMIT #{page}, #{size}")List<Thread> getListByPage(Param("page") int page, Param("size&qu…...

关于机器学习方向学习的一些建议(过来人)

以下是关于机器学习方向学习的一些建议&#xff1a; 一、扎实的数学基础 线性代数 线性代数是机器学习的基石。矩阵运算在数据表示、模型参数计算等方面无处不在。例如&#xff0c;在多元线性回归中&#xff0c;我们用矩阵来表示自变量和因变量之间的关系。像最小二乘法求解回…...

【云原生】云原生后端:网络架构详解

目录 引言一、微服务间的通信1.1 通信方式概览1.2 HTTP/REST1.3 gRPC1.4 消息队列1.5 GraphQL 二、API网关2.1 API网关架构示例2.2 API网关实现示例 三、服务发现3.1 服务发现实现示例3.2 服务发现的优势 四、网络安全4.1 网络安全最佳实践4.2 网络安全架构示例 总结参考资料 引…...

期货资管子系统框架设计JS路径及源代码分享

期货资管子系统框架设计JS路径及源代码分享 随着期货资管子系统前端技术的飞速发展&#xff0c;JavaScript&#xff08;JS&#xff09;及其相关框架已成为构建这类系统的重要工具。本文将详细介绍一个期货资管子系统框架的设计思路&#xff0c;并分享部分JS路径及源代码&#…...

【YOLO 系列】基于YOLO的工业自动化轴承缺陷检测系统【python源码+Pyqt5界面+数据集+训练代码】

前言 轴承作为机械设备中的关键部件&#xff0c;其性能直接影响到设备的稳定性和寿命。轴承缺陷的早期检测对于预防设备故障、减少维护成本和提高生产效率至关重要。然而&#xff0c;传统的轴承缺陷检测方法往往依赖于人工检查&#xff0c;这不仅效率低下&#xff0c;而且容易…...

Word中Normal.dotm样式模板文件

Normal.dotm文档 首先将自己电脑中C:\Users\自己电脑用户名\AppData\Roaming\Microsoft\Templates路径下的Normal.dotm文件做备份&#xff0c;在下载本文中的Normal.dotm文件&#xff0c;进行替换&#xff0c;重新打开word即可使用。 字体样式如下&#xff08;可自行修改&#…...

生成式 AI 与向量搜索如何扩大零售运营:巨大潜力尚待挖掘

在竞争日益激烈的零售领域&#xff0c;行业领导者始终在探索革新客户体验和优化运营的新途径&#xff0c;而生成式 AI 和向量搜索在这方面将大有可为。从个性化营销到高效库存管理&#xff0c;二者在零售领域的诸多应用场景中都展现出变革性潜力&#xff0c;已成为保持行业领先…...

WonderWorld:斯坦福与 MIT 联手打造实时交互生成图像,单图秒变 3D 虚拟世界

❤️ 如果你也关注大模型与 AI 的发展现状&#xff0c;且对大模型应用开发非常感兴趣&#xff0c;我会快速跟你分享最新的感兴趣的 AI 应用和热点信息&#xff0c;也会不定期分享自己的想法和开源实例&#xff0c;欢迎关注我哦&#xff01; &#x1f966; 微信公众号&#xff…...

2024年【制冷与空调设备安装修理】考试内容及制冷与空调设备安装修理最新解析

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 制冷与空调设备安装修理考试内容是安全生产模拟考试一点通总题库中生成的一套制冷与空调设备安装修理最新解析&#xff0c;安全生产模拟考试一点通上制冷与空调设备安装修理作业手机同步练习。2024年【制冷与空调设备…...

PHP const 和 define主要区别

在PHP中&#xff0c;const 和 define 都用于定义常量&#xff0c;但它们有一些关键的区别。以下是它们之间的主要不同点&#xff1a; 定义方式&#xff1a; const&#xff1a;在定义常量时&#xff0c;不需要使用函数形式&#xff0c;而是直接赋值。 const MY_CONSTANT som…...

期中前学习复习总结

期中前终于把每一科的本质给搞明白了。这篇文章也将各学科剖分为两部分。 目录 本质 学法 从问题或条件出发思考问题 从条件出发思考问题 从结论/问题出发思考问题 整理知识与反向押题法 反向押题法 本质 作者是一个理科脑&#xff0c;什么都觉得只要我脑子够新东西我…...

基于大模型的 UI 自动化系统

基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...

Zustand 状态管理库:极简而强大的解决方案

Zustand 是一个轻量级、快速和可扩展的状态管理库&#xff0c;特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...

Java - Mysql数据类型对应

Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...

oracle与MySQL数据库之间数据同步的技术要点

Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异&#xff0c;它们的数据同步要求既要保持数据的准确性和一致性&#xff0c;又要处理好性能问题。以下是一些主要的技术要点&#xff1a; 数据结构差异 数据类型差异&#xff…...

TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案

一、TRS收益互换的本质与业务逻辑 &#xff08;一&#xff09;概念解析 TRS&#xff08;Total Return Swap&#xff09;收益互换是一种金融衍生工具&#xff0c;指交易双方约定在未来一定期限内&#xff0c;基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...

Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理

引言 Bitmap&#xff08;位图&#xff09;是Android应用内存占用的“头号杀手”。一张1080P&#xff08;1920x1080&#xff09;的图片以ARGB_8888格式加载时&#xff0c;内存占用高达8MB&#xff08;192010804字节&#xff09;。据统计&#xff0c;超过60%的应用OOM崩溃与Bitm…...

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分&#xff1a; 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...

pikachu靶场通关笔记19 SQL注入02-字符型注入(GET)

目录 一、SQL注入 二、字符型SQL注入 三、字符型注入与数字型注入 四、源码分析 五、渗透实战 1、渗透准备 2、SQL注入探测 &#xff08;1&#xff09;输入单引号 &#xff08;2&#xff09;万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取表名…...

嵌入式学习之系统编程(九)OSI模型、TCP/IP模型、UDP协议网络相关编程(6.3)

目录 一、网络编程--OSI模型 二、网络编程--TCP/IP模型 三、网络接口 四、UDP网络相关编程及主要函数 ​编辑​编辑 UDP的特征 socke函数 bind函数 recvfrom函数&#xff08;接收函数&#xff09; sendto函数&#xff08;发送函数&#xff09; 五、网络编程之 UDP 用…...

计算机系统结构复习-名词解释2

1.定向&#xff1a;在某条指令产生计算结果之前&#xff0c;其他指令并不真正立即需要该计算结果&#xff0c;如果能够将该计算结果从其产生的地方直接送到其他指令中需要它的地方&#xff0c;那么就可以避免停顿。 2.多级存储层次&#xff1a;由若干个采用不同实现技术的存储…...