欢迎来到天天文库
浏览记录
ID:6079596
大小:527.75 KB
页数:23页
时间:2018-01-02
《web service入门教程》由会员上传分享,免费在线阅读,更多相关内容在教育资源-天天文库。
WebService概述 WebService的定义 W3C组织对其的定义如下,它是一个软件系统,为了支持跨网络的机器间相互操作交互而设计。WebService服务通常被定义为一组模块化的API,它们可以通过网络进行调用,来执行远程系统的请求服务。 这里我们从一个程序员的视角来观察webservice。在传统的程序编码中,存在这各种的函数方法调用。通常,我们知道一个程序模块M中的方法A,向其发出调用请求,并传入A方法需要的参数P,方法A执行完毕后,返回处理结果R。这种函数或方法调用通常发生在同一台机器上的同一程序语言环境下。现在的我们需要一种能够在不同计算机间的不同语言编写的应用程序系统中,通过网络通讯实现函数和方法调用的能力,而Webservice正是应这种需求而诞生的。 最普遍的一种说法就是,WebService=SOAP+HTTP+WSDL。其中,SOAPSimpleObjectAccessProtocol)协议是webservice的主体,它通过HTTP或者SMTP等应用层协议进行通讯,自身使用XML文件来描述程序的函数方法和参数信息,从而完成不同主机的异构系统间的计算服务处理。这里的WSDL(WebServicesDescriptionLanguage)web服务描述语言也是一个XML文档,它通过HTTP向公众发布,公告客户端程序关于某个具体的Webservice服务的URL信息、方法的命名,参数,返回值等。 下面,我们先来熟悉一下SOAP协议,看看它是如何描述程序中的函数方法、参数及结果对象的。 SOAP协议简介 什么是SOAP SOAP指简单对象访问协议,它是一种基于XML的消息通讯格式,用于网络上,不同平台,不同语言的应用程序间的通讯。可自定义,易于扩展。一条SOAP消息就是一个普通的XML文档,包含下列元素: Envelope元素,标识XML文档一条SOAP消息 Header元素,包含头部信息的XML标签 Body元素,包含所有的调用和响应的主体信息的标签 Fault元素,错误信息标签。 以上的元素都在SOAP的命名空间http://www.w3.org/2001/12/soap-envelope中声明; SOAP的语法规则 SOAP消息必须用XML来编码 SOAP消息必须使用SOAPEnvelope命名空间 SOAP消息必须使用SOAPEncoding命名空间 SOAP消息不能包含DTD引用 SOAP消息不能包含XML处理指令 SOAP消息的基本结构XML/HTML代码1. xml version="1.0"?> 2. 5. 6. ... 7. ... 8. 9. 10. ... 11. ... 12. 13. ... 14. ... 15. 16. 17. SOAPEnvelope元素 Envelope元素是SOAP消息的根元素。它指明XML文档是一个SOAP消息。它的属性xmlns:soap的值必须是http://www.w3.org/2001/12/soap-envelope。 encodingStyle属性,语法:soap:encodingStyle="URI" encodingStyle属性用于定义文档中使用的数据类型。此属性可出现在任何SOAP元素中,并会被应用到元素的内容及元素的所有子元素上。 XML/HTML代码1. xml version="1.0"?> 2. 5. ... 6. Message information goes here 7. ... 8. SOAPHeader元素 actor属性,语法soap:actor="URI" 通过沿着消息路径经过不同的端点,SOAP消息可从某个发送者传播到某个接收者。并非SOAP消息的所有部分均打算传送到SOAP消息的最终端点,不过,另一个方面,也许打算传送给消息路径上的一个或多个端点。SOAP的actor属性可被用于将Header元素寻址到一个特定的端点。 mustUnderstand属性,语法soap:mustUnderstand="0|1" SOAP的mustUnderstand属性可用于标识标题项对于要对其进行处理的接收者来说是强制的还是可选的。假如您向Header元素的某个子元素添加了"mustUnderstand="1",则要求处理此头部的接收者必须认可此元素。XML/HTML代码1. xml version="1.0"?> 2. 5. 6.234 2. 3.... 4.... 5. SOAPBody元素 必需的SOAPBody元素可包含打算传送到消息最终端点的实际SOAP消息。Body元素中既可以包含SOAP定义的命名空间中的元素,如Fault,也可以是用户的应用程序自定义的元素。以下是一个用户定义的请求:XML/HTML代码1. xml version="1.0"?> 2. 5. 6. 7. Apples 8. 9. 10. 上面的例子请求苹果的价格。请注意,上面的m:GetPrice和Item元素是应用程序专用的元素。它们并不是SOAP标准的一部分。而对应的SOAP响应应该类似这样: SOAPFault元素 Fault元素表示SOAP的错误消息。它必须是Body元素的子元素,且在一条SOAP消息中,Fault元素只能出现一次。Fault元素拥有下列子元素: 常用的SOAPFaultCodes HTTP协议中的SOAP实例 下面的例子中,一个GetStockPrice请求被发送到了服务器。此请求有一个StockName参数,而在响应中则会返回一个Price参数。此功能的命名空间被定义在此地址中:"http://www.jsoso.net/stock" SOAP请求:(注意HTTP的Head属性)XML/HTML代码1.POST /InStock HTTP/1.1 2.Host: www.jsoso.net 3.Content-Type: application/soap+xml; charset=utf-8 4.Content-Length: XXX 5. 6. xml version="1.0"?> 7. 2. 3. 4. IBM 5. 6. 7. SOAP响应:(注意HTTP的Head属性)XML/HTML代码1.HTTP/1.1 200 OK 2.Content-Type: application/soap+xml; charset=utf-8 3.Content-Length: XXX 4. 5. xml version="1.0"?> 6. 9. 10. 11. 34.5 12. 13. 14. HTTP协议中的SOAPRPC工作流程 WSDL简介 介绍过了SOAP,让我们关注WebService中另外一个重要的组成WSDL。 WSDL的主要文档元素 WSDL文档可以分为两部分。顶部分由抽象定义组成,而底部分则由具体描述组成。抽象部分以独立于平台和语言的方式定义SOAP消息,它们并不包含任何随机器或语言而变的元素。这就定义了一系列服务,截然不同的应用都可以实现。具体部分,如数据的序列化则归入底部分,因为它包含具体的定义。在上述的文档元素中,、、属于抽象定义层,、属于具体定义层。所有的抽象可以是单独存在于别的文件中,也可以从主文档中导入。 WSDL文档的结构实例解析 下面我们将通过一个实际的WSDL文档例子来详细说明各标签的作用及关系。XML/HTML代码1. 2. 9. 1. 2. 3. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 1. 2. 3. 4. 5. 6. 9. 10. 11. 12. 14. 15. 16. 18. 19. 20. 21. 22. 23. 25. 26. 27. 29. 30. 31. 32. 33. 1. 2. 3. 4. 5. 6. 7. 8. 由于上面的事例XML较长,我们将其逐段分解讲解 WSDL文档的根元素:<definitions>XML/HTML代码1. 8.…… 9.…… 10. <definitions>定义了文档中用到的各个xml元素的namespace缩写,也界定了本文档自己的targetNamespace="http://www.jsoso.com/wstest",这意味着其它的XML要引用当前XML中的元素时,要声明这个namespace。注意xmlns:tns="http://www.jsoso.com/wstest"这个声明,它标示了使用tns这个前缀指向自身的命名空间。 引用 WSDL文档数据类型定义元素:XML/HTML代码1. 2. 3. 3. 4. 标签定义了当前的WSDL文档用到的数据类型。要说明的是,为了最大程度的平台中立性,WSDL使用XMLSchema语法来定义数据类型。这些数据类型用来定义webservice方法的参数和返回指。对于通用的原生数据类型如:integer,boolean,char,float等,在W3C的标准文档http://www.w3.org/2001/XMLSchema中已经做了定义。这里我们要引入的schema定义schemaLocation="http://localhost:8080/hello?xsd=1"是我们自定义的Java对象类型。 WSDL文档消息体定义元素:XML/HTML代码1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. <message>元素定义了web service函数的参数。<message>元素中的每个<part>子元素都和某个参数相符。输入参数在<message>元素中定义,与输出参数相隔离,输出参数有自己的<message>元素。兼作输入、输出的参数在输入输出的<message>元素中有它们相应的<part>元素。输出<message>元素以"Response"结尾,对Java而言方法得返回值就对应一个输出的<message>。每个<part>元素都有名字和类型属性,就像函数的参数有参数名和参数类型。 在上面的文档中有两个输入参数、两个输出参数和一个错误参数(对应Java中的Exception)。 输入参数<message>的name属性分别命名为toSayHello,sayHello。 toSayHello对应输入参数userName,参数类型为xsd:string,在Java语言中就是String; sayHello对应两个输入参数person和arg1,类型为tns:person和xsd:string。这里tns:person类型就是引用了标签中的类型定义。 输出参数<message>的name属性分别命名为toSayHelloResponse和sayHelloResponse。 这个名称和输入参数的<message>标签name属性对应,在其后面加上Response尾缀。 toSayHelloResponse对应的返回值是returnWord,参数类型为xsd:string; sayHelloResponse对应的返回值是personList,参数类型为tns:personArray(自定义类型); 错误参数<message>的name属性为HelloException。 它的子标签element而不是type来定义类型。 以上的message标签的name属性通常使用webservice函数方法名作为参照,错误参数标签则使用异常类名为参照。标签中的参数名称,即part子元素的name属性是可自定义的(下一章节详细说明)。message标签的参数类型将引用types标签的定义。 WSDL文档函数体定义元素:XML/HTML代码1. 2. 3. 4. 5. 1. 2. 3. 4. 5. 6. 元素是最重要的WSDL元素。它可描述一个webservice、可被执行的操作,以及相关的消息。portType的name属性对应Java中的一个服务类的类名。元素使用其子元素描述一个webservice的服务方法。 在元素中,name属性表示服务方法名,parameterOrder属性表示方法的参数顺序,使用空格符分割多个参数,如:“parameterOrder="personarg1”。元素的子标签表示输入参数说明,它引用<message>标签中的输入参数。表示输出参数说明,它引用<message>标签中的输出参数。标签在Java方法中的特别用来表示异常(其它语言有对应的错误处理机制),它引用<message>标签中的错误参数。 WSDL绑定实现定义元素:XML/HTML代码1. 2. 5. 6. 7. 8. 10. 11. 12. 14. 15. 16. 1. 2. 3. 5. 6. 7. 9. 10. 11. 12. 13. 14. 标签是完整描述协议、序列化和编码的地方,,和标签处理抽象的数据内容,而标签是处理数据传输的物理实现。 标签把前三部分的抽象定义具体化。 首先标签使用的transport和style属性定义了WebService的通讯协议HTTP和SOAP的请求风格RPC。其次子标签将portType中定义的operation同SOAP的请求绑定,定义了操作名称soapAction,输出输入参数和异常的编码方式及命名空间。 WSDL服务地址绑定元素:XML/HTML代码1. 2. 3. 4. 5. service是一套<port>元素。在一一对应形式下,每个<port>元素都和一个location关联。如果同一个<binding>有多个<port>元素与之关联,可以使用额外的URL地址作为替换。 一个WSDL文档中可以有多个<service>元素,而且多个<service>元素十分有用,其中之一就是可以根据目标URL来组织端口。在一个WSDL文档中,<service>的name属性用来区分不同的service。在同一个service中,不同端口,使用端口的"name"属性区分。 这一章节,我们简单的描述了WSDL对SOAP协议的支持,以及在WebService中的作用。在接下来的章节中,我们将学习如何使用Java6.0的Annotation标签来定义和生成对应的WSDL。 JavaSE6.0下的WebService 从JavaSE6.0开始,Java引入了对WebService的原生支持。我们只需要简单的使用Java的Annotation标签即可将标准的Java方法发布成WebService。 但不是所有的Java类都可以发布成WebService。Java类若要成为一个实现了WebService的bean,它需要遵循下边这些原则: 这个类必须是public类 这些类不能是final的或者abstract 这个类必须有一个公共的默认构造函数 这个类绝对不能有finalize()方法 下面我们将通过一个具体的JavaWebService代码例子,配合上述的WSDL文件,讲述如何编写JavaSE6.0的原生WebService应用。 完整的JavaWebService类代码Java代码1.package org.jsoso.jws.server; 2. 3.import java.util.ArrayList; 4.import javax.jws.WebMethod; 5.import javax.jws.WebParam; 6.import javax.jws.WebResult; 7.import javax.jws.WebService; 8.import javax.jws.WebParam.Mode; 1.import javax.jws.soap.SOAPBinding; 2./ 3. * 提供WebService服务的类 4. */ 5.@WebService(name="Example", targetNamespace="http://www.jsoso.com/wstest", serviceName="Example") 6.@SOAPBinding(style=SOAPBinding.Style.RPC) 7.public class Example { 8. private ArrayList persons = new ArrayList();; 9. /** 10. * 11. * 返回一个字符串 12. * @param userName 13. * @return 14. */ 15. @WebMethod(operationName="toSayHello",action="sayHello",exclude=false) 16. @WebResult(name="returnWord")//自定义该方法返回值在WSDL中相关的描述 17. public String sayHello(@WebParam(name="userName")String userName) { 18. return "Hello:" + userName; 19. } 20. 21. /** 22. * web services 方法的返回值与参数的类型不能为接口 23. * @param person 24. * @return 25. * @throws HelloException 26. */ 27. @WebMethod(operationName="sayHello", action="sayHello") 28. @WebResult(partName="personList") 29. public Person[] sayHello(@WebParam(partName="person", mode=Mode.IN)Person person, 30. String userName) throws HelloException { 1. if (person == null || person.getName() == null) { 2. throw new HelloException("说hello出错,对像为空。。"); 3. } 4. System.out.println(person.getName() + " 对 " + userName + " 说:Hello,我今年" + person.getAge() + "岁"); 5. persons.add(person); 6. return persons.toArray(new Person[0]); 7. } 8.} Annotation1@WebService(name="Example",targetNamespace="http://www.jsoso.com/wstest",serviceName="Example") @WebService标签主要将类暴露为WebService,其中targetNamespace属性定义了自己的命名空间,serviceName则定义了标签和标签的name属性。 Annotation2:@SOAPBinding(style=SOAPBinding.Style.RPC) @SOAPBinding标签定义了WSDL文档中SOAP的消息协议,其中style属性对应SOAP的文档类型,可选的有RPC和DOCUMENT Annotation3:@WebMethod(operationName="toSayHello",action="sayHello",exclude=false) @WebMethod定义WebService运作的方法, 属性action对应操作的活动,如 属性operationName匹配的wsdl:operation的名称,如 属性exclude用于阻止将某一继承方法公开为web服务,默认为false Annotation4:@WebResult(name="returnWord") @WebResult定义方法返回值得名称,如 Annotation5:@WebParam(partName="person",mode=Mode.IN @WebParam定义方法的参数名称,如,其中mode属性表示参数的流向,可选值有IN/OUT/INOUT 这里要着重说明的是,上述WebService类的sayHello方法中,带有HelloException这个异常声明,造成该服务类不能直接发布成WebService。需要使用wsgen工具为其生存异常Bean。关于wsgen工具的使用,请参考wsgen与wsimport命令说明 发布一个的JavaWebService 在完成了上述的WebServiceAnnotation注释后,我们使用wsgen工具为其进行服务资源文件的构造(这里主要是生成一个名为org.jsoso.jws.server.jaxws.HelloExceptionBean的异常bean类),最后使用以下的类发布Web服务:Java代码1.package org.jsoso.jws.server; 2. 3.import java.util.LinkedList; 4.import java.util.List; 5.import javax.xml.ws.Binding; 6.import javax.xml.ws.Endpoint; 7.import javax.xml.ws.handler.Handler; 8. 9./** 10. * @author zsy 启动web services服务 11. */ 12.public class StartServer { 13. 14. /** 15. * @param args 16. */ 17. public static void main(String[] args) { 18. /* 19. * 生成Example 服务实例 20. */ 21. Example serverBean = new Example(); 22. /* 23. * 发布Web Service到http://localhost:8080/hello地址 1. */ 2. Endpoint endpoint = 3. Endpoint.publish("http://localhost:8080/hello", serverBean); 4. Binding binding = endpoint.getBinding(); 5. /* 6. * 设置一个SOAP协议处理栈 7. * 这里就简单得打印SOAP的消息文本 8. */ 9. List handlerChain = new LinkedList(); 10. handlerChain.add(new TraceHandler()); 11. binding.setHandlerChain(handlerChain); 12. System.out.println("服务已启动 http://localhost:8080/hello"); 13. } 14.} 在控制台运行这个类,就可以使用URL:http://localhost:8080/hello?wsdl浏览到上文所描述的WSDL的全文了。这说明您的第一个WebService应用发布成功! 构建WebService客户端 使用JavaSE6.0构建WebService的客户端是一件相当简单的事。这里我们要使用到JDK中的另一个命令行工具wsimport。在控制台下输入以下命令: 引用 wsimport-d./bin-s./src-porg.jsoso.jws.client.refhttp://localhost:8080/hello?wsdl 即可在包org.jsoso.jws.client.ref中生成客户端的存根及框架文件。其中我们要使用的类只有两个:服务类Example_Service和本地接口Example。编写如下客户端,即可调用WebService服务:Java代码1.package org.jsoso.jws.client; 2. 3.import org.jsoso.jws.client.ref.*; 4. 1.public class RunClient { 2. 3. /** 4. * @param args 5. */ 6. public static void main(String[] args) { 7. //初始化服务框架类 8. Example_Service service = new Example_Service(); 9. //或者本地服务借口的实例 10. Example server = (Example) service.getExamplePort(); 11. try { 12. //调用web service的toSayHello方法 13. System.out.println("输入toSayHello的返回值——" + server.toSayHello("阿土")); 14. Person person = new Person(); 15. person.setName("阿土"); 16. person.setAge(25); 17. //调用web service的sayHello方法 18. server.sayHello(person, "机器人"); 19. 20. person = new Person(); 21. person.setName("aten"); 22. person.setAge(30); 23. //调用web service的sayHello方法 24. PersonArray list = server.sayHello(person, "机器人"); 25. //输出返回值 26. System.out.println(" 以下输入sayHello的返回值——"); 27. for (Person p : list.getItem()) { 28. System.out.println(p.getName() + ":" + p.getAge()); 29. } 30. } catch (HelloException_Exception e) { 31. e.printStackTrace(); 32. } 1. } 2.} 届此,本次WebService的学习暂告一个段落。JavaWebService是一个相当庞大的知识体系,其中涉及的相关技术较多,这里无法一一道来,我们将会在今后的开发和使用中,同大家做进一步深入的探讨和学习。 附录:wsgen与wsimport命令说明 wsgen wsgen是在JDK的bin目录下的一个exe文件(Windows版),该命令的主要功能是用来生成合适的JAX-WS。它读取WebService的终端类文件,同时生成所有用于发布WebService所依赖的源代码文件和经过编译过的二进制类文件。这里要特别说明的是,通常在WebServiceBean中用到的异常类会另外生成一个描述Bean,如果WebServiceBean中的方法有申明抛出异常,这一步是必需的,否则服务器无法绑定该对像。此外,wsgen还能辅助生成WSDL和相关的xsd文件。wsgen从资源文件生成一个完整的操作列表并验证webservice是否合法,可以完整发布。 命令参数说明: -cp定义classpath -r生成bean的wsdl文件的存放目录 -s生成发布WebService的源代码文件的存放目录(如果方法有抛出异常,则会生成该异常的描述类源文件) -d生成发布WebService的编译过的二进制类文件的存放目录(该异常的描述类的class文件) 命令范例:wsgen-cp./bin-r./wsdl-s./src-d./bin-wsdlorg.jsoso.jws.server.Example wsimport wsimport也是在JDK的bin目录下的一个exe文件(Windows版),主要功能是根据服务端发布的wsdl文件生成客户端存根及框架,负责与WebService服务器通信,并在将其封装成实例,客户端可以直接使用,就像使用本地实例一样。对Java而言,wsimport帮助程序员生存调用web service所需要的客户端类文件.java和.class。要提醒指出的是,wsimport可以用于非Java的服务器端,如:服务器端也许是C#编写的webservice,通过wsimport则生成Java的客户端实现。 命令参数说明: -d生成客户端执行类的class文件的存放目录 -s生成客户端执行类的源文件的存放目录 -p定义生成类的包名 命令范例:wsimport-d./bin-s./src-porg.jsoso.jws.client.refhttp://localhost:8080/hello?wsd
此文档下载收益归作者所有
举报原因
联系方式
详细说明
内容无法转码请点击此处