XFire:开发WEB服务简易之道

来源:百度文库 编辑:神马文学网 时间:2024/03/29 23:12:50
Web服务
Web服务允许我们建立应用组件放置于网络上的分布式系统. 不管这些应用组件是怎么写的,使用什么语言写的,要运行在什么操作系统上, 我们都能以统一的方式访问这些组件.如果一个Web服务有效并且设计实现了互用性问题,那么无论你的应用是用什么语言,在什么平台上开发的,都可以使用这些服务.
为了实现平台无关,实现独立的访问Web服务, 业界制定了一系列技术标准,下面是一些最重要的技术:
* XML
* SOAP
* WSDL
下图展示了上述技术在工作环境中是如何使用的.

在这里,提供者是可以提供服务的应用组件, 申请者是需要使用服务的客户端程序. 很多其他技术也参与了这个交互过程,但是这里只显示了在Web服务环境中必不可少的核心组件.
XFire
XFire是一个免费的,开源的SOAP框架. 它不仅允许你轻松简易地实现这么一个环境.而且还提供了很多先进的特性.不错,你没有看错,"轻松简易". 本文中你将会看到用XFire构建Web服务是多么的简单.如果你的Web应用有一个Java类, 现在你希望这个类编程Web服务,用XFire完成这一工作你不必写一句代码.仅需操作一下部署描述器,你就会得到一个Web服务. 是的, 就是这么简单.让我们来看个例子.
一个简单的Java类
我的这个例子是一个位于Apache Tomcat 5.5.7主机运行在J2SE 1.4.2_07下的银行应用. 我假设你已经知道如何使用Java编写web应用并且已经配置了Tomcat服务器.我们的这个应用很简单,  只完成一项工作, 就是将钱从一个帐户转到另一个帐户.BankingService类中的transferFunds()为我们完成这一工作. 他需要4个传入参数
String fromAccount String toAccount double amount String currency
下面是代码:
package com.mybank.xfire.example;

import java.text.NumberFormat;
import java.text.DecimalFormat;

/** *//** XFire WebServices sample implementation class.
*/
public class BankingService implements IBankingService {

    //Default constructor.
    public BankingService(){
    }

    /** *//** Transfers fund from one account to another.
    */
    public String transferFunds(
        String fromAccount, String toAccount, double amount, String currency){

        String statusMessage = "";

        //Call business objects and other components to get the job done.
        //Then create a status message and return.
        try {
            NumberFormat formatter = new DecimalFormat("###,###,###,###.00");
            statusMessage = "COMPLETED: " + currency + " " + formatter.format(amount)+
            " was successfully transferred from A/C# " + fromAccount + " to A/C# " + toAccount;
        } catch (Exception e){
            statusMessage = "BankingService.transferFunds(): EXCEPTION: " + e.toString();
        }
        return statusMessage;
    }

}
在上面的代码中你看到奇怪的代码了吗? 大概没有吧. 除了那个公共的默认构造函数.这个构造函数是必不可少的,因为XFire要用他来实例这个类.
因为使用接口来完成是很好的实践,因此我们的类也实现了一个名叫IBankingService的接口.代码很简单:
package com.mybank.xfire.example;

public interface IBankingService {

    public String transferFunds(
        String fromAccount, String toAccount, double amount, String currency);

}

实际开发中,这个方法可能包含所有复杂的调用,请求和处理操作,但是我们的例子将其最小化以便我们能将精力集中到我们的目标上:将这个方法转换成Web服务.
你可以看到,我们的BankingService只不过是一个普通的Java类,没有任何代码说明它是否在Web服务中使用.这就对了!我们不需要写任何代码,所有工作都交给部署描述去处理.
后面我将介绍如何编写部署描述。
摘要:XFire本身就是基于Servlet的应用,因此我们需要向文件中添加一些必要的参照.那么我们就需要配置我们创建的Web服务.我们使用名叫services.xml的文件来完成配置。
Web应用的部署描述
在Java中,Web应用至少使用一个名叫web.xml的部署描述来部署. XFire本身就是基于Severlet的应用,因此我们需要向文件中添加一些必要的参照.那么我们就需要配置我们创建的Web服务.我们使用名叫services.xml的文件来完成配置.
web.xml
首先想让我们看一下web.xml.我们需要加上如下语句:    
XFireServlet
XFire Servlet
org.codehaus.xfire.transport.http.XfireConfigurableServlet



XFireServlet
/servlet/XFireServlet/*


XFireServlet
/services/*

services.xml
下面我们就要描述一下我们的Web服务都包含什么.这个工作在services.xml中完成.这个文件位于META-INF/xfire目录下,下面是基本的配置条目:


Banking
mybank
com.mybank.xfire.example.IBankingService
com.mybank.xfire.example.BankingService


让我们看看文件中的具体内容. 对Web服务的定义包含在元素内.元素下还有若干子元素.
第一个子元素是, 你可以提供任何有效的xml名字,这个名字会被客户端程序和服务器上的其他组件使用.例如,当服务器起来以后,你可以在浏览器上使用这个名称来查看WSDL.
下一个子元素是. 任何有效地xml名称都可以, 将作为你服务器的唯一标识变量使用.
元素包含Java类名用来指明方法的签名.在我们的这个例子中是IBankingService接口.如果你的Java类没有实现任何接口,那就填入类名.在你的Java类或接口中也许含有不知一个方法,只需要一个入口来将他们转换成Web服务.
元素记录实现接口的Java类名.这是一个可选元素.如果前一个元素填入的是接口,那么此处就要填入相应的实现类名.
至此,我们的Web服务配置工作就完成了.
XFire和其他库
现在,我们做最后一步工作--获得所有必要的库文件.我们怎么获得他们呢? 访问XFire官方网站http://xfire.codehaus.org/ 下载xfire-distribution-1.0.zip并解压到本地文件夹中.将下列文件拷贝到WEB-INF\lib:
activation-1.0.2.jar commons-codec-1.3.jar commons-httpclient-3.0.jar commons-logging-1.0.4.jar jaxen-1.1-beta-8.jar jdom-1.0.jar log4j-1.2.x.jar mail-1.3.3_01.jar spring-1.2.x.jar stax-api-1.0.jar wsdl4j-1.5.2.jar wstx-asl-2.9.jar xbean-2.1.0.jar xbean-spring-2.2.jar xfire-all-1.0.jar XmlSchema-1.0.jar
大功告成!让我们部署并启动应用.要部署这个例子,只需要将websvc.war复制到Apache Tomcat 环境的webapps目录下,等待几分钟,应用会自动启动. 例子的所有源代码也包含在这个war文件中(文件太大,我将其分卷压缩)part1 part2  part3 part4 part5.现在,我们的应用已经是一个Web服务了.
我们怎么知道Web服务有效?
我们来做一些测试,看看Web服务是否有效.
首先,我们先来看看WSDL是否有效。在浏览器中输入URL。哪个URL?因为我们的war文件名叫websvc.war,services.xml 中给出的servicenames是Banking, 那么WSDL URL为http://localhost:8080/websvc/services/Banking?wsdl。
请注意:URL的前一部分,例如:http://localhost:8080会根据你安装的应用服务不同而不同。如果你输入了URL,你将会看到以为根结点的xml文件。这个文件叫做web服务的WSDL.如果你看到了这个文件,那么初步验证你的Web服务有效。
但是这个验证还不够。有时候情况会复杂一些,你可以看到WSDL,但是客户端却无法访问Web服务。因此要真正检验Web服务是否真的好使,就要用客户端程序对Web服务作一次真正的调用。
摘要:在《XFire:开发Web服务的简易之道(二)》中最后提到过:要想检验Web服务是否有效,需要一个客户端程序实际调用一下这个Web服务。本章我们就来创建这样一个用于检验的客户端程序,验证一下我们前面的工作是不是真的有效。最后总结一下用XFire开发Web服务的步骤。
创建客户端程序
我们可以使用很多方法,任何SOAP工具来创建客户端程序,例如.Net或Apache Axis。我的这个例子中我是用一个名叫WsClient.java的Servlet中的动态代理。为了减少编码的代价,我将所有屏幕构建元素都放到doGet()方法中。对Web服务服务的实际调用在callWebService()方法中。代码很简单:
/**//* Call the Web service
    *
    */
    public String callWebService(
        String fromAccount, String toAccount, double amount, String currency)
        throws MalformedURLException, Exception {

        //Create a metadata of the service
        Service serviceModel = new ObjectServiceFactory().create(IBankingService.class);
        log.debug("callSoapServiceLocal(): got service model." );

        //Create a proxy for the deployed service
        XFire xfire = XFireFactory.newInstance().getXFire();
        XFireProxyFactory factory = new XFireProxyFactory(xfire);

        String serviceUrl = "http://localhost:8080/websvc/services/Banking";

        IBankingService client = null;
        try {
            client = (IBankingService) factory.create(serviceModel, serviceUrl);
        } catch (MalformedURLException e) {
            log.error("WsClient.callWebService(): EXCEPTION: " + e.toString());
        }

        //Invoke the service
        String serviceResponse = "";
        try {
            serviceResponse = client.transferFunds(fromAccount, toAccount, amount, currency);
       } catch (Exception e){
            log.error("WsClient.callWebService(): EXCEPTION: " + e.toString());
            serviceResponse = e.toString();
        }
        log.debug("WsClient.callWebService(): status=" + serviceResponse);

        //Return the response
        return serviceResponse;
    }
这段代码做了些什么?让我解释一下:首先我们创建了一个服务模型,里面包含了对服务的描述,换句话说,我们创建了服务的元数据。我们是用XFire的ObjectServiceFactory通过接口IBankingService.class创建了这个服务模型。
下一步就是获取XFire的代理对象。这一步中没有任何应用细节。通过proxyFactory,使用服务模型和服务终点URL(用于获得WSDL),我们获得了服务的本地代理。
这个代理就是实际的客户端。现在我们可以调用transferFunds()方法获得我们想要的Web服务了。
一旦这个例子部署成功并启动,就可以用下面的Servlet URL检验:
http://localhost:8080/websvc/ws
Servlet使用默认的参数访问Web服务并显示接收到的响应。你应该能看到下面两行信息
Response Received
COMPLETED: CDN$ 500.00 was successfully transferred from A/C# 11111-01234 to A/C# 99999-05678
现在你可以确信Web服务真的起来了并且工作正常。
你可以尝试传入不同的数据。你可以输入类似于下面的URL
http://localhost:8080/websvc/ws?from=11-2345&to=77-9876&amt=250.00&cur=EUR.
Web服务开发的基本步骤
下面列出了使用XFire开发Web服务的基本步骤:
1、检验Java类的方法和构造函数时公共的;
2、将XFire Servlet相关的入口添加到web.xml中;
3、创建services.xml并把它放到WEB-INF/classes/META-INF/xfire目录下;
4、将Xfire和其他第三方库添加到你的Web应用的WEB-INF/lib 目录下。
OK,这就是全部要做,就是这么简单。