图解WildFly8之Servlet容器Undertow剖析

简介: Undertow简介Undertow 是RedHat(红帽公司)的开源产品,采用 Java 开发的灵活的高性能 Web 服务器,提供包括阻塞和基于 NIO 的非堵塞机制。

Undertow简介

Undertow 是RedHat(红帽公司)的开源产品,采用 Java 开发的灵活的高性能 Web 服务器,提供包括阻塞和基于 NIO 的非堵塞机制。

WildFly8的默认Servlet容器采用的不是Tomcat,也不是Jetty,而是JBoss自己开源的Undertow,Undertow是用Java编写的性能灵活的Servlet容器,底层基于高性能的NIO框架XNIO,XNIO也是JBoss开源的产品,JBoss开源的高性能NIO框架还有一个很有名:Netty。Undertow在WildFly8中的角色如图:


Undertow的架构类似于Jetty,采用应用内嵌的方式,这也正是为什么说它有灵活的性能的原因,利用Undertow可以快速构建一个小巧的应用服务,实现代码如下:

import io.undertow.Handlers;
import io.undertow.Undertow;
import io.undertow.server.HttpHandler;
import io.undertow.server.handlers.PathHandler;
import io.undertow.servlet.Servlets;
import io.undertow.servlet.api.DeploymentInfo;
import io.undertow.servlet.api.DeploymentManager;
import io.undertow.servlet.api.ServletContainer;
import io.undertow.servlet.api.ServletInfo;

public class WildFlyServer {

    public static void main(final String[] args) throws Exception {
        
        // 创建ServletInfo,名字"MyServlet"必须唯一
        ServletInfo servlet1 = Servlets.servlet("MyServlet", MyServlet.class);
        // 设置Servlet的init方法执行时需要的数据
        servlet1.addInitParam("message", "Hello World");
        // 绑定映射为/hello
        servlet1.addMapping("/hello");
        
        // 创建名字MessageServlet为的ServletInfo
        ServletInfo servlet2 = Servlets.servlet("MessageServlet", MessageServlet.class);
        servlet2.addInitParam("message", "MyServlet");
        // 绑定映射为/myservlet
        servlet2.addMapping("/qrcode");
        
        // 创建DeploymentInfo应用布署
        DeploymentInfo deployment = Servlets.deployment();
        // 指定ClassLoader
        deployment.setClassLoader(WildFlyServer.class.getClassLoader());
        // 应用上下文(必须与映射路径一致,否则sessionID会有问题,每次都新建)
        deployment.setContextPath("/myapp");
        // 设置布署包名
        deployment.setDeploymentName("test.war");
        // 添加ServletInfo
        deployment.addServlets(servlet1,servlet2);

        // 创建DeploymentInfo2应用布署
        DeploymentInfo deployment2 = Servlets.deployment();
        deployment2.setClassLoader(WildFlyServer.class.getClassLoader());
        deployment2.setContextPath("/myapp2");
        deployment2.setDeploymentName("test2.war");
        deployment2.addServlets(servlet1,servlet2);
        
        // 使用默认Servlet容器,并将布署添加至容器
        ServletContainer container = Servlets.defaultContainer();
        // 将布署添加至容器,生成布置对应的管理器
        DeploymentManager manager = container.addDeployment(deployment);
        DeploymentManager manager2 = container.addDeployment(deployment2);
        // 实施布署
        manager.deploy();
        manager2.deploy();
        
        // 生成路径处理器(作用是dispatch servlet),默认返回"/*"处理器
        PathHandler path = Handlers.path();
        // 生成路径处理器,返回"/*"自动重定向到"/myapp"的处理器
//        PathHandler path = Handlers.path(Handlers.redirect("/myapp"));
        
        // 启动容器,生成请求处理器
        HttpHandler myapp = manager.start();
        HttpHandler myapp2 = manager2.start();
        // 绑定映射关系
        path.addPrefixPath("/myapp", myapp);
        path.addPrefixPath("/myapp2", myapp2);
        
        Undertow server = Undertow.builder()
                // 绑定端口与主机
                .addHttpListener(8080, "localhost")
                // 设置分发处理器PathHandler
                .setHandler(path)
                .build();
        // 启动Server
        server.start();
        
    }
}

从源代码,我们可以抽象出Undertow生成应用的架构,如图所示


利用运行调试,我们可以更加深入地了解Undertow中的一些概念:
ServletInfo:Servlet的最小单位,是对javax.servlet.Servlet具体实现的再次封装

FilterInfo:过滤器封装
DeploymentInfo:包布署对象,包含多个ServletInfo,可以说是ServletInfo的集合
ServletContainer:容器,用来管理DeploymentInfo,一个容器可以添加多个DeploymentInfo
DeploymentManager:包布署的管理,是对添加到ServletContainer的DeploymentInfo的一个引用,用于运行发布和启动容器
HttpHandler:servlet path处理器,DeploymentManager启动后返回的Servlet处理器,通常是HttpContinueReadHandler(连续读处理器)
PathHandler:分发器,将用户请求分发给对应的HttpHandler
HttpServerExchange:数据交换封装,可以转换成ServletRequest和ServletResponse
示例代码的调试运行栈如下:


连接通道


作为Servlet协议协议转换的实体HttpServerExchange的结构如下:


Undertow的性能

专业测评结果的数据如下:


目录
相关文章
|
Java 中间件 应用服务中间件
Servlet容器与Web容器详解
Servlet容器与Web容器详解
577 0
|
Java 应用服务中间件 容器
25 SpringBoot使用外置的Servlet容器
25 SpringBoot使用外置的Servlet容器
210 0
|
前端开发 Java 应用服务中间件
Spring Boot 2.x 嵌入式 Servlet 容器
Spring Boot使用内嵌Tomcat,默认端口8080,可通过`application.properties`配置端口、上下文路径等。配置方式有两种:1) 直接在配置文件中添加`server.port`和`server.servlet.context-path`;2) 创建`WebServerFactoryCustomizer` Bean来自定义配置,如设置端口`factory.setPort(8083)`,这种方式优先级更高。
479 0
|
Java 应用服务中间件 容器
手写SpringBoot(二)之动态切换Servlet容器
我们在切换serlvet容器的时候,会将SpringBoot默认的tomcat jar包给排除掉,换上我们需要的jar包,比如jetty。
248 0
|
前端开发 Java 应用服务中间件
24 SpringBoot配置嵌入式Servlet容器
24 SpringBoot配置嵌入式Servlet容器
306 0
24 SpringBoot配置嵌入式Servlet容器
|
Java 中间件 应用服务中间件
Web 容器、HTTP 服务器 、Servlet 容器区别与联系
Web 容器、HTTP 服务器 、Servlet 容器区别与联系
758 0
Web 容器、HTTP 服务器 、Servlet 容器区别与联系
|
设计模式 安全 Java
【Tomcat技术专题】循序渐进,分析Servlet容器鼻祖的Server和Service组件原理
【Tomcat技术专题】循序渐进,分析Servlet容器鼻祖的Server和Service组件原理
429 0
【Tomcat技术专题】循序渐进,分析Servlet容器鼻祖的Server和Service组件原理
|
缓存 安全 Java
Java服务器端技术:Servlet与JSP的集成与扩展
Java服务器端技术:Servlet与JSP的集成与扩展
270 3
|
存储 Java 关系型数据库
基于Servlet和JSP的Java Web应用开发指南
基于Servlet和JSP的Java Web应用开发指南
624 1
|
存储 缓存 前端开发
Servlet与JSP在Java Web应用中的性能调优策略
Servlet与JSP在Java Web应用中的性能调优策略
288 1