Web Service概述
什么是Web Service
Web Service是能够基于网络,尤其是基于万维网(World Wide Web)直接调用的能够处理离散任务或连续任务的软件模型。目前较为流行的应用是,由一家公司对其专有数据进行封装,提供Web Service,然后其它公司就可以通过Internet来动态使用这些在线服务。这为未来全球的电子商务发展提供了新的标准和架构。
Web Service架构
Web Service是独立的、模块化的应用,能够通过因特网来描述、发布、定位以及调用。在Web Service的体系架构中包括三个角色:服务提供者(Service Provider)、服务请求者(Service Requestor)、服务注册器(Service Registry)。角色间主要有三个操作:发布(Publish)、查找(Find)、绑定(Bind)。
下图清楚的描述了三种角色,以及角色之间的作用关系。
图示一:
图示二:
这个流程图显示了Web Services中的核心技术是如何工作的。
这里,Provider是提供服务的应用程序组件,Requester是使用服务的客户端程序。很多其他技术也会参与到交互中,但是这个图只显示了在Web Services环境中必需的核心技术组件。
Web Service协议标准
简单对象访问协议(SOAP)
SOAP是Simple Object Access Protocol的缩写,是一种基于XML的不依赖传输协议的表示层协议,用来在分散或分布式的应用程序之间方便地以对象的形式交换数据。在SOAP的下层,可以是HTTP/HTTP,也可以是SMTP/POP3,还可以是为一些应用而专门设计的特殊的通信协议。
SOAP包括三个主要部分:
² SOAP封装结构:定义了一个整体框架,以表示消息中包含什么内容,谁来处理这些内容以及这些内容是可选的或是必需的。
² SOAP编码规则:定义了用以交换应用程序定义的数据类型的实例的一系列机制。
² SOAP RPC表示:定义了一个用来表示远程过程调用和应答的协定。
Web Service描述语言(WSDL)
WSDL是Web Service Des cription Language的缩写,该语言将网络服务定义成一个能交换消息的通信端点集,为分布式系统提供了帮助文档,同时也可作为自动实现应用间通信的解决方案。
统一描述、发现和集成协议(UDDI)
UDDI是一套基于Web的、分布式的、为Web Service提供的、信息注册中心的实现标准规范,同时也包含一组使企业能将自身提供的Web Service注册,以使别的企业能够发现的访问协议的实现标准。
以上概念转自http://www.itlove.net/Article/203/207/2005/2005082532541.html
XFire
XFire是一个免费的开源SOAP框架,它不仅可以极大方便地实现这样一个环境,并且可以提供许多Web Services规范中高级特征,这些特征在多数的商业或者开源工具都没有提供。http://xfire.codehaus.org/Download是它的官方网站下载区,同时你也可以了解关于它的更多内容。
创建过程示例
下面我们就来使用Java构建一个WebService并且构建一个客户端来测试访问它。
首先请确保你的JDK和Tomcat在Eclipse环境中是可用的,配置方法不做赘述。并且你了解一些java编程技术和tomcat的发布常识。
版本信息:MyEclipse6.0.0M1;Tomcat6.0;JDK1.5;Xfire1.2
1、打开MyEclipse新建一个WebService Project,为你的项目命名,我选择了Java EE5.0,项目在你的WorkSpace目录下。下一步:看到了这个界面
在这里Eclipse为你创建了webService的配置文件services.xml(主意文件名是有“s”的),并进行了Xfire的Servlet基本配置告诉项目你使用了Xfire改信息将体现在项目的web.xml文件中。继续下一步,加载Xfire相关的jar包,你看到了
在这个项目里我勾选了Xfire1.2 Core Libraries;HTTP Client Libraries;XML Beans Libraries。主要是确保引入了这些包包:
• ? 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
如果你好奇其他的包包是做什么用的就有待于我们在今后的学习中继续探究了~点击“Finish”完成了项目创建。目录结构如下图所示:
打开web.xml我们可以看到如下片断:
xml 代码
1. <servlet>
2. <servlet-name>XFireServlet</servlet-name>
3. <servlet-class>org.codehaus.xfire.transport.http.XFireConfigurableServlet</servlet-class>
4. <load-on-startup>0</load-on-startup>
5. </servlet>
6. <servlet-mapping>
7. <servlet-name>XFireServlet</servlet-name>
8. <url-pattern>/services/*</url-pattern>
9. </servlet-mapping>
10. <welcome-file-list>
11. <welcome-file>index.jsp</welcome-file>
12. </welcome-file-list>
13.
接下来的工作是开始编写java类接下来我们要写一个服务端java类。模拟应用是一个银行转账应用,从账户A转账到账户B并需要给出金额和货币种类。我们先来实现一个接口IBankingService.java代码全文如下:
java 代码
1. package com.mybank.xfire.example;
2.
3. public interface IBankingService {
4.
5. public String transferFunds(
6. String fromAccount, String toAccount, double amount, String currency);
7.
8. }
9.
然后编写一个普通的Java类BankingService包含了一个叫做transferFunds()的方法来为我们完成这项工作。它需要四个输入参数:
• 1、 String fromAccount
• 2、 String toAccount
• 3、 double amount
• 4、 String currency
代码如下:
java 代码
1. package com.mybank.xfire.example;
2.
3. import java.text.NumberFormat;
4. import java.text.DecimalFormat;
5.
6. public class BankingService implements IBankingService {
7.
8. //Default constructor.
9. public BankingService(){
10. }
11.
12. /** Transfers fund from one account to another.
13. */
14. public String transferFunds(
15. String fromAccount, String toAccount, double amount, String currency){
16.
17. String statusMessage = "";
18.
19. //调用业务逻辑执行操作.
20. //建立并返回状态信息.
21. try {
22. NumberFormat formatter = new DecimalFormat("###,###,###,###.00");
23. statusMessage = "COMPLETED: " + currency + " " + formatter.format(amount)+
24. " was successfully transferred from A/C# " + fromAccount + " to A/C# " + toAccount;
25. } catch (Exception e){
26. statusMessage = "BankingService.transferFunds(): EXCEPTION: " + e.toString();
27. }
28. return statusMessage;
29. }
30.
31. }
32.
你可以看到BankingService是一个普通的Java类,没有任何代码告诉我们它将会在Web Services中使用。只是要有默认的构造函数,类型是public。这是必须的。否则,XFire不能够初始化这个类。好的,这里我们不需要增加任何东西。我们所有的工作都在部署描述符里完成。
Web应用的部署描述符
在Java中,Web应用程序通常需要至少一个部署描述符(叫做web.xml)对其进行配置。XFire本身是一个基于servlet的应用程序。因此,我们需要增加必要的引用到描述符文件中。然后我们还必须配置将要创建的Web Services。我们使用一个称为services.xml的新文件来完成这件事。在使用Eclipse工具构建工程的时候我们已经完成了这项配置(参见(上)文)。
services.xml
现在我们不得不说一下我们的Web Services的由什么组成的了。这由一个叫做services.xml的文件完成,当这个项目在tomcat发布后,它存放在WEB-INF/classes/META-INF/xfire目录下,它在Web应用程序的标准类路径中。而在Eclipse环境中我们可以清除的看到Eclipse已经为我们把它清楚的列在项目路径中。这里是services.xml中的基本配置条目:
xml 代码
1. <beans xmlns="http://xfire.codehaus.org/config/1.0">
2.
3. <service>
4. <name>Banking</name>
5. <namespace>mybank</namespace>
6. <serviceClass>com.mybank.xfire.example.IBankingService</serviceClass>
7. <implementationClass>com.mybank.xfire.example.BankingService</implementationClass>
8. </service>
9.
10. </beans>
Web Services的定义包含在元素中,它还含有一些子元素。
第一个子元素是Banking,它可以是你提供任何的合法名字。这将会被客户端程序和其它需要定位你的服务的组件用到。例如,在服务准备好以后,你将在浏览器上使用这个名字来查看WSDL。
下一个子元素是。任何合法的XML名字都是可以的。用来唯一标识你的服务的各个参数。(注释@)
注释@:Namespace派什么用?namespace的作用是要避免命名冲突。如果我建立一项Web
Service,其中的WSDL文件包含一个名为"foo"的元素,而你想要使用我的服务与另一项服务连接作为补充,这样的话另一项服务的WSDL文件就不能包含名为"foo"的元素。两个服务器程序只有在它们在两个事例中表示完全相同的东西时,才可以取相同的名字。如果有了表示区别的namespace,我的网络服务里的"foo"就可以表示完全不同于另一个网络服务里"foo"的含义。在你的客户端里,你只要加以限制就可以引用我的"foo"。
元素包含了Java类的名字,它指定了方法签名。在我们的例子中,它是接口IBankingService。如果Java类没有实现任何接口,你就需要把类的名字放在这里。在你的Java类或者接口中可能有几个方法。只需要一个入口把它们全部发布为Web Services。
保存了实现方法的Java类名。这是一个可选元素。如果上一个元素包含了一个接口,那么相应的实现类必须在这里指定。
就是这样。我们的Web Services配置完成了。
我们如何知道Web Service正在工作呢?
为了了解Web Service是否正在工作,我们需要测试。首先,我们测试来看WSDL是否可用。我们在浏览器中输入URL。哪个URL?因为我们的应用程序的war文件是aa.war,并且在services.xml中给出的服务名是Banking,WSDL的URL应该是:http://localhost:8080/aa/services/Banking?wsdl。
请注意:URL的第一部分,例如,http://localhost:8080,可能会根据你的应用服务器不同而不同。无论怎样,当你输入URL后,将会看到一个XML文档,这个文档叫做服务的WSDL。如果你看到了,这就是你的应用作为Web Service已经可用的第一个证明。
正确的执行情况:
在这个WSDL中我们可以看到<xsd:element name="transferFunds">的服务方法明以及他的四个参数描述等信息。但是这个测试是不够的。可能会发生这种情况,可以看到WSDL,但是从客户端程序可能会访问不到服务。因此为了核实服务是否可以访问了,我们必须使用一个客户端进行服务的实际调用来进行一个真正的测试。
开发一个客户端
编写BankClient.java
java 代码
1. package com.mybank.xfire.client;
2.
3. import java.net.MalformedURLException;
4. import org.codehaus.xfire.XFire;
5. import org.codehaus.xfire.XFireFactory;
6. import org.codehaus.xfire.client.XFireProxyFactory;
7. import org.codehaus.xfire.service.Service;
8. import org.codehaus.xfire.service.binding.ObjectServiceFactory;
9.
10. import com.mybank.xfire.example.IBankingService;
11. /**
12. * @author AdminiDD
13. *
14. */
15. public class BankClient {
16.
17. /**
18. * @param args
19. */
20. public static void main(String[] args) {
21. // TODO Auto-generated method stub
22.
23. }
24. /* Call the Web service
25. *
26. */
27. public String callWebService(
28. String fromAccount, String toAccount, double amount, String currency)
29. throws MalformedURLException, Exception {
30.
31. //Create a metadata of the service 创建一个service的元数据
32. Service serviceModel = new ObjectServiceFactory().create(IBankingService.class);
33. System.out.println("callSoapServiceLocal(): got service model." );
34.
35. //Create a proxy for the deployed service 为XFire获得一个代理工厂对象
36. XFire xfire = XFireFactory.newInstance().getXFire();
37. XFireProxyFactory factory = new XFireProxyFactory(xfire);
38. //得到一个服务的本地代理
39. String serviceUrl = "http://127.0.0.1:8080/wstest/services/Banking";
40.
41. IBankingService client = null;
42. try {
43. client = (IBankingService) factory.create(serviceModel, serviceUrl);
44. } catch (MalformedURLException e) {
45. System.out.println("WsClient.callWebService(): EXCEPTION: " + e.toString());
46. }
47.
48. //Invoke the service 调用服务 返回状态结果信息
49. String serviceResponse = "";
50. try {
51. serviceResponse = client.transferFunds(fromAccount, toAccount, amount, currency);
52. } catch (Exception e){
53. System.out.println("WsClient.callWebService(): EXCEPTION: " + e.toString());
54. serviceResponse = e.toString();
55. }
56. System.out.println("WsClient.callWebService(): status=" + serviceResponse);
57.
58. //Return the response
59. return serviceResponse;
60. }
61.
62. }
63.
编写两个JSP页来模拟请求和响应
index.jsp;发送请求
&13;&10;">&13;&10;">
java 代码
1.
2.
3.
4. "-//W3C//DTD HTML 4.01 Transitional//EN">
5.
6.
7. "">
8.
9.
10. "pragma" content="no-cache">
11. "cache-control" content="no-cache">
12. "expires" content="0">
13. "keywords" content="keyword1,keyword2,keyword3">
14. "description" content="This is my page">
15.
16.
17.
18.
19.
Welcomle to WebService!
20.
________________________________________
21. Bank test : give my money to you!
22. "form1" action="say.jsp" method="POST">
23. your account ID:"toAcc" type="text"/>
24. How much do you want:"amount" type="text" />
25. "center">"submit" value="提交">
26.
27.
28.
29.
say.jsp,接收请求并返回响应结果
java 代码
1.
2.
3.
4.
5. "-//W3C//DTD HTML 4.01 Transitional//EN">
6.
7.
8. "">
9.
10.
11.
12. "pragma" content="no-cache">
13. "cache-control" content="no-cache">
14. "expires" content="0">
15. "keywords" content="keyword1,keyword2,keyword3">
16. "description" content="This is my page">
17.
18.
19.
20.
21.
22.
Welcomle to WebService!
23.
________________________________________
24. Message from WebService:
25.
26.
27.
项目aa编译完毕并发布到Tomcat上,启动Tomcat测试开始!访问http://127.0.0.1:8080/aa/index.jsp
执行效果:
添上你的账户,想要多少钱就写多少钱,嘿嘿 提交!请求转发到say.jsp如果你看到下面的情况:
恭喜你!成功啦~ 可以看到有 RMB$ 1,000.00 从affman(a fit foolish man~)的账户转到了liudan的账户上!
总结:
基本的Web Services开发步骤清单
这个清单总结了将一个Java方法发布为Web Service所必须的步骤:
o 1、 检查Java类的方法和默认构造函数确保为public
o 2、 增加XFire servlet相关条目到web.xml中
o 3、 创建services.xml,把它放到WEB-INF/classes/META-INF/xfire目录下
o 4、 增加XFire和第三方包到你的Web应用的WEB-INF/lib文件夹中
嗯~确实不复杂!
以上步骤均经过亲自测试执行,如有勘误请至mail to:
[email protected] 欢迎指教和共同探讨
以下相关讨论(转自原文http://www.360doc.com/showweb/0/0/516946.aspx)
XFire的其他高级特性
XFire的使用可能比较简单,但是在特性和功能性上,它却占据着领导者的位置。下面是它的高级特性:
o ---本地数据绑定支持POJOs(plain-old Java objects)、XMLBeans、JAXB(Java Architecture for XML Binding)、Castor等等。数据绑定说明了Web Services的XML请求和映射到Java对象的XML响应。
o ---使用StAX(Streaming API for XML)处理XML文档。同DOM的基于树和SAX的事件驱动的处理方式相比,StAX使用了拉(pull)机制,它使处理更快速,内存效率更高。
o ---支持多种传输协议,如HTTP、JMS(Java Message Service)和JVM内部传输。
o ---嵌入式,这是XFire的核心功能之一。你可以把这个SOAP引擎嵌入到你的应用中,完全隐藏所有XFire特定引用,同样所有配置都是程序驱动。
o ---丰富的API,它使XFire可高度自定义,允许开发者在不同的阶段截获请求,并且对他们进行处理。
o ---兼容最新的标准例如SOAP1.1(没有加密远程工程调用,或者RPC)和1.2、WSDL1.1、the Web Services Interoperability Organization’s Basic Profile 1.0、Web Services Addressing和WS-Security。
最重要的是,XFire属于新一代Web Services引擎。不仅仅是营销用语,“新一代”有一些重要的意义。Apache Axis是第一代Java语言的Web Services引擎,已经成为了所有后来工具的参考标准。在过去的几年里,Axis以及这些其它的工具已经在很多生产环境中进行了实地测试。从中得出的一个关键的问题就是Web Services并不最适合RPC类型的通信。对于性能和效率,面向文档的消息形式是最好的方式。但是Apache Axis和很多其他的Web Services引擎都被设计成了面向RPC的(尽管它们支持文档形式)。现在,整个行业正在开发新一代的SOAP引擎,设计为面向文档的。Apache已经宣布结束旧版本的Axis引擎开发,现在专注于Axis2,现在它的预发布版本是0.95。XFire在今年的2月份发布了它的第一个产品版本(1.0)。它的下一个版本(1.1)仅仅在几个星期之后就进行了发布。
局限性
XFire有些重要的局限性你应该清楚:
o ---开发Web Services的好的实践是从WSDL开始。大部分的SOAP引擎提供了从WSDL生成服务stub的工具。XFire也提供了这样一个工具。但是它是基于注释(annotations-based)的,因此需要J2SE5.0。对于仍坚持使用J2SE1.4.x的人来说,它不是一个令人拍手叫好的工具,因为我们有很多其他方式来编写客户端,一个就是文章中演示的方式。
o ---附件支持,它将会包含在未来发行的版本中。
o ---易于学习的用户向导。XFire团队在这个方面还有很多工作需要做。
结论
Java当前的趋势是简化技术的使用。因此,我们正看到一波基于POJO的开发成就。同时,面向服务架构(SOA,Services-oriented architecture)和Web Services已经变成了当前行业的热点话题。XFire正是在这种情况下产生的。它能够使POJO发布为最少的Web Services,而只需要付出最小化的努力。从而,它使希望使用这项技术的初级开发者的学习曲线变得平缓。同时,由于它兼容最新标准和提供了丰富的API,XFire为高级用户提供了更多的大好机会。