图解WildFly8之Servlet容器Undertow剖析
Undertow簡(jiǎn)介
Undertow 是RedHat(紅帽公司)的開(kāi)源產(chǎn)品,采用 Java 開(kāi)發(fā)的靈活的高性能 Web 服務(wù)器,提供包括阻塞和基于 NIO 的非堵塞機(jī)制。
WildFly8的默認(rèn)Servlet容器采用的不是Tomcat,也不是Jetty,而是JBoss自己開(kāi)源的Undertow,Undertow是用Java編寫(xiě)的性能靈活的Servlet容器,底層基于高性能的NIO框架XNIO,XNIO也是JBoss開(kāi)源的產(chǎn)品,JBoss開(kāi)源的高性能NIO框架還有一個(gè)很有名:Netty。Undertow在WildFly8中的角色如圖:
Undertow的架構(gòu)類似于Jetty,采用應(yīng)用內(nèi)嵌的方式,這也正是為什么說(shuō)它有靈活的性能的原因,利用Undertow可以快速構(gòu)建一個(gè)小巧的應(yīng)用服務(wù),實(shí)現(xiàn)代碼如下:
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 {// 創(chuàng)建ServletInfo,名字"MyServlet"必須唯一ServletInfo servlet1 = Servlets.servlet("MyServlet", MyServlet.class);// 設(shè)置Servlet的init方法執(zhí)行時(shí)需要的數(shù)據(jù)servlet1.addInitParam("message", "Hello World");// 綁定映射為/helloservlet1.addMapping("/hello");// 創(chuàng)建名字MessageServlet為的ServletInfoServletInfo servlet2 = Servlets.servlet("MessageServlet", MessageServlet.class);servlet2.addInitParam("message", "MyServlet");// 綁定映射為/myservletservlet2.addMapping("/qrcode");// 創(chuàng)建DeploymentInfo應(yīng)用布署DeploymentInfo deployment = Servlets.deployment();// 指定ClassLoaderdeployment.setClassLoader(WildFlyServer.class.getClassLoader());// 應(yīng)用上下文(必須與映射路徑一致,否則sessionID會(huì)有問(wèn)題,每次都新建)deployment.setContextPath("/myapp");// 設(shè)置布署包名deployment.setDeploymentName("test.war");// 添加ServletInfodeployment.addServlets(servlet1,servlet2);// 創(chuàng)建DeploymentInfo2應(yīng)用布署DeploymentInfo deployment2 = Servlets.deployment();deployment2.setClassLoader(WildFlyServer.class.getClassLoader());deployment2.setContextPath("/myapp2");deployment2.setDeploymentName("test2.war");deployment2.addServlets(servlet1,servlet2);// 使用默認(rèn)Servlet容器,并將布署添加至容器ServletContainer container = Servlets.defaultContainer();// 將布署添加至容器,生成布置對(duì)應(yīng)的管理器DeploymentManager manager = container.addDeployment(deployment);DeploymentManager manager2 = container.addDeployment(deployment2);// 實(shí)施布署manager.deploy();manager2.deploy();// 生成路徑處理器(作用是dispatch servlet),默認(rèn)返回"/*"處理器PathHandler path = Handlers.path();// 生成路徑處理器,返回"/*"自動(dòng)重定向到"/myapp"的處理器 // PathHandler path = Handlers.path(Handlers.redirect("/myapp"));// 啟動(dòng)容器,生成請(qǐng)求處理器HttpHandler myapp = manager.start();HttpHandler myapp2 = manager2.start();// 綁定映射關(guān)系path.addPrefixPath("/myapp", myapp);path.addPrefixPath("/myapp2", myapp2);Undertow server = Undertow.builder()// 綁定端口與主機(jī).addHttpListener(8080, "localhost")// 設(shè)置分發(fā)處理器PathHandler.setHandler(path).build();// 啟動(dòng)Serverserver.start();} }
從源代碼,我們可以抽象出Undertow生成應(yīng)用的架構(gòu),如圖所示
利用運(yùn)行調(diào)試,我們可以更加深入地了解Undertow中的一些概念:
ServletInfo:Servlet的最小單位,是對(duì)javax.servlet.Servlet具體實(shí)現(xiàn)的再次封裝
FilterInfo:過(guò)濾器封裝
DeploymentInfo:包布署對(duì)象,包含多個(gè)ServletInfo,可以說(shuō)是ServletInfo的集合
ServletContainer:容器,用來(lái)管理DeploymentInfo,一個(gè)容器可以添加多個(gè)DeploymentInfo
DeploymentManager:包布署的管理,是對(duì)添加到ServletContainer的DeploymentInfo的一個(gè)引用,用于運(yùn)行發(fā)布和啟動(dòng)容器
HttpHandler:servlet path處理器,DeploymentManager啟動(dòng)后返回的Servlet處理器,通常是HttpContinueReadHandler(連續(xù)讀處理器)
PathHandler:分發(fā)器,將用戶請(qǐng)求分發(fā)給對(duì)應(yīng)的HttpHandler
HttpServerExchange:數(shù)據(jù)交換封裝,可以轉(zhuǎn)換成ServletRequest和ServletResponse
示例代碼的調(diào)試運(yùn)行棧如下:
連接通道
作為Servlet協(xié)議協(xié)議轉(zhuǎn)換的實(shí)體HttpServerExchange的結(jié)構(gòu)如下:
Undertow的性能
專業(yè)測(cè)評(píng)結(jié)果的數(shù)據(jù)如下:
總結(jié)
以上是生活随笔為你收集整理的图解WildFly8之Servlet容器Undertow剖析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: AOE网
- 下一篇: OSChina 周三乱弹——节前综合症来