在应用程序中嵌入HTTP服务引擎

红薯 发布于 2008/10/05 17:21
阅读 1K+
收藏 3

不久前我的一篇文章《在应用程序中嵌入数据库功能》发表在IBM的developerWorks网站上,有很多读者来信表示了对题目的极大兴趣以及 探讨相关的一些细节。那篇文章介绍的是通过嵌入数据库的服务来简化应用程序的发布过程,而我们今天的题目跟它有点相似,不同的只是数据库服务变成了 HTTP服务,嵌入的目的也不相同,嵌入数据库服务是应用程序发布的一个过渡,它简化了发布的过程,而嵌入HTTP服务则是为了给应用程序提供一个方便易 用的管理界面。什么意思呢?假设我们有这样一个应用程序,它是以服务的形式或者是后台守护进程的方式运行,作为服务程序当然要尽量保证服务的不间断。但是 我们可能经常要调整应用程序的运行时参数,很多人可能会把这些参数写到一个配置文件中,然后在应用程序中定时去检测文件是否更改,如果文件更改则重新加载 配置以达到修改运行时参数的目的。但是这样的做法有很多弊病,由于配置文件一般和应用程序在同一台机器,所以修改时必须登录到应用程序所在的机器;另外由 于配置文件隐晦难懂,除了开发者自己外其他人很难懂;同时由于配置文件只是一个数据文件,脱离程序自身的逻辑使二者难以无缝结合。采用嵌入HTTP服务引 擎的方式提供一个基于WEB的配置管理界面就可以很好的解决这些问题:我们可以使用浏览器远程访问管理界面;可以开发向导式的配置界面来简化应用的管理; 因为采用嵌入到应用程序的方式,所以HTTP的服务引擎和应用程序在同一个进程,使二者可以紧密的结合,例如可以访问应用中的一些全局变量等。

       好了,既然我们已经决定要在我们的应用程序中嵌入HTTP服务引擎用以提供基于WEB的配置管理界面,那我们还需要注意什么问题呢?其实最大的问题在于 HTTP服务引擎的选型上,我们不需要它的功能特别强大、但至少要稳定,不至于因为它的一些错误把应用程序本身整垮;另外要支持动态的页面,因为我们讲的 是JAVA的程序,所以我们希望这个引擎要支持JSP或者Servlet,才能便于与应用程序本身进行无缝的结合;最后一个需要注意的是这个引擎要尽量的 小,不能喧宾夺主,因为配置管理只是应用程序中的一小部分,如果嵌入的引擎本身比整个应用程序还大会让人觉得不伦不类,比如在你的程序中嵌入Tomcat 仅仅是为了提供管理界面,这都不知道到底是谁嵌入谁了,得不偿失!

       Jetty就是一个非常适合用于嵌入的HTTP服务引擎,它是一个轻量级、高性能和可靠性、可嵌入的、可扩展的HTTP服务器。当然,我们还关心它的功 能,Jetty支持JSP和Servlet。有这两样就已经足够应付开发一般的管理界面了。由于下载的Jetty的压缩包解压后目录不少,并且文件也都不 小,为了避免第一次使用Jetty的读者感到茫然,我们将开发一个DEMO程序并将Jetty嵌入其中,同时整理出Jetty运行的最小集,也就是把不必 要的文件滤去以减小文件的大小。

Jetty的体系结构

       Jetty不仅是一个HTTP服务器且是一个遵循标准(Servlet 2.3)的Servlet容器。下图是Jetty的主要类结构图。其中类org.mortbay.http.HttpServer提供了HTTP服务的核 心,而org.mortbay.jetty.Server扩展HttpServer来实现对XML配置信息以及小服务程序Servlet的支持。

也就是说如果你只需要支持静态页面那么就执行org.mortbay.http.HttpServer,如果需要支持JSP或者Servlet那就 要使用org.mortbay.jetty.Server,在这里我们需要的是第二个类,因为只有动态的页面才对我们有用。

Jetty的运行结构及其所需的环境

       通过对Jetty的测试和提炼发现,如果仅仅是需要一个支持JSP和Servlet的引擎,那么我们完全可以抛弃Jetty压缩包中的大部分文件。下面我 们针对两种不同的应用:只支持静态页面以及支持动态JSP页面,分别给出其所需要的最小运行环境。 

1.  只支持静态页面的HTTP Server

该应用仅仅需要两个jar文件:org.mortbay.jetty.jar来自jetty压缩包中的lib目 录;javax.servlet.jar来自SUN或者jetty压缩包中的lib目录。有了这两个文件即可运行一个HTTP服务器。由于Jetty把当 前目录当成页面的根目录,因此我采用以下的目录结构来运行一个简单的HTTP Server:

httpd\    服务所在目录
\httpd\lib   库文件目录,存放jetty.jar以及servlet.jar
\httpd\html   存放静态页面的目录
 
转到html目录下使用如下启动HTTP Server的命令,执行完毕后可以通过浏览器访问本机的8080端口即可列出html目录下的所有文件,或者直接可以访问到某个html文件或者其他二 进制文件。

java –Djava.ext.dirs=..\lib org.mortbay.http.HttpServer 8080

所需库文件大小加起来不超过700K,达到我们前面提出的“小”的要求!

2.  支持JSP/Servlet的服务引擎

我们前面提到过,支持小服务程序的容器类org.mortbay.jetty.Server是从HttpServer类继承过来的,在HTTP服务 的基础上提供了对JSP以及Servlet的支持。在JSP的处理上Jetty使用的是Jakarta的Jasper项目(Tomcat也是使用该项目进 行JSP的处理的,可靠性可想而知),因此需要Jasper项目的库文件以及一个用于发布页面的库分别是:

jasper-compiler.jar  用于编译JSP文件的库
jasper-runtime.jar  用于执行JSP的库
ant.jar  用于执行自动编译和发布的库
 
同样的需要把这三个库文件加到我们刚才的httpd\lib目录下。小服务引擎和Http服务不仅仅是 增加几个库文件,它还需要很多的参数信息,Jetty把这些参数信息放入到一个XML文件中,这个文件可以直接从Jetty的压缩包中etc目录下的 jetty.xml文件复制过来做一些小改动即可,关于这个配置文件中各项参数的意思我们接下来的如何开发基于Jetty的页面程序再详细介绍。接下来需 要建两个目录,一个是logs目录用来存放访问日志文件的,另外一个是webapps目录用来存放web应用程序,这两个目录名都可以通过 jetty.xml来修改。为了验证服务是否正常运行,我们先创建一个最简单的只有一个测试页面的应用,在webapps目录下建目录test,然后在 test目录下新建JSP文件hello.jsp内容如下:

<%@ page language="java" contentType="text/html;charset=GBK"%>
你好,Jetty

下面先来预览一下我们的目录结构看你是否设置正确:

现在可以启动并测试一个最简化的Jetty的服务了,在如上图所示的JETTY目录下执行:

java -Djava.ext.dirs=lib org.mortbay.jetty.Server jetty.xml

运行结果如下图所示:

然后就可以使用浏览器来测试一下运行的情况,地址是:http://liudong:8080/test/hello.jsp , 浏览器就会有 你好,Jetty的输出。因为Jetty需要处理xml配置信息,建议使用JDK1.4,否则你可能会收到很多类找不到的异常信息,当然你可以把xml处 理的库文件拷贝到lib目录下。

       再来看看现在我们提取出来的Jetty目录的大小:1.6兆,其中有一半以上是用来处理JSP文件的。这个大小应该也是令我们满意的。

如何开发基于Jetty的页面程序

       “啊,这个都要讲,不是说符合J2EE的Web应用程序标准嘛?难道Jetty有什么不同吗?” 呵呵,没错,Jetty跟其他的小服务容器没有什么不同,但是这都是Jetty自己说的,为了保险起见我们还是需要验证一下,另外Jetty的一些配置以 及如何发布我们自己的应用还是需要了解一下。

       首先来看看配置方面,Jetty把所有的配置信息都集中在jetty.xml中,我们可以修改该文件来达到修改服务引擎所运行的端口、web应用程序所在 的目录以及其他的一些配置。最重要的还是web应用程序所在的目录,Jetty默认的目录是当前目录下的webapps目录。找到jetty.xml中的 下面这段即可根据自己的需要来修改文档的主目录。

 

<Set name="rootWebApp">root</Set>
  <Call name="addWebApplications">
    <Arg></Arg>
    <Arg><SystemProperty name="jetty.home" default="."/>/webapps/</Arg>
    <Arg>org/mortbay/jetty/servlet/webdefault.xml</Arg>
    <Arg type="boolean">true</Arg>
  </Call>

根据默认的设置,我们只需要把web应用程序的目录直接拷贝到webapps目录下,或者将war文件拷贝到该目录让Jetty自动发布,不过当发 布一个新的应用时需要重新启动Jetty。

       如果发布已经没问题了,那么我们可以来验证Jetty是否支持标准的web应用程序。最简单的办法及时拷贝一个在Tomcat下运行很好的web应用到 Jetty的webapps目录,我测试的是一个基于struts框架开发的开放源码的页面菜单项目struts-menu,经过测试你不会发现跟它在 Tomcat下运行有什么两样。放心开发你的应用吧。

简单嵌入Jetty的源码

       前面我们都是在介绍Jetty这个项目以及如何在它之上开发应用程序,这好像跟我们的题目相背离,真的吗?当然不是,前面的内容为了就是验证Jetty是 否适合嵌入到我们的应用程序中,而真正的嵌入则是非常的简单,可以说两三行代码就可以完成的事情。人类不也是经常耗费很长的时间来验证一个看似简单的结论 吗?虽然是简单我们还是给一个例子用来嵌入Jetty服务。

package lius.jetty.demo;

import org.mortbay.jetty.Server;
/**
 * 用于嵌入Jetty的简单例子
 * @author Liudong
 */
public class HttpService {
    public static void main(String[] args) {
        Server.main(new String[] {"jetty.xml"});
    }
}

天啊,这种程序我实在拿不出手啊!J

不过这只是一个启动Jetty服务的最简单的例子,这样使得Jetty和我们自己的程序运行在同一个进程内,互相访问已经是没有问题了,至于如何实 现管理功能那是你自己的事了。

其他注意事项

1.  Jetty目前还不支持类更新重新加载
2.  Jetty将编译JSP文件所生成的java文件以及class文件放置到系统临时目录中一个与web应用名称对应的目录,例如C:\Temp \Jetty__8080__struts-menu下,这个目录的内容会在Jetty关闭并重新启动成功后清除,也就是说Jetty每重新启动一次所有 的web应用程序在被访问之前都要重新编译一次。

参考资料

Jetty首页                                  http://jetty.mortbay.org
在 SourceForge.net的地址              http://sourceforge.net/project/jetty

加载中
返回顶部
顶部