Jetty是Java领域另一个出色的Web服务器,它同样也是开源的。
与tomcat不同的是它可作为一个嵌入式服务器。
也就是说,如果我们在应用中加入jetty的核心jar文件,应用即可对外提供http服务。
它同时也是平台无关的java web服务器,既可以在Windos平台上运行,也可以在Linux平台上运行。
如果让一个人说出一种开源的servlet容器,可能他们会回答Apache Tomcat。
但是,Tomcat并不是孤单的,我们还有Jetty。Jetty作为可选的servlet容器只是一个额外的功能,而它真正出名是因为它 是作为一个可以嵌入到其他的Java代码中的servlet容器而设计的。
这就是说,开发小组将Jetty作为一组Jar文件提供出来,因此你可以在你自 己的代码中将servlet容器实例化成一个对象并且可以操纵这个容器对象。
Jetty在servlet容器中算不上一个新面孔;它从1998年就已经崭露头角。Jetty的发布遵循了Apache 2.0的开源协议,你可以在免费软件和商业软件中使用Jetty而不用支付版税。
嵌入式Servlet容器的意义何在?
在你采用Jetty之前,理智的做法是首先问问自己:为什么自己的应用程序中需要嵌入一个servlet容器。
吸引我的视线的是Jetty可以为一个已经 存在的应用程序提供servlet功能的能力。这种能力对于很多组织都是有用的,包括Java EE应用服务器生产商,软件测试人员以及定制软件生产商。
大部分的Java开发人员都可以划分到这三种情况中。
首先,考虑要建立自己的Java EE应用服务器这样一种边缘情况。
根据规范,一个完整的应用服务器必须提供servlet,EJB,以及其他一些功能。
你应该采用已经存在而且测试过的组 件并且使用Jetty而不是从零开始。
Apache Geronimo, JBoss, 和ObjectWeb JOnAS这些项目组在建立自己Java EE应用服务器时也是这样做的。
当已经存在的容器不能满足需要的时候,软件测试人员会得益于按照需要来生成自己的servlet容器。
例如,曾经有个同事想要寻找某种方式来驱动他为 web service代码所写的单元测试。对于他的这种情形——几个开发人员加上几个运行在Cruise Control中的自动单元测试——我向他示范了在他的单元测试组(unit test suites)中如何动态的(on the fly)使用Jetty来实例化一个servlet容器。
没有多余的脚本,没有剩余的文件,只有代码。
对于那些开发Java EE应用作为产品的人员来说,为什么仅仅提供一个WAR文件?这样你为会容器的规范而头疼,同时也会增加你的技术支持的成本。
相反的,可以提供给客户一个 自己具有启动,停止以及管理功能的应用程序。就连硬件生产商也会从中受益:Jetty对于普通的HTTP服务(没有servlet)只需要350k的内 存,这使得可以将其用在智能设备中。
你可以提供基于web的控制面板并且具有Java web应用的所有功能而不用担心那些独立的容器所带来的压力。
最后,我敢打赌嵌入式servlet容器最有趣的应用会发生在那些从来不编写传统的基于web应用的人身上。
可以将Java EE和HTTP的组合作为一个C/S结构程序的后台。考虑一个事件驱动的服务,例如(假想的)Message-Driven Bank(onjava上的另外一篇文章中提到),从main()方法启动并且等待到来的请求,就像Unix中的daemon程序一样。肯定会有一些人想 要将这个程序暴露成一种基于用户的风格,例如一个GUI桌面应用,这只是个时间问题。
要创建自己的基础组件,协议和socket通讯代码是最令人生厌的,而且会使人从业务逻辑中分心,就更不用说将来可能要调试的事情了。
使用嵌入式的 Jetty容器来将业务逻辑通过HTTP协议暴露是一个不错的选择,它不用对现有程序作过多改变。选择采用Swing,SWT,XUI这些GUI并且将请 求包装成HTTP Post操作,REST,甚至SOAP来完成这个回路。
与定制的特定于某个领域的协议相比,这些通用的协议可能性能稍差,但是,用不了多久,你就会从这些 已经存在的经过实际检验的协议中得到好处并且节省大量的努力。
建立一个嵌入式的容器:使用Jetty API 希望以上的想法能够刺激你的胃口让你尝试一下嵌入式的servlet容器。
示例程序Step1Driver 演示了一个基于Jetty的简单服务。
它创建了一个servlet容器的实例,将一个servlet class映射到一个URI,并且使用一些URL来调用这个servlet。为了代码的简洁,我牺牲了一些代码的质量。
Service对象就是Jetty容器,实例化出这样一个对象就产生了一个容器。
Server service = new Server() ;这样一来,Service对象就像一个没有门的宾馆:没有人能够进入并且使用,所以还是没有用的。
接下来的一行代码设置容器在localhost,端口7501监听。
service.addListener( “localhost:7501” ) ;为了在所有的interface上监听,不使用主机名(”addListener( “:7501″ )”)。
就像名字暗示的那样,你可以调用addListener()多次来在多个interface上监听。