Jetty 源码分析

合集下载

jettyhttpclient实现分析

jettyhttpclient实现分析

背景谈到http client,可能大多数想到就是apache的那个http client 或者jdk自带的urlconnection,也许有人会考虑使用netty,无论如何,jetty的高性能实现总归是让人感到好奇,接下来我们一探究竟样例我们结合样例代码具体分析l 初始化l 运行代码分为两段l 初始化:设置httpclientl 运行:实例化ContentExchange,定义callback,本例定义了两个常用的callback:onResponseComplete 和 onExpire 更多的callbac可参考官方文档/Jetty/Tutorial/HttpClientl APP在调用httpClient.send(exchange);后不会象往常一样等待返回而是立即返回, 如果有结果或者超时会通过上面的callback通知到APP httpclient的原理及实现1 )httpclient的模型lSelectConnector: 作为一个connection管理器,封装了selector和connection lHttpDestination:一个host的抽象一个HttpClient会连接到多个HttpDestination lHttpExchange:一次http请求的封装,一个HttpDestination会有多个HttpExchange以及多个AsyncHttpConnection lAsyncHttpConnection:HttpClient对某个HttpDestination的一个网络连接,底层包含一个对应的socket, 可复用来完成多次请求, 如果空闲太久会被废弃lSelectChannelEndPoint:socket的封装,AsyncHttpConnection和SelectChannelEndPoint一一对应, 但AsyncHttpConnection承载了更多的东西lHttpGenerator:生成http request,在jetty server中负责生成http response lHttpParser: 解析http response, 在jetty server中负责解析http request lThreadPool: 线程池,httpclient需要使用线程池配合完成无阻塞IO,这个会在后面的httpclient整体架构分析中详述l Timeout:一个已时间排序的链表结构,链表中存储需要过期执行的task,这个会在后面流程分析详述2)httpclient的整体架构http client 分为3组线程配合完成lselector线程组:数目可设置,默认为1,从_change队列中获取socket注册并扫描操作系统级别的网络事件, 通常是socket 可读, 可写的信息,一旦发现有socket可读写,会将相关socket任务丢入_jobs队列供worker线程执行l worker线程组:数目根据并发的情况决定,从_jobs队列获取任务,如果任务阻塞会丢入_changes队列异步等待通知再干活l tick线程:数目1个,专门用于监控超时的请求以及空闲太久的连接l 所有的线程都来自线程池,所以线程池最小为3,否则无法work 3)典型的场景分析模拟一次请求3.1 )httpclient初始化l1-2设置两个超时链表,一个是超时请求链表,一个是超时连接链表l3 启动httpbuffer l4 启动线程池l5 启动SelectConnector,此时会启动selector线程任务l6 启动tick线程任务3.2)jetty http client runtime3.2.1)httpClient.send(exchange)到底干了什么l1-2正如样例代码所示,APP设置HttpExchange,然后httpclient的send方法l2.1-2.2 httpclient根据httpexchange获取对应http destination,并调用其send方法l2.2.1 将次请求加入请求超时链表l2.2.2 -2.2.3 获取空闲连接,如果没有,则产生一个新的连接,并调用select进行注册,否则直接使用该连接, 并将此连接丢入 _jobs队列让worker线程完成 请求l 此时客户端就这样无阻塞的完成了3.2.2)select线程如何参与这个场景l1-3 selector线程从_change队列获取到新的socket, 开始实例化SelectChannelEndPoint l4 通知http desination连接完成,于是http detination将次连接丢入连接超时链表l 5-6 将此连接/请求丢入_jobs队列供worker线程使用3.2.3)worker线程又如何参与这个场景lworker线程从队列中获取任务l1.1 通过此连接发送请求,请求内容http generator产生l1.2 一发完请求立即通过http parser读取响应,如果服务器够快,通常会读到响应l1.3 如果服务器不能及时响应,那么调用SelectChannelEndPoint的updateKey。

activiti源码分析(一)设计模式

activiti源码分析(一)设计模式

activiti源码分析(⼀)设计模式 对activiti有基本了解的朋友都知道,activiti暴露了七个接⼝来提供⼯作流的相关服务,这些接⼝具体是如何实现的呢?查看源码发现其实现的形式⼤体如下: public class RuntimeServiceImpl extends ServiceImpl implements RuntimeService {public ProcessInstance startProcessInstanceByKey(String processDefinitionKey) {return commandExecutor.execute(new StartProcessInstanceCmd<ProcessInstance>(processDefinitionKey, null, null, null));}public ProcessInstance startProcessInstanceByKey(String processDefinitionKey, String businessKey) {return commandExecutor.execute(new StartProcessInstanceCmd<ProcessInstance>(processDefinitionKey, null, businessKey, null));}...} service中的⼤部分⽅法都是通过调⽤commandExecutor.execute()完成的,然⽽点进去看则会发现什么都没有:public class CommandExecutorImpl implements CommandExecutor {private final CommandConfig defaultConfig;private final CommandInterceptor first;public CommandExecutorImpl(CommandConfig defaultConfig, CommandInterceptor first) {this.defaultConfig = defaultConfig;this.first = first;}public CommandInterceptor getFirst() {return first;}@Overridepublic CommandConfig getDefaultConfig() {return defaultConfig;}@Overridepublic <T> T execute(Command<T> command) {return execute(defaultConfig, command);}@Overridepublic <T> T execute(CommandConfig config, Command<T> command) {return first.execute(config, command);}} 看到这⾥就会发现并不能看出这条语句究竟做了什么,那么究竟是如何提供服务的呢?其实activiti中⼤部分操作都是基于设计模式中的命令模式完成的(这⾥还使⽤了职责链模式,构造了命令拦截器链,⽤于在命令真正被执⾏之前做⼀系列操作)。

SpringBoot内置Tomcat启动原理源码分析

SpringBoot内置Tomcat启动原理源码分析

SpringBoot内置Tomcat启动原理源码分析1、获取SpringBoot内置Tomcat⾃动配置类: 在SpringBoot项⽬中引⼊spring-boot-starter-web依赖,就默认使⽤Tomcat容器,该依赖中引⼊spring-boot-starter-tomcat、spring-webmvc,就引⼊了tomtcat核⼼依赖和springMvc相关jar包,这样就间接地引⼊了tomcat。

在执⾏SpringBoot项⽬启动类的main()⽅法,启动SpringBoot项⽬的过程中会加载各个jar包下META-INF/spring.factories的⽂件,在该⽂件中包含着⾃动配置的⼦路径,在refresh()⽅法中的invokeBeanFactoryPostProcessors()中⾸先会对启动类上的 @SpringBootApplication 注解进⾏解析,最终调⽤ AutoConfigurationImportSelector类中的 getAutoConfigurationEntry() 加载 META-INF/spring.factories ⽂件中的⾃动配置类,得到⾃动配置类的全路径,其中 org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration 为tomcat⾃动配置类。

具体加载流程见:protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {if (!isEnabled(annotationMetadata)) {return EMPTY_ENTRY;}AnnotationAttributes attributes = getAttributes(annotationMetadata);// 1、得到META-INF/spring.factories⽂件中配置的所有⾃动配置类List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);// 移除重复的配置类configurations = removeDuplicates(configurations);// 获取需要排除的⾃动配置类,eg:注解属性中的exculde的配置类Set<String> exclusions = getExclusions(annotationMetadata, attributes);// 检查需要被排除的配置类,因为有些不是⾃动配置类,需要抛异常checkExcludedClasses(configurations, exclusions);// 移除需要排除的配置类configurations.removeAll(exclusions);// 根据 META-INF/spring-autoconfigure-metadata.properties 中配置的规则过虑掉⼀部分配置类(根据@ConditionalOnXXX注解进⾏过滤)configurations = getConfigurationClassFilter().filter(configurations);// 获取符合条件的配置类后,触发 AutoConfigurationImportEvent 事件fireAutoConfigurationImportEvents(configurations, exclusions);// 将符合条件和需要排除的配置类封装进 AutoConfigurationEntry 对象中返回return new AutoConfigurationEntry(configurations, exclusions);}2、ServletWebServerFactoryAutoConfiguration - tomcat⾃动配置类分析3、创建tomcat⼯⼚@Configuration(proxyBeanMethods = false)@ConditionalOnClass({ Servlet.class, Tomcat.class, UpgradeProtocol.class })@ConditionalOnMissingBean(value = ServletWebServerFactory.class, search = SearchStrategy.CURRENT)static class EmbeddedTomcat {@BeanTomcatServletWebServerFactory tomcatServletWebServerFactory(ObjectProvider<TomcatConnectorCustomizer> connectorCustomizers,ObjectProvider<TomcatContextCustomizer> contextCustomizers,ObjectProvider<TomcatProtocolHandlerCustomizer<?>> protocolHandlerCustomizers) {// 创建⽣产tomcat的⼯⼚TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();factory.getTomcatConnectorCustomizers().addAll(connectorCustomizers.orderedStream().collect(Collectors.toList()));factory.getTomcatContextCustomizers().addAll(contextCustomizers.orderedStream().collect(Collectors.toList()));factory.getTomcatProtocolHandlerCustomizers().addAll(protocolHandlerCustomizers.orderedStream().collect(Collectors.toList()));return factory;}} 4、创建tomcat容器 在SpringBoot启动过程中会调⽤ AbstractApplicationContext.refresh() ⽅法,在该⽅法会调⽤onRefresh()⽅法,这个⽅法是个模板⽅法,最终会交给⼦类实现,在使⽤内置tomcat的SpringBoot项⽬中,最终会调⽤ ServletWebServerApplicationContext 实现(AbstractApplicationContext是GenericWebApplicationContext,ServletWebServerApplicationContext 是GenericWebApplicationContext),最终调⽤ServletWebServerApplicationContext 的createWebServer()⽅法创建 webServer。

Jetty的基本架构

Jetty的基本架构

Jetty的基本架构Jetty 的基本架构Jetty 目前的是一个比较被看好的 Servlet 引擎,它的架构比较简单,也是一个可扩展性和非常灵活的应用服务器,它有一个基本数据模型,这个数据模型就是Handler,所有可以被扩展的组件都可以作为一个Handler,添加到Server 中,Jetty 就是帮你管理这些Handler。

Jetty 的基本架构下图是 Jetty 的基本架构图,整个 Jetty 的核心组件由 Server 和Connector 两个组件构成,整个 Server 组件是基于 Handler 容器工作的,它类似与 Tomcat 的 Container 容器,Jetty 与 T omcat 的比较在后面详细介绍。

Jetty 中另外一个比不可少的组件是 Connector,它负责接受客户端的连接请求,并将请求分配给一个处理队列去执行。

图 1. Jetty 的基本架构Jetty 中还有一些可有可无的组件,我们可以在它上做扩展。

如JMX,我们可以定义一些 Mbean 把它加到 Server 中,当 Server 启动的时候,这些 Bean 就会一起工作。

图 2. Jetty 的主要组件的类图从上图可以看出整个Jetty 的核心是围绕着Server 类来构建,Server 类继承了Handler,关联了Connector 和Container。

Container 是管理 Mbean 的容器。

Jetty 的 Server 的扩展主要是实现一个个 Handler 并将 Handler 加到 Server 中,Server 中提供了调用这些 Handler 的访问规则。

整个 Jetty 的所有组件的生命周期管理是基于观察者模板设计,它和 Tomcat 的管理是类似的。

下面是 LifeCycle 的类关系图每个组件都会持有一个观察者(在这里是Listener 类,这个类通常对应到观察者模式中常用的Observer 角色,关于观察者模式可以参考《Tomcat系统架构与设计模式,第2部分:设计模式分析》一文中关于观察者模式的讲解)集合,当 start、fail 或 stop 等事件触发时,这些Listener 将会被调用,这是最简单的一种设计方式,相比Tomcat 的 LifeCycle 要简单的多。

jetty的工作原理以及与tomcat的比较

jetty的工作原理以及与tomcat的比较

Jetty 的工作原理以及与Tomcat 的比较与Tomcat 的比较总结大概如下:tomcat适合处理少量但是业务非常繁忙的服务比如应用平台,jetty适合做大量而且可以上时间保存的连接服务,如web服务,jetty体积小只有几百k Tomcat 和Jetty 都是作为一个Servlet 引擎应用的比较广泛,可以将它们比作为中国与美国的关系,虽然Jetty 正常成长为一个优秀的Servlet 引擎,但是目前的Tomcat 的地位仍然难以撼动。

相比较来看,它们都有各自的优点与缺点。

Tomcat 经过长时间的发展,它已经广泛的被市场接受和认可,相对Jetty 来说Tomcat 还是比较稳定和成熟,尤其在企业级应用方面,Tomcat 仍然是第一选择。

但是随着Jetty 的发展,Jetty 的市场份额也在不断提高,至于原因就要归功与Jetty 的很多优点了,而这些优点也是因为Jetty 在技术上的优势体现出来的。

架构比较从架构上来说,显然Jetty 比Tomcat 更加简单,如果你对Tomcat 的架构还不是很了解的话,建议你先看一下《Tomcat系统架构与设计模式》这篇文章。

Jetty 的架构从前面的分析可知,它的所有组件都是基于Handler 来实现,当然它也支持JMX。

但是主要的功能扩展都可以用Handler 来实现。

可以说Jetty 是面向Handler 的架构,就像Spring 是面向Bean 的架构,iBATIS 是面向statement 一样,而Tomcat 是以多级容器构建起来的,它们的架构设计必然都有一个“元神”,所有以这个“元神“构建的其它组件都是肉身。

从设计模板角度来看Handler 的设计实际上就是一个责任链模式,接口类HandlerCollection 可以帮助开发者构建一个链,而另一个接口类ScopeHandler 可以帮助你控制这个链的访问顺序。

另外一个用到的设计模板就是观察者模式,用这个设计模式控制了整个Jetty 的生命周期,只要继承了LifeCycle 接口,你的对象就可以交给Jetty 来统一管理了。

《Jetty6_指南书》

《Jetty6_指南书》

前言和目录写在前面:使用jetty已经很久了,它是一个很出色的web容器和工具,特在此和大家分享jetty6的知识。

网络上有一些关于jetty的资料,但过去陈旧且不具有系统性,导致很多人误解jetty的功能,国外目前也没有关于jetty的书籍,所以那些搞翻译的人也没有翻译来源,故决定写一本关于jetty6 的书,以推广jetty在国内的使用。

记住jetty不仅仅是一个web容器!版权声明:这一系列章节只在javaeye的博客发表,谢绝任何组织和个人的转载或抄袭!本人保留所有权利!如侵犯本版权则需赔偿人民币5000000圆整,因为劳动是无价的,这算便宜的了!作者:陈汝烨由于这一些系列文章正在编写过程中,写好一章就发一章,难免有很多错误的地方,欢迎哥们指正!关键字: jetty是什么 jetty配置 jetty使用 jetty嵌入 jetty启动 jetty部署 jetty教程 jetty嵌入式 jetty第1章Jetty介绍1.1 Jetty功能介绍1.2 Jetty的特点1.3 jetty项目历史和现状1.4 jetty vs tomcat1.5 本章小结2.1 下载2.2 安装2.3 使用java命令启动2.3.1 快速启动2.3.2 停止服务2.3.3 start.jar深入探讨2.4我们可以学到什么2.5 Windows系统下启动和关闭控制2.6 Linux系统下启动和关闭控制2.6.1 系统变量的设置2.6.2 命令参数2.6.3 相关配置文件2.7本章小结3.1 构架概述3.2 Connector3.3 Handler3.4 Server 和ThreadPool3.5 目录结构第4章Jetty服务配置文件4.1 jetty.xml 示例剖析4.2 Jetty xml Configuration语法4.3 org.mortbay.xml.XmlConfiguration 第5章在Jetty中部署Web应用程序相关的配置文件静态部署动态热部署Servlet2.5 新特性第6章Handler详细本章相信介绍各种Handler的功能和用法第7章类加载器第8章Jetty ConnectorSSL的配置,和apache mod_proxy,ajp部署9虚拟主机讲解Jetty下虚拟主机的配置方法10管理服务器服务器日志管理,请求日志,实时状态,关闭服务器,JMX管理 linux 非root用户在80端口启动11配置JNDI介绍jndi如何使用、12会话与集群13性能优化线程池,内存大小配置,共享libGZIPOptimizing with Last-Modified and Cache-Control Optimizing Browser CachingOptimizing on High Load Serverslinux最大连接数配置linux下epull启用配置14异步Servlet,AJax,Comet15Embedding Jetty16 JEE服务器整合17 在开发环境中使用Jetty18 安全19 FAQJetty6 指南书 - 第一章 Jetty介绍文章分类:Java编程写在前面:使用jetty已经很久了,它是一个很出色的web容器和工具,特在此和大家分享jetty6的知识。

Jetspeed (开源Portal)系统及源代码分析

Jetspeed (开源Portal)系统及源代码分析

Jetspeed 系统及源代码分析技术研究四室2003-5-18目录JETSPEED 系统及源代码分析 (1)序言 (5)1.1简介 (7)1.2代码目录介绍 (8)1.3安装运行 (9)1.4配置文件 (10)1.4.1Properties文件 (10)1.4.2Xreg文件 (10)1.5主要概念 (12)1.5.1页面组件(modules) (12)1.5.2服务(service) (13)1.5.3模板(templates) (14)1.5.4对象关系模型(om) (14)1.5.5Portlet & Portal (14)1.6系统结构 (15)1.7P ORTAL S ERVLET及系统主要流程 (18)1.7.1初始化 (18)1.7.2RunData数据结构 (18)1.7.3处理请求 (20)1.7.4页面生成 (21)1.7.5事件处理流程 (25)1.7.6Session Validator处理流程 (26)1.8M ODULES (27)1.8.1Action (27)1.8.2Page (27)1.8.3Layout (27)1.8.4Screen (27)1.8.5Navigation (28)1.11J ETSPEED T AG L IB (31)1.12R EGISTRY (33)1.13P ORTAL &P ORTLET (36)1.14用户管理及访问控制 (38)1.15S ERVICES (39)1.15.1TurbineService (39)1.15.2AssemblerBrokerService (39)1.15.3GlobalCacheService (40)1.15.4CastorService (41)1.15.5ComponentService (42)1.15.6DB Service (43)1.15.7FactoryService (43)1.15.8FreeMarkerService (45)1.15.9IntakeService (46)1.15.10JspService (46)1.15.11LocalizationService (47)1.15.12LoggingService (47)1.15.13MimeTypeService (48)1.15.14NamingService (49)1.15.15PoolService (49)1.15.16ProfileService (50)1.15.17PsmlManagerService (50)1.15.18PullService (51)1.15.19ResourceService (51)1.15.20RegistryService (51)1.15.21RunDataService (51)1.15.22ScheduleService (54)1.15.23SecurityService (54)1.15.26UniqueIdService (56)1.15.27UploadService (56)1.15.28VelocityService (57)1.15.29WebMacroService (58)1.15.30XmlRpcService (59)1.15.31XSLTService (62)1.16自主化个性门户的实现 (63)1.16.1需要实现怎样一个自主化的个性门户 (63)1.16.2需要对Jetspeed的修改完善之处 (63)1.16.3考虑自己重新实现的可行性 (65)1.17附录 (66)1.17.1Turbine.init (66)1.17.2Turbine.doGet (67)1.17.3JetspeedSessionValidator (71)1.17.4DefaultPage.doBuilde (73)1.17.5JetspeedPanTag (74)1.17.6JetspeedToolkitService.getSet (75)1.17.7PortletSet.getContent (77)1.18后序 (79)序言随着Portal的应用越来越广泛,人们对Portal的由来与开发也变得越来越感兴趣。

天移系统源码

天移系统源码

天移系统源码天移系统是一款基于Java平台开发的网络文件传输系统。

该系统能够快速地传输大量的文件,具有高效、安全、稳定等优点,受到广大用户的欢迎。

本文将对天移系统的源码进行分析,探究其优势和使用方法,为读者提供有指导意义的参考。

首先,我们来看一下天移系统的源码结构。

该系统的主要代码分为两个模块,分别是服务端和客户端。

服务端代码主要包括文件上传、下载、管理等功能,而客户端代码则负责与服务端进行通信,实现文件传输和控制等操作。

服务端主要由两个类组成,分别是FileServer和FileHandler。

FileServer是服务器的主类,负责启动服务端和与客户端建立连接。

而FileHandler则是服务端的核心处理类,负责具体的文件传输和管理操作。

在客户端代码中,主要有两个类,分别是FileClient和FileSender。

FileClient是客户端的主类,会向服务端发出请求并接收响应结果。

而FileSender则是文件传输的核心类,负责将文件分块并按顺序发送到服务端。

客户端还包括文件下载的功能,由文件下载类FileDownloader实现。

其次,天移系统的优势在于高效、安全、稳定等方面。

首先,该系统采用多线程方式实现,能够在传输大量文件时提高传输速度;其次,系统的设计考虑到了文件传输的安全性,加入了MD5校验码等机制,确保文件传输的完整性和准确性;最后,系统稳定性高,即使传输大量文件时也不会出现卡顿、崩溃等问题。

最后,我们还需要掌握天移系统的使用方法。

在使用之前,需要先启动服务端。

可以将服务端代码打包成jar包,然后在命令行中运行java -jar xxx.jar来启动。

服务端启动后,客户端就可以与其建立连接,在客户端中输入相应的命令来实现上传、下载等操作。

总之,天移系统是一款优秀的网络文件传输系统,其源码结构合理、优势明显、使用方便,可以满足大家在文件传输方面的需求。

读者们可以通过仔细阅读本文和相关资料,进一步掌握该系统的使用方法和开发技巧。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Jetty 源码分析在文库看到一个关于jetty源码分析的PDF文档,发现该文档根本不全,遂在网上又找到了关于此文档内容的网站,将其网页内容拷贝了出来,供大家浏览!一、总括你了解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网站 /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(); // 创建一个新的HttpServerSocketListener listener = new SocketListener(); // 创建一个新监听器listener.setPort(8080);// 设置监听端口为8080server.addListener(listener);// 将监听类注册到server中HttpContext context = new HttpContext(); // 创建一个新HttpContextcontext.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(); // 创建一个新的HttpServerSocketListener listener = new SocketListener();// 创建一个新监听器listener.setPort(8080); // 设置监听端口为8080server.addListener(listener ); // 将监听类注册到server中server.addWebApplication("myapp","./webapps/myapp/"); // 将这个web应用注册到这个Server中server.start(); // 最后启动这个server短短数行代码就可创建一个web服务器并启动它,这有点类似于我们windows中的即插即用的概念,需要什么就添加什么,把这些类以HttpServer为核心组合在一起,就可以完成强大的功能。

三、Jetty Server1.上面我们探讨了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到另一个urlServletHandler:用于将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.setCont extPath(“/app2/*”);server.addContext(context1);HttpServer & HttpLister & HttpContext:另外Jetty对多网卡(多个IP地址,不同的主机名)的服务器也提供了很好的支持,每个HttpContext都有自身的HttpServer:<图1-6 >配置代码:HttpServer server1 = new HttpServer();SocketListener listener1 = new SocketListener();listener1.setHost(“”);//orListener1.setHost(“”)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中取一个空闲的线程为当前用户连接服务。

相关文档
最新文档