`
longdick
  • 浏览: 584840 次
  • 性别: Icon_minigender_1
  • 来自: 0
社区版块
存档分类
最新评论
阅读更多

Jetty 是一个开源的servlet容器,它为基于Java的web内容,例如JSP和servlet提供运行环境。Jetty是使用Java语言编写的,它的API以一组JAR包的形式发布。开发人员可以将Jetty容器实例化成一个对象,可以迅速为一些独立运行(stand-alone)的Java应用提供网络和web连接。

本文包括以下内容:
1.        嵌入式Servlet容器有什么意义? 
2.        建立一个嵌入式的容器: 使用The Jetty API 
3.        将配置从代码中独立出来: XML驱动的配置文件 
4.        可执行的JAR包 
5.        结论 
6.        资源 


如果让一个人说出一种开源的servlet容器,可能他们会回答Apache Tomcat。但是,Tomcat并不是孤单的,我们还有Jetty。Jetty作为可选的servlet容器只是一个额外的功能,而它真正出名是因为它是作为一个可以嵌入到其他的Java代码中的servlet容器而设计的。这就是说,开发小组将Jetty作为一组Jar文件提供出来,因此你可以在你自己的代码中将servlet容器实例化成一个对象并且可以操纵这个容器对象。

Jetty在servlet容器中算不上一个新面孔;它从1998年就已经崭露头角。Jetty的发布遵循了Apache 2.0的开源协议,你可以在免费软件和商业软件中使用Jetty而不用支付版税。

在本文中,笔者将为你为何需要嵌入式servlet容器提出一点见解,解释Jetty API的基础,并且展示如何使用XML配置文件来将Jetty的代码精简到最少。

本文的示例代码是在Jetty5.1.10以及Sun JDK 1.5.0_03下测试的。

版权声明:任何获得Matrix授权的网站,转载时请务必保留以下作者信息和链接
作者:Ethan McCallum;shenpipi
原文:http://www.onjava.com/pub/a/onjava/2006/06/14/what-is-jetty.html
Matrix:http://www.matrix.org.cn/resource/article/44/44588_Jetty.html
关键字: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上监听。

注意到示例代码中维护了Server对象的一个引用,这是将来要停止容器需要用到的。
将一个web应用映射到Service是很直观的:
service.addWebApplication(
   "/someContextPath" ,
   "/path/to/some.war"
) ;


这个调用将处理一个web应用中的web.xml部署描述符(descriptor)来映射其中的过滤器servlet和servlet,就像其他容器所做的那样。第一个参数是context path,这个web应用的所有servlet和JSP都会被映射成相对于这个路径的URI。第二个参数是web应用本身。可以是一个打包的WAR文件或者目录格式的web应用。再次调用addWebApplication()可以用来添加其他的web应用。

注意到Jetty并不需要一个完整的符合规范的WAR文件来部署servlet。如果编写了一个搭载于HTTP协议的定制应用程序协议,你可以加载一个单一的servlet并且将其通过网络提供出去。并没有必要使用WAR文件仅仅为了使一个非web应用具有通过HTTP协议访问的功能。

为了映射这种一次性的servlet,通过在Service对象上调用getContext()动态的建立一个context。这个示例代码建立了一个叫做/embed的context。
ServletHttpContext ctx = (ServletHttpContext)
   service.getContext( "/embed" ) ;


如果context不存在地话,调用getContext()将会创建一个新的context
接下来,调用addServlet()将一个servlet类映射到一个URI
ctx.addServlet(
   "Simple" , // servlet name
   "/TryThis/*" , // URI mapping pattern
   "sample.SimpleServlet" // class name
) ;


第一个参数是该servlet的一个描述性的名字。第二个参数是要映射的路径,等同于web.xml servlet映射中的<url-pattern>。这个映射路径是相对于context path的,这里是/embed。”/*”表示这个servlet接收/embed/TryThis这样一个URI,同时它也会接收所有以此开头的URI,例如/embed/TryThis/123。在使用一个单一的servlet来作为一个大系统的入口的时候,这种映射方式非常有用。Struts和Axis就是实际应用中使用这样的映射方式的例子。
有时候你可能想让你的context成为root context,或者说“/”,这样更像一个普通的HTTP服务。Jetty通过Service.setRootWebapp()来支持此功能。
service.setRootWebapp(
   "/path/to/another.war"
) ;


唯一的一个参数是一个web应用的路径。
容器在此时还是不活动的。而且它也没有试图去绑定要监听的socket,启动容器需要调用:
service.start() ;


这个方法会立即返回,因为Jetty将服务在一个独立的线程中运行。因此,当容器运行的时候,main()可以来做其他任何事情。
其余的代码是使用一组URL来调用这个嵌入式容器。这些调用确保容器已经在运行并且servlet按照期望的方式工作。
关闭容器就像启动它一样直观
service.stop() ;


注意最外层try/catch块中的catch语句。
{

   service.start() ;
   // ... URL calls to mapped servlet ...
   service.stop() ;

}catch( Throwable t ){

   System.exit( 1 ) ;

}


显示的调用System.exit()确保容器在发生异常的时候被关闭。否则,容器会持续运行因此整个应用程序也不会退出。
必须记住Jetty web应用并不限于使用代码来访问。如果我将service.stop()从刚才的代码中去掉,那么容器将一直运行并且我可以在浏览器中调用servlet,例如
http://localhost:7501/embed/TryThis/SomeExtraInfo

你并不一定要完全按照我说的去做。这个示例代码可以作为一个Eclipse项目运行。而且你也可以写一段shell脚本使其运行在Unix/Linux命令行中。在上面两种情况下,确信Jetty在你的classpath中。

将配置从代码中独立出来: XML驱动的配置文件

尽管Jetty的API非常直观简练,但是直接的调用Jetty API会将大量的配置信息——端口号,context path,servlet类名——埋藏在代码之中。Jetty提供了一种基于XML的配置方式来替代直接调用API,这样你就可以将这些配置信息都放在代码外面而使你的代码保持清洁。

Jetty的XML配置文件是基于Java反射的。java.lang.reflect中的类代表了Java中的方法和类,这样你可以实例化一个对象并且使用方法的名字和参数类型来调用它的方法。这种情况下,Jetty的XML配置文件解析器会将XML的element和属性翻译成反射方法调用。

这段节选自Step2Driver示例类中的代码是Step1Driver的一个改良版本。要是使用到了配置文件,就必须有一定的Jetty代码来加载它。
URL serviceConfig = /* load XML file */ ;
   // can use an InputStream or URL

XmlConfiguration serverFactory =
   new XmlConfiguration( serviceConfig ) ;

                        
Server service =
   (Server) serverFactory.newInstance() ;


不可否认,这不比Step1Driver示例节省多少代码,但是,即使你要添加新的servlet或者web应用,Step2Driver的代码不会因此而增加。而直接调用Service和context对象的方法在配置逐渐增加的情况下会越来越差。
列表1是Step2Driver加载的XML文件。顶层的<Configure> element 的属性指明了要实例化那个类。这里是Jetty Server对象。
<!-- 1 -->
<Configure class="org.mortbay.jetty.Server">

  <!-- 2 -->
  <Call name="addListener">
    <Arg>
      <!-- 3 -->
      <New
         class="org.mortbay.http.SocketListener">

        <!-- 4 -->
        <Set name="Host">

          <!-- 5 -->
          <SystemProperty
             name="service.listen.host"
             default="localhost"
          />

        </Set>

        <Set name="Port">
          <SystemProperty
             name="service.listen.port"
             default="7501"
          />
        </Set>

      </New>
    </Arg>
  </Call>


  <Call name="getContext">

    <Arg>/embed</Arg>


    <!--
    call methods on the return value of
    Server.getContext()
    -->

    <!-- 6 -->
    <Call name="addServlet">

      <!-- servlet name -->
      <Arg>"Simple"</Arg>

      <!-- URL pattern -->
      <Arg>/TryThis/*</Arg>

      <!-- servlet class -->
      <Arg>sample.SimpleServlet</Arg>

    </Call>

  </Call>

</Configure>


<Call> element代表要在Server对象上调用的方法。这里要调用addListener(),如标记(2)处,它自己又有一个子element叫做<Arg>,这指明了方法的参数。这里我只能传递一个字符串值作为监听的地址,而addListener()却需要接受一个SocketListener对象作为参数。因此,我要使用<New>在标记(3)处实例化一个新的SocketListener对象。标记2和3处的代码等同于以下代码:
server.addListener(
   new SocketListener( ... )
) ;


为了配置SocketListener自己,必须使用一个<Call>来调用它的setHost()方法,既然这个方法遵循了JavaBean的命名规则,示例代码因此使用了<Set> element(4)作为一种快捷方式。在后台,Jetty给set中name属性所指定的属性赋值,并且决定调用什么方法,这里是setHost()

setHost()的参数这里没有显示给出,而是使用了<SystemProperty>来从系统属性中来获取参数的值,这里从系统参数service.listen.host 和 service.listen.port。如果系统属性没有定义,你可以使用default来指定一个默认值。这里,4和5等同于以下调用:
   socketListener.setHost(
      System.getProperty(
         "service.listen.host" ,
         "localhost"
      )
  ) ;


最后注意标记6处的<Call> element位于调用getContext方法的<Call>中。内部的<Call>是作用在外部的<Call>的返回的对象上的,这里,调用的是getServlet()返回的context上的addServlet()方法:
server.getContext().addServlet( ... ) ;


Jetty 小组的英明在于这个XML配置文件的进一步深入处理:我们可以注意到列表1中所有的Jetty特定的调用都是element和属性的值,而不是名字,这就意味着XML配置文件可以被用在任何类上,而不仅仅是Jetty的类中。根据你的应用程序的编写方式,你可以全部使用Jetty的XML配置文件来配置。

可执行JAR包

如果你使用Jetty的XML来配置你的应用,你需要使用大量的重复的代码来加载你的config文件并且运行你的应用。不过你可以使用Jetty的可执行的start.jar来为你加载文件,这会让你节省更多的代码。

例如,你可以使用以下的命令行来加载Step2Driver中的Jetty服务。
CLASSPATH= ...various Jetty JARs...
java \
   -Djetty.class.path=${CLASSPATH} \
   -jar <jetty install path>/start.jar \
   standalone.xml



注意到这个命令仅仅加载xml文件来建立容器和监听器,因此,它并不会调用示例代码中用来测试URL的代码。

结论
一个嵌入式的Jetty servlet容器可以让你的web使用Java应用而不用打包成正式的web应用的形式。这提供了多种可能性,让Jetty成为你的工具箱中的一个多才多艺的帮手。
当然,我这里所写的东西并不能包含Jetty的所有内容。我建议你去访问Jetty的网站来获取更多的文档和示例代码。

资源
---本文的示例代码
--The Jetty网站 上有文档,示例以及下载的链接。同时,它还包含了一个使用Jetty的项目的列表页。同样值得注意的是JettyPlus子项目,它提供了JNDI,数据源和其他servlet规范中的功能(特性)。 
--Sun's Java EE 网站, 其中包含了servlet规范的链接 
--Java Reflection in Action 详细讨论了Java的反射和自省API。 
--为了比较, OnJava同样发布一篇文章关于 Tomcat's embedded side. 
--本文中提到使用 Swing, XUI, and SWT 作为基于Java的GUI前端(frontend)应用程序 
--Message-Driven Bank 来自于另一篇文章, "J2EE Without the Application Server." 
Ethan McCallum 致力于 Unix/Linux, C++, 以及 Java的研究.

 

原帖url:http://www.matrix.org.cn/resource/article/2006-08-14/Jetty_44588.html

分享到:
评论

相关推荐

    jetty 6 指南书

    这本书不仅介绍了 Jetty 作为 Web 容器的基本功能,还深入探讨了其独特的特性和高级用法。 1. **Jetty 介绍** - **功能介绍**:Jetty 不仅是一个 HTTP 服务器,还是一个Servlet容器,支持WebSocket、HTTP/2等协议...

    Eclipse3 jetty插件

    2. **Jetty介绍** Jetty是由Mort Bay Consulting开发的开源Web服务器和Servlet容器。它的设计目标是轻量、快速且易于嵌入。Jetty可以直接嵌入到Java应用程序中,无需外部服务器进程,这使得它成为许多微服务和...

    jetty指南书

    1. **Jetty介绍**:Jetty是一个用Java语言编写的开源项目,它提供了执行JSP和servlet所需的环境。作为servlet容器,Jetty允许开发人员以对象的形式快速为独立的Java应用程序提供网络和web服务。Jetty的特点包括轻量...

    HelloWorld之jetty运行

    【Jetty介绍】 Jetty是一个轻量级的开源服务器和Servlet容器,它遵循Java Servlet规范,能够处理HTTP协议。由于其嵌入式特性和高效性能,Jetty常被用于开发快速原型、微服务和云应用。在Java社区中,Jetty因其小巧、...

    CXF+Jetty发布WebService

    二、Jetty介绍 Jetty是一款高性能、小巧的HTTP服务器和Servlet容器,它的设计目标是快速、轻量且易于集成。由于其小巧的体积和优秀的性能,Jetty常被嵌入到Java应用程序中,为Web服务提供运行环境。 三、CXF+Jetty...

    Android代码-i-jetty开源项目.zip

    **一、Jetty介绍** `Jetty`是一款高效且可嵌入的Java Web服务器和Servlet容器,广泛应用于各种Web应用程序和框架,如Spring Boot。它的设计目标是轻量级、快速以及易于集成。在Android平台上,由于内存和CPU资源有限...

    Android端i-jetty服务器开发(一)[参照].pdf

    1. **i-jetty介绍** i-jetty允许用户在Android手机上运行Web应用,这使得用户可以利用移动设备来提供个人Web服务。通过i-jetty,开发者可以构建与Android API交互的Web应用,这样不仅能够将手机上的信息(如联系人...

    jetty-6.1.26.zip

    以下是一些关于Jetty 6.1.26及其核心知识点的详细介绍: 1. **Servlet容器**:Jetty作为Servlet容器,能够解析HTTP请求并将其转发给相应的Servlet进行处理。它支持Servlet 2.5规范,这使得开发者可以使用当时最新的...

    maven集成jetty所需jar包maven-jetty-plugin,多版本

    本文将详细讨论如何将Jetty与Maven进行集成,并介绍关键的`maven-jetty-plugin`插件及其不同版本。 1. Maven与Jetty集成的意义: Maven通过其强大的依赖管理功能,使得项目构建变得简单和规范。而Jetty作为轻量级...

    jetty在eclipse中配置

    本教程将详细介绍如何在Eclipse中配置Jetty,以便于便捷地调试和运行Web应用。 首先,确保你已经安装了Eclipse IDE和Jetty服务器。你可以从Jetty官网下载适合你Java版本的Jetty发布包,并解压到本地文件系统。 1. ...

    jetty9.4.11+jetty在idea上的配置教程

    首先,我们需要解决Jetty资源下载慢的问题,然后详细介绍在IDEA中配置Jetty的步骤。 **解决Jetty资源下载慢的问题:** 由于Jetty的官方下载站点可能对国内用户访问速度较慢,我们可以选择从国内的镜像站点或者第三...

    Jetty 学习资料汇总

    3. **安装与配置**:介绍如何下载Jetty,设置环境变量,以及配置Jetty启动参数。 4. **Jetty与Maven集成**:讲解如何在Maven项目中添加Jetty插件,实现快速的本地开发服务器。 二、Jetty核心概念 1. **Servlet**...

    idea的jetty-runner1.2.1插件

    **一、Jetty 服务器介绍** Jetty 是一个开源的 HTTP 服务器和 Java Servlet 容器,它轻量级、快速且易于配置。由于其对标准的遵循和广泛的社区支持,Jetty 成为了许多开发者选择的服务器平台,尤其在开发和测试环境...

    jetty启动器资源配置文件

    本文主要介绍Jetty的启动配置文件——`jetty.xml`的基本结构与关键配置项。 #### 二、文件格式与结构 `jetty.xml`遵循XML文档的标准格式,包含声明、DTD定义、注释以及具体的配置节点等部分。 ##### 2.1 XML文档...

    Jetty配置支持https

    本文将详细介绍如何在Jetty中配置HTTPS,并生成受信的网站证书。 #### 二、Jetty HTTPS配置步骤 ##### 1. 生成证书 第一步是生成一个自签名证书。这可以通过JDK自带的`keytool`工具完成。 **命令行操作:** ```...

    jetty6 指南书

    Jetty6 指南书是一本专注于介绍Jetty 6版本的详尽教程,旨在为读者提供关于这个轻量级、高效的Web服务器和Servlet容器的深入理解。Jetty不仅是一个标准的Web容器,它的灵活性和可嵌入性使得它在许多不同的应用场景中...

    jetty修改js不用重启项目的方法

    本文将详细介绍如何在Jetty环境中配置,使得修改js文件时无需重启项目即可生效。 1. **查找Jetty Maven包**: 首先,你需要找到Jetty的Maven包,这个通常位于用户的`.m2`仓库目录下。例如,在Windows系统中,路径...

    eclipse jetty插件安装(离线版)

    本篇文章将详细讲解如何离线安装Eclipse Jetty插件,并介绍其基本使用方法。 首先,离线安装Eclipse Jetty插件的过程相对简单。你需要先下载一个包含插件的压缩包,如"jetty-plugin"。这个压缩包通常包含了所有必要...

    Jetty权威指南.pdf

    **1.1 Jetty功能介绍** Jetty是一个完全由Java编写的高性能HTTP服务器及servlet容器,它不仅能够作为一个独立的服务运行,还具备强大的可嵌入性。Jetty的设计模块化、组件化,能够很好地集成到其他应用中。它支持...

    jetty软件包升级版本

    本篇将详细介绍如何进行Jetty软件包的升级过程,并探讨新版本11.0.12所带来的变化和改进。 首先,让我们了解Jetty的版本管理。Jetty遵循语义版本(Semantic Versioning),其格式为`主版本号.次版本号.修订版本号`...

Global site tag (gtag.js) - Google Analytics