分享

XFire:开发WEB服务简易之道

 shaobin0604@163.com 2006-09-17
Web服务
Web服务允许我们建立应用组件放置于网络上的分布式系统. 不管这些应用组件是怎么写的,使用什么语言写的,要运行在什么操作系统上, 我们都能以统一的方式访问这些组件.如果一个Web服务有效并且设计实现了互用性问题,那么无论你的应用是用什么语言,在什么平台上开发的,都可以使用这些服务. 

 为了实现平台无关,实现独立的访问Web服务, 业界制定了一系列技术标准,下面是一些最重要的技术:
 * XML
 * SOAP
 * WSDL
下图展示了上述技术在工作环境中是如何使用的.
jw-0501-xfire.jpg
在这里,提供者是可以提供服务的应用组件, 申请者是需要使用服务的客户端程序. 很多其他技术也参与了这个交互过程,但是这里只显示了在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个传入参数
  1. String fromAccount
  2. String toAccount
  3. double amount
  4. 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.我们需要加上如下语句:
    <servlet>
        <servlet-name>XFireServlet</servlet-name>
        <display-name>XFire Servlet</display-name>
        <servlet-class>org.codehaus.xfire.transport.http.XfireConfigurableServlet
         </servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>XFireServlet</servlet-name>
        <url-pattern>/servlet/XFireServlet/*</url-pattern>
    </servlet-mapping>
    
    <servlet-mapping>
        <servlet-name>XFireServlet</servlet-name>
        <url-pattern>/services/*</url-pattern>
    </servlet-mapping>

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

<beans xmlns="http://xfire./config/1.0">
  
  <service>
    <name>Banking</name>
    <namespace>mybank</namespace>
    <serviceClass>com.mybank.xfire.example.IBankingService</serviceClass>
    <implementationClass>com.mybank.xfire.example.BankingService</implementationClass>
  </service>  
  
</beans>

让我们看看文件中的具体内容. 对Web服务的定义包含在<service>元素内.<service>元素下还有若干子元素.
第一个子元素是<name>, 你可以提供任何有效的xml名字,这个名字会被客户端程序和服务器上的其他组件使用.例如,当服务器起来以后,你可以在浏览器上使用这个名称来查看WSDL.
下一个子元素是<namespace>. 任何有效地xml名称都可以, <namespace>将作为你服务器的唯一标识变量使用.
<serviceClass>元素包含Java类名用来指明方法的签名.在我们的这个例子中是IBankingService接口.如果你的Java类没有实现任何接口,那就填入类名.在你的Java类或接口中也许含有不知一个方法,只需要一个入口来将他们转换成Web服务.
<implementationClass>元素记录实现接口的Java类名.这是一个可选元素.如果前一个元素<serviceClass>填入的是接口,那么此处就要填入相应的实现类名.
至此,我们的Web服务配置工作就完成了.

XFire和其他库
现在,我们做最后一步工作--获得所有必要的库文件.我们怎么获得他们呢? 访问XFire官方网站
http://xfire./ 下载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,你将会看到以<wsdl:definitions>为根结点的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,这就是全部要做,就是这么简单。

    • 本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
      转藏 分享 献花(0

      0条评论

      发表

      请遵守用户 评论公约

      类似文章 更多