一、 总括

你了解Jetty 吗,就像我们所熟知的Tomcat一样, Jetty是一个免费的开放源码的100%纯Java的Http服务器和Servlet容器。

Jetty具备以下特点:

快速高效

。Jetty是最快的Servlet服务器之一

     。Jetty可以处理上千个并发连接
     小巧嵌入
     。Jetty的jar只有600多K
     。可动态嵌入到应用程序,适合开发web2.0等应用

应用广泛

。开源项目有Geronimo, JBoss, JOnAS等

。商业项目有IBM Tivoli, Sonic MQ and Cisco SESM等

可到Jetty网站 http://jetty.mortbay.org/jetty/ 查看最新信息

     本文将通过对Jetty最新稳定版 Jetty5.1.5RC2 源码的研究,向读者展示Jetty在设计方面使用的不同设计理念, 希望对广大开发者在设计自己的系统时有所帮助。

Jetty按照功能可以分为四个主个主要的部分,HttpServer, HttpContext,HttpHandler,HttpListener,详见如下类图:

<图 1-1>

二、HttpServer及配置

     对于初次接触Jetty的人一定会对上图感到迷惑,其实在Jetty中 HttpServer是一个服务器的核心控制类, 我们可以看到,其它的组件类都是由该类扩展开来,HttpServer的作用就是在一系列的监听器类和处理器类之间搭起了一个桥梁,有效的控制着消息在系统内的传递,如下图:
<图 1-2 >
     HttpServer职责是接受从HttpListener传递过来的request(请求),HttpServer通过对request的Host(主机)或Path(路径)进行匹配,然后分发给相应的HttpContext(可以理解为一个web application)。
     这里举个例子,假设我们现在要建立一个提供静态页面web服务,页面内容在c:\root \下,可以通过如此配置HttpServer:
     HttpServer server = new HttpServer(); // 创建一个新的HttpServer
     SocketListener listener = new SocketListener(); // 创建一个新监听器
     listener.setPort(8080);// 设置监听端口为8080
     server.addListener(listener);// 将监听类注册到server中
     HttpContext context = new HttpContext(); // 创建一个新HttpContext
     context.setContextPath(“/app/*”); // 设置访问路径
     context.setResourceBase(“c:/root/”); // 设置静态资源路径
     context.addHandler(new ResourceHandler()); // 为这个HttpContext添加一个静态资源处理器
     server.addContext(context); // 将这个HttpContext注册到server中
     server.start();// 最后启动这个server
     当我们要建立一个提供动态页面web服务时, 假设我们自己的 web 应用放在Jetty目录下的webapps下并打好包文件名为myapp.war, 可以通过如此配置HttpServer:
     Server server = new Server(); // 创建一个新的HttpServer
     SocketListener listener = new SocketListener();// 创建一个新监听器
     listener.setPort(8080); // 设置监听端口为8080
     server.addListener(listener ); // 将监听类注册到server中
     server.addWebApplication(“myapp”,”./webapps/myapp/”); // 将这个web应用注册到这个Server中
     server.start(); // 最后启动这个server
     短短数行代码就可创建一个web服务器并启动它,这有点类似于我们windows中的即插即用的概念,需要什么就添加什么,把这些类以HttpServer为核心组合在一起,就可以完成强大的功能。
 

三、Jetty Server

     1.上面我们探讨了HttpServer的启动,读者一定还存在这样疑问,整个Jetty 服务器是怎样启动的?
     首先我们可以在图 1-1 看到左下角有一个Server类,这个类实际上继承了HttpServer,当启动Jetty服务器时,具体来说,在Jetty根目录下命令行下如输入 JAVA -jar start.jar etc/demo.xml,注意这里有一个配置文件 demo.xml做为运行参数,这个参数也可以是其它的配置文件,也可是多个xml配置文件,其实这个配置文件好比我们使用struts时的struts -config.xml文件,将运行Server需要用到的组件写在里面,比如上一节中HttpServer的配置需要的组件类都可以写在这个配置文件中。
     2.我们自己部署到Jetty的webapps目录下的web application,Jetty如何运行我们自己的web application?
     首先当我们按上述方法启动Jetty Server时,就会调用Server类里面的main方法,这个入口方法首先会构造一个Server类实例(其实也就构造了一个 HttpServer),创建实例过程中就会构造XmlConfiguration类的对象来读取参数配置文件,之后再由这个配置文件产生的 XmlConfiguration对象来配置这个Server,配置过程其实是运用Java的反射机制调用Server的方法并传入配置文件中所写的参数来向这个Server添加HttpListener,HttpContext,HttpHandler,web application(对应我们自己部署的web应用)。
     添加我们自己的web application过程中相应的就会读取我们所熟知的/WEB-INF/web.xml来创建一个WebApplicationContext(这个类继承了HttpContext)的实例,同时也会创建WebApplicationContext自身的ServletHandler(实现了 HttpHandler接口),注意到ServletHandler中包含一组ServletHolder指向实际的Servlet,譬如说我们在 web.xml文件中配置了两个Filter和一个Servlet,这里就会有三个ServletHolder,实际处理请求时 ServeletHandler就会依次调用这三个ServletHolder传入request,response处理(实际最后交给这两个 Filter和Servlet处理),这样我们自己做好的一个 web应用就挂载到这个Server上了,可以接受客户端相应的request(请求)。
 

四、运行原理(时序图)

<图 1-7 >

上图展示了一个request的处理过程,首先HttpListener监听到客户端发来的请求创建一个HttpConnection实例(封装了连接细节,比如从Socket连接中获取的输入流和输出流), HttpConnection对象构建过程中会创建Jetty内部自定义的HttpRequest和HttpResponse对象,接着 HttpListener会调用这个HttpConnection实例的handle方法, HttpConnection实例就调用HttpRequest对象的read()方法读取信息,调用HttpServer的service方法以 HttpRequest,HttpResponse为参数传给HttpServer,HttpServer又将HttpRequest和 HttpResponse分发给相应的HttpCotext,HttpContext最后将HttpRequest和HttpResponse交给自身的 HttpHandler 处理,在这里HttpRequest,HttpResponse被再次封装为ServletHttpRequest和 ServletHttpResponse,其实这两个类实现了我们所熟知的HttpServletRequest和 HttpServletResponse接口。

 

五、高级组件

1.HttpHandler:

     该接口的实现类用于处理HttpContext分发过来的reqeust,不同的实现类的有不同的处理功能,这里介绍几常用的HttpHandler实现类:
     ReourceHandler:用于处理静态内容,如以扩展名为.html的文件

SecurityHandler:提供基本的安全验证

ForwardHandler:转发一个request到另一个url

     ServletHandler:用于将request交由具体的Servlet类进行处理
     2.当你在看图 1-2 时候会注意到HttpServer和HttpListener,HttpServer与HttpContext,HttpContext与 HttpHandler存在一对多的关系,下面就介绍一下它们之间的这种关系如何通过程序来配置.

HttpListener & HttpServer:

HttpListener是所有监听器类的接口,如图中的SocketListener (基于传统的Socket技术)就实现了该接口,Jetty还有其它的实现该接口类,如SocketChannelListener(基于NIO技术)类等,HttpListener职责主要是在服务器启动后监听相应端口的来自客户端请求并建立连接(图 1-1 中所示用HttpConnection封装连接细节),监听器可在同个IP上开启多个端口为同一个HttpServer 进行监听,所以HttpListener和HttpServer是多对一的关系,如下图:

<图 1-3 >

     配置代码:
     HttpServer server = new HttpServer();
     HttpListenrer listener1 = new SocketChanneListener();
     Listener1.setPort(8080);
     HttpListenrer listener1 = new SocketListener();
     Listener1.setPort(8443);
     server.addListener(listener1);
     server.addListener(listener2);
 

HttpContext & HttpHandler:

HttpContext相当于对应客户端请求的URL或某个虚拟机, 其子类中包含若干个HttpHandler, 当接受到request(请求)时,HttpContext会依次(按某个预定的次序)把request交给这些HttpHandler处理,直到这个 request被标示处理过为止, 需要注意的是这个request可能被多个HttpHandler处理,但只能有一个HttpHandler能标示这个request已被处理过.

     一个典型的HttpContext有用于安全处理、静态资源处理及Servlet类的 HttpHandler,如下图:
<图 1-4>
     配置代码:
     HttpContext context = new HttpContext();
     context.setContextPath(“/myapp/*”);
     HttpHandler securitHandler = new SecurityHandler();
     HttpHandler resourceHandler = new ResourceHandler();
     HttpHandler servletHandler = new ServletHandler();
     context.addHandler(securitHandler);
     context.addHandler(resourceHandler);
     context.addHandler(servletHandler);
 
     HttpServer & HttpContext:
     一般的HTTP服务器软件可以同时处理多个web application,同样一个HttpServer可以包含多个HttpContext,如下图可以通过同一个端口的监听类来映射多个 HttpContext:

<图 1-5 >

     配置代码:
     HttpServer server = new HttpServer();
     HttpContext context1 = new HttpContext();
     context1.setContextPath(“/app1/*”);
     HttpContext context2 = new HttpContext();
     context2.setContextPath(“/app2/*”);
     server.addContext(context1);
 
     HttpServer & HttpLister & HttpContext:

另外Jetty对多网卡(多个IP地址,不同的主机名)的服务器也提供了很好的支持,每个 HttpContext都有自身的HttpServer:

<图 1-6 >

     配置代码:
     HttpServer server1 = new HttpServer();
     SocketListener listener1 = new SocketListener();

listener1.setHost(“www.app1.com”);//orListener1.setHost(“www.app2.com”)

listener2.setPort(80);

HttpContext context1 = new HttpContext();

context1.setContextPath(“/”);

     server1.addListener(listener1);

server1.addContext(context1);

 
     3.Jetty对高并发的支持
<图 1-8>
     如果多用户请求服务就会涉及到多线程的管理,如图 1-8,Jetty中主要由ThreadPool负责管理多线程,注意其中Pool.PondLife是Pool的一个内部接口, ThreadPool.PoolThread是ThreadPool的一个内部线程类,我们看到Pool.PondLife和Pool存在一个聚集的关系,实际上Pool对象中存放在是一个个ThreadPool.PoolThread线程对象,当有新用户连接上Server时,ThreadPool就从Pool中取一个空闲的线程为当前用户连接服务。
 

六、小结

本文通过图示简要介绍了Jetty整个体系架构和主要的组件类及服务器的启动执行过程,其实Jetty 通常被用来做为内嵌的Web Server来使用,一些常见的服务器软件,如Apache Cocoon、JBoss ,JOnAs等都会采用Jetty作为Web解決方案;另外由于Jetty在性能及稳定性要优于同类HTTP Server的原因,Jetty已在国外已很流行,鉴于这一点,本文作者可以预测在不久的将来Jetty同样也会在国内流行开来。

Jetty 源码分析相关推荐

  1. Jetty - Container源码分析

    1. 描述 Container提供管理bean的能力. 基于Jetty-9.4.8.v20171121. 1.1 API public interface Container {// 增加一个bean ...

  2. SparkContext源码分析

    SparkContext源码分析 粗略的说明一下SparkContext源码! createTaskScheduler()针对不同的提交模式,执行不同的方法(local,standalone.yanr ...

  3. Dubbo源码分析笔记-一(工程目录介绍)

    Dubbo 是阿里开发的分布式服务调用框架,提供了它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现. 工程目录 模块介绍 dubbo-common   Dubb ...

  4. zuul源码分析之Request生命周期管理

    为什么80%的码农都做不了架构师?>>>    zuul核心框架 zuul是可以认为是一种API-Gateway.zuul的核心是一系列的filters, 其作用可以类比Servle ...

  5. 精尽Spring Boot源码分析 - 内嵌Tomcat容器的实现

    概述 我们知道 Spring Boot 能够创建独立的 Spring 应用,内部嵌入 Tomcat 容器(Jetty.Undertow),让我们的 jar 无需放入 Servlet 容器就能直接运行. ...

  6. SpringBoot源码分析之内置Servlet容器

    原文链接:http://fangjian0423.github.io/2017/05/22/springboot-embedded-servlet-container/ SpringBoot内置了Se ...

  7. Tomcat8源码分析系列-spring boot集成tomcat

    前言 本文基于 spring boot 1.5.9 spring boot 支持目前主流的 servlet 容器,包括 tomcat.jetty.undertow,可以在我们的项目中方便地集成这些 s ...

  8. springboot源码分析

    快速开发底层原理 SpringBoot核心理念 能够实现帮助开发者快速的整合第三方框架(Spring.Mybatis.hibernate) 原理:Maven依赖封装整合和自定义starter. 完全去 ...

  9. 第七章:小朱笔记hadoop之源码分析-hdfs分析 第五节:Datanode 分析

    第七章:小朱笔记hadoop之源码分析-hdfs分析 第五节:Datanode 分析 5.1 Datanode 启动过程分析 5.2 Datanode 心跳分析 5.3 Datanode 注册分析 5 ...

最新文章

  1. 亚洲最大的元宇宙平台,体验在豪宅里开party
  2. 机器学习经典分类算法 —— C4.5算法(附python实现代码)
  3. 深度学习之自编码器(2)Fashion MNIST图片重建实战
  4. android华为虚拟截屏黑屏,Android截屏表面视图显示黑屏
  5. 设置最小值_WELSIM中设置有限元计算结果的最大最小值
  6. ftp ---- 认识ftp
  7. oracle oid 10G
  8. mysql 锁监视器_MySQL锁监视器
  9. bandwidth 0.32k 发布,内存带宽测试工具
  10. Linux chapter 1
  11. Face Recognition 人脸识别该如何测试
  12. otsu阈值分割算法原理_Otsu算法
  13. java单点登录解决方案_N多系统单点登录,实现、解决方案。四种解决方案
  14. Activiti 入门学习笔记
  15. 一起学Vue自定义组件之拼图小游戏
  16. 重磅!中国首家互联网银行联手腾讯、华为各大APP,最高5万额度,疯狂提额100亿!!!...
  17. 通话用哪款蓝牙耳机好?通话效果比较好的蓝牙耳机推荐
  18. usb触摸屏驱动 - usbtouchscreen
  19. C# 调用微软自带SpeechSDK 实现文字转语音
  20. 2.SpringBoot学习(二)——Spring Boot ConfigurationProperties

热门文章

  1. 如何使用vlookup+excel数组公式 完成逆向查找?
  2. 定时清理某一类文件,使其保证一定的数量
  3. Linux ora-12514多实例,ORA-12514问题解决
  4. 常见web安全隐患及解决方案
  5. Django框架总结
  6. 选择IB课程需要慎重
  7. k8s Pod探针(健康检查和服务可用性检查)
  8. 在使用 NModBus 开发Modbus协议数据时对待无符号16整形的问题(UShort转Short)
  9. 三维重建 几何方法 深度学习_三维重建 3D reconstruction 有哪些实用算法?
  10. cesiumjs坐标经纬度转换