摘要:XFire是一个免费的开源SOAP框架Q它不仅可以极大方便地实现这样一个环境,q且可以提供许多Web Services规范中高U特征,q些特征在多数的商业或者开源工具都没有提供。你要恰当的理解q些单词Qgreat ease and simplicityQ非常轻村֒单)。你会看到使用XFire创徏Web Services是多么的单?br />
你的POJOҎ发布为Web Services
摘要
问一?Net的开发者,开发Web Services有多困难Q他们会被你的问题逗乐Q他们会告诉你所有步骤花费的旉不会过一分钟。再问一下Java开发者,q气好的话你会碰C面的回答Q一般情况下Q你会得C个完全不同的{案。从Web Services引入到Java中至今已l?q了Q然而它仍然被认为是一门较新的技术,一个主要的原因是使用Java实现Web Services太困难了。现在,随着C代Web Services引擎XFire的发布,q种情况会发生明显的变化。用XFireQ你可以把JavacL法发布ؓWeb Services而不需要编写额外的代码。在q篇文章中,你将会看到XFire使Web Services开发变得多么容易和单?br />
Web Services使我们能够在|络上徏立分布式pȝQ应用程序组件可以通过Mq_、Q何语a和Q何方式访问。无论应用程序如何开发,使用了什么语aQ以及运行在什么操作系l^CQ只要它作ؓWeb ServiceQƈ且ؓ协同解决问题而设计,那么你的应用E序Q以M语言开发或在Q何^CQ都可以利用它的服务。这是Web Service的主要概c?br />
Z实现Web Services的^台无x和实现讉K独立性,软g行业需要遵循一些作为标准的技术。其中一些包括:
---XMLQ在Web Services环境中各层之间进行传递的默认数据格式?br />-- -SOAPQ封装和交换信息的默认协议。第一ơ被提出Ӟ它是只取Simple Object Access ProtocolQ简单对象访问协议)的首字母。但是现在SOAP更多被认为是一个特定的名词Q以它自p命名,同样很多是用词不当:SOAP实际上不是用来访问对象的。另外,它也不再单?br />---WSDLQWeb Services Description LanguageQWeb Services描述语言Q:描述Web Services的语a。尽基于XMLq且可以被h理解QWSDL主要是由机器处理Q由客户端程序读取和理解?br />
下面的高U层ơ图表,ZWWW协会发布的“Web Services Architecture”(Web Services架构Q文,昄了这些技术在实际的工作环境中是如何发挥作用:

q个程图显CZWeb Services中的核心技术是如何工作的?br />
q里QProvider是提供服务的应用E序lgQRequester是用服务的客户端程序。很多其他技术也会参与到交互中,但是q个囑֏昄了在Web Services环境中必需的核心技术组件?br />
XFire 是一个免费的开源SOAP框架Q它不仅可以极大方便地实现这样一个环境,q且可以提供许多Web Services规范中高U特征,q些特征在多数的商业或者开源工具都没有提供。你要恰当的理解q些单词Qgreat ease and simplicityQ非常轻村֒单)。你会看到使用XFire创徏Web Services是多么的单?br />
假如你的Web应用有一个Javac,q且你想把它的一个方法发布ؓWeb ServicesQ当使用XFireӞ你不需要编写一行额外的Java代码。只需要编辑发布描q符Q然后你׃得到一个Web Services。是的,它相当地单。我们来看一个例子?br />
一个简单的Javac?/span>
我们的例子是一个银行业应用E序Q服务器是运行在J2SE1.4.2_07下的Apache Tomcat5.5.7。假定你已经了解如何使用Java~写Web应用E序Qƈ知道应该如何把它部v到Apache Tomcat服务器上。我们的Web应用E序非常单;它只做一件事——将资金从一个̎戯{到另外一个̎户上。一个普通的Javac?BankingService包含了一个叫做transferFunds()的方法来为我们完成这工作。它需要四个输入参敎ͼ
1、 String fromAccount
2、 String toAccount
3、 double amount
4、 String currency
代码如下Q?br />
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;
}
}
在这里你看到了什么异常的东西了吗Q或许没有,除了默认的构造函敎ͼcd是public。这是必ȝ。否则,XFire不能够初始化q个cR?br />
因ؓ使用接口的设计是一个好的实践,所以我们的JavacM实现了一个称为IBankingService的接口。代码十分简单:
package com.mybank.xfire.example;


public interface IBankingService
{

public String transferFunds(
String fromAccount, String toAccount, double amount, String currency);
}
在实际实CQ这样一个方法可能包括各U类型的复杂调用、查询和处理操作。但是我们的CZ代码已经最化了,以至于我们可以集中精力在主要目标上:把这个方法发布ؓWeb Services?br />
你可以看到BankingService是一个普通的Javac,没有M代码告诉我们它将会在Web Services中用。好的,q里我们不需要增加Q何东ѝ我们所有的工作都在部v描述W里完成?br />
Web应用的部|描q符
在Java 中,Web应用E序通常需要至一个部|描q符Q叫做web.xmlQ对其进行配|。XFire本n是一个基于servlet的应用程序。因此,我们需要增加必要的引用到描q符文g中。然后我们还必须配置要创徏的Web Services。我们用一个称为services.xml的新文g来完成这件事?br />
web.xml
首先Q修改web.xml。我们需要增加下面的XFire servlet相关的条目:
<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的由什么组成的了。这׃个叫做services.xml的文件完成,它存攑֜META-INF/xfire目录下,而这整个目录攑֜ WEB-INF/classes文g夹中Q它在Web应用E序的标准类路径中。这里是services.xml中的基本配置条目Q?br />
<beans xmlns="http://xfire.codehaus.org/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>
让我们看看这里都包含了什么内宏VWeb Services的定义包含在<service>元素中,它还含有一些子元素。第一个子元素?lt;name>Q它可以是你提供M的合法名字。这会被客LE序和其它需要定位你的服务的lg用到。例如,在服务准备好以后Q你在览器上使用q个名字来查看WSDL?br />
下一个子元素?lt;namespace>。Q何合法的XML名字都是可以的?lt;namespace>用来唯一标识你的服务的各个参数?br />< serviceClass>元素包含了Javacȝ名字Q它指定了方法签名。在我们的例子中Q它是接口IBankingService。如?JavacL有实CQ何接口,你就需要把cȝ名字攑֜q里。在你的JavacL者接口中可能有几个方法。只需要一个入口把它们全部发布为Web Services?br />
<implementationClass>保存了实现方法的Javacd。这是一个可选元素。如果上一个元?lt;serviceClass>包含了一个接口,那么相应的实现类必须在这里指定?br />
是q样。我们的Web Services配置完成了?br />
XFire和其它类?/span>
现在是最后一步了Q需要得到所有必需的类库。我们怎样得到它们呢?去XFire|站Q下载xfire-distribution-1.0.zipQ然后解压到一个本地文件夹。复制下面的jar文g和它的库文g夹到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
一切妥当。我们来部v和启动应用程序。ؓ了部|示例应用,只需要复制websvc.war到Apache Tomcat的webapps文g夹中Q再{待几秒钟。它会自动启动。这个应用的全部源代码也包含在这个war文g中。我们的E序已经准备作ؓ一?Web Service了?br />
我们如何知道Web Service正在工作呢?
Z了解Web Service是否正在工作Q我们需要测试。首先,我们试来看WSDL是否可用。我们在览器中输入URL。哪个URLQ因为我们的应用E序的war文g是websvc.warQƈ且在services.xml中给出的服务名是BankingQWSDL的URL应该是:http: //localhost:8080/websvc/services/Banking?wsdl?br />
h意:URL的第一部分Q例如, http://localhost:8080Q可能会Ҏ你的应用服务器不同而不同。无论怎样Q当你输入URL后,会看到一个XML文档Q它的根元素?<wsdl:definitions>。这个文档叫做服务的WSDL。如果你看到了,q就是你的应用作为Web Service已经可用的第一个证明?br />
但是q个试是不够的。可能会发生q种情况Q可以看到WSDLQ但是从客户端程序可能会讉K不到服务。因此ؓ了核实服务是否可以访问了Q我们必M用一个客Lq行服务的实际调用来q行一个真正的试?br />
开发一个客L
你可以用Q何的SOAP工具创徏客户端,例如Q?Net或者Apache AxisQ有很多U方法:使用从WSDL产生的stubsQ用动态代理,{等。在例子中,我们使用一个动态代理,以一个简单的Servlet形式Q叫?WsClient.java。ؓ了保持代码两最,所有在屏幕昄的元素都攑֜了doGet()Ҏ中。对Web Service的实际调用由callWebService()Ҏ完成Q它相当地简单。和下面的类|

/**//* 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;
}
q个代码是如何工作的呢?我来解释一下:首先Q我们创Z个服务模型,它包含服务的说明——换句话_是服务的元数据。我们用XFire的ObjectServiceFactory从IBankingService.class接口创徏q个模型?br />
接着QؓXFire获得一个代理工厂对象,它包含了常规的代码,也相当地单和易懂。这一步中没有M特定应用的东ѝ从q个proxyFactoryQ用服务模型和服务端点URLQ用来获得WSDLQ,我们可以得到一个服务的本地代理?br />
是它了。这个代理就是实际的客户端。现在,我们可以调用它的transferFunds()Ҏ来得到我们需要的Web Service?br />一旦示例应用发布ƈ启动Q就可以试servlet URLQ?br />http://localhost:8080/websvc/ws?br />
q个Servlet使用默认参数来调用Web Service和显C接收到的响应。页面的最后两行应该读取:
Response Received
COMPLETED: CDN$ 500.00 was successfully transferred from A/C# 11111-01234 to A/C# 99999-05678
现在你可以确定Web Service已经发布q且在运行中了?br />
Z试不同的输入|你可以用完整的URLQ例如:
http://localhost:8080/websvc/ws?from=11-2345&to=77-9876&amt=250.00&cur=EUR?br />
基本的Web Services开发步骤清?/span>
q个清单ȝ了将一个JavaҎ发布为Web Service所必须的步骤:
1、 检查JavacȝҎ和默认构造函数确保ؓpublic
2、 增加XFire servlet相关条目到web.xml?br />3、 创建services.xmlQ把它放到WEB-INF/classes/META-INF/xfire目录?br />4、 增加XFire和第三方包到你的Web应用的WEB-INF/lib文g夹中
q就是所有需要的步骤Q是的,相当单?br />
XFire的其他高U特?/span>
XFire的用可能比较简单,但是在特性和功能性上Q它却占据着领导者的位置。下面是它的高Ҏ:
-- -本地数据l定支持POJOsQplain-old Java objectsQ、XMLBeans、JAXBQJava Architecture for XML BindingQ、Castor{等。数据绑定说明了Web Services的XMLh和映到Java对象的XML响应?br />---使用StAXQStreaming API for XMLQ处理XML文档。同DOM的基于树和SAX的事仉动的处理方式相比QStAX使用了拉QpullQ机Ӟ它处理更快速,内存效率更高?br />---支持多种传输协议Q如HTTP、JMSQJava Message ServiceQ和JVM内部传输?br />---嵌入式,q是XFire的核心功能之一。你可以把这个SOAP引擎嵌入C的应用中Q完全隐藏所有XFire特定引用Q同h有配|都是程序驱动?br />---丰富的APIQ它使XFire可高度自定义Q允许开发者在不同的阶D|莯求,q且对他们进行处理?br />-- -兼容最新的标准例如SOAP1.1Q没有加密远E工E调用,或者RPCQ和1.2、WSDL1.1、the Web Services Interoperability Organization’s Basic Profile 1.0、Web Services Addressing和WS-Security?br />
最重要的是QXFire属于C代Web Services引擎。不仅仅是营销用语Q“新一代”有一些重要的意义。Apache Axis是第一代Java语言的Web Services引擎Q已l成Z所有后来工L参考标准。在q去的几q里QAxis以及q些其它的工具已l在很多生环境中进行了实地试。从中得出的一个关键的问题是Web Servicesq不最适合RPCcd的通信。对于性能和效率,面向文的消息Ş式是最好的方式。但是Apache Axis和很多其他的Web Services引擎都被设计成了面向RPC的(管它们支持文形式Q。现在,整个行业正在开发新一代的SOAP引擎Q设计ؓ面向文的。Apache 已经宣布l束旧版本的Axis引擎开发,现在专注于Axis2Q现在它的预发布版本?.95。XFire在今q的2月䆾发布了它的第一个品版本(1.0Q。它的下一个版本(1.1Q仅仅在几个星期之后p行了发布?br />
性能
Web Services需要消耗很多资源,但是性能斚w它们不是那么引h注目。XFire打破了这U趋ѝ它消耗更的内存Q部分因?StAX的用)Q但是表现却比多数可比较的SOAP引擎。你可以在资源中提供的链接中看到比较的结果?br />此外QXFireq提供了各种Ҏ来进一步优化性能。一个方法是使用JVM内置传输Qin-JVM transportQ。如果你知道Web Services和客Lq行在同一个JVM上,你可以选择使用本地传输Q它可以大幅提升性能。在CZ中的客户端代码,看以下指定服务端点URL的这行:
String serviceUrl = "http://localhost:8080/websvc/services/Banking";
替换?br />String serviceUrl = "xfire.local://Banking";
你会看到性能上的明显提高Q因为它l过了整个网l层?br />
局限?/span>
XFire有些重要的局限性你应该清楚Q?br />-- -开发Web Services的好的实跉|从WSDL开始。大部分的SOAP引擎提供了从WSDL生成服务stub的工兗XFire也提供了q样一个工兗但是它是基于注释(annotations-basedQ的Q因此需要J2SE5.0。对于仍坚持使用J2SE1.4.x的h来说Q它不是一个o人拍手叫好的工具Q因为我们有很多其他方式来编写客LQ一个就是文章中演示的方式?br />---附g支持Q它会包含在未来发行的版本中?br />---易于学习的用户向对{XFire团队在这个方面还有很多工作需要做?br />
l论
Java 当前的趋势是化技术的使用。因此,我们正看C波基于POJO的开发成。同Ӟ面向服务架构QSOAQServices-oriented architectureQ和Web Services已经变成了当前行业的热点话题。XFire正是在这U情况下产生的。它能够使POJO发布为最的Web ServicesQ而只需要付出最化的努力。从而,它希望使用q项技术的初开发者的学习曲线变得q缓。同Ӟ׃它兼Ҏ新标准和提供了丰富的 APIQXFire为高U用h供了更多的大好机会?br />
关于作?/b>
Shahid Ahmed是一个Y件架构师Q如今在国一家主要的无线q行商作咨询工作。他?2q前开始开发YӞ当时Kaypro、Osborne、Apple II和TRS-80sl治着整个地球。在q去?q里Q他更多的精力集中于Java。他现在的工作包括SOA、Web Services、消息、POJO、Spring、Ajax{等。Shahid是一个Y件热衯,每天都在奋斗以求在技术的qh和社会生zȝ热爱之间Lq炏V?br />
资源Q?/b>
Matrix JavaC:http://www.matrix.org.cn
下蝲本文中的CZ应用Q?a target="_new">http://www.javaworld.com/javaworld/jw-05-2006/xfire/jw-0501-xfire.zip
Web Services架构:http://www.w3.org/TR/ws-arch/
WSDL2.0Q原来提议ؓWSDL1.2Q现在重新命名了Q:W一部分Q核心语aQW3C Candidate Recommendation 27 March 2006Q?br />
引自:http://www.matrix.org.cn/resource/article/2006-09-24/XFire_6bd1061c-4bc6-11db-978f-43b3336b7e51.html

]]>