用Java实现基于SOAP的XML文档网络传输及远程过程调用(RPC)_第1页
用Java实现基于SOAP的XML文档网络传输及远程过程调用(RPC)_第2页
用Java实现基于SOAP的XML文档网络传输及远程过程调用(RPC)_第3页
用Java实现基于SOAP的XML文档网络传输及远程过程调用(RPC)_第4页
用Java实现基于SOAP的XML文档网络传输及远程过程调用(RPC)_第5页
已阅读5页,还剩32页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、用Java实现基于SOAP的XML文档网络传输及远程过程调用(RPC)SOAP(SimpleObjectAccessProtocol,简单对象访问协议)是一种基于XML的,用于计算机之间交换信息的协议。SOARtt应用于各种消息接发系统,并能通过各种传输协议进行消息传递,但最初的侧重点是通过HTTP专输的远程过程调用。SOAP是Webservice的一个重要组成部份,如果把Webservice比喻成Internet,那么SOAP就可以比喻成TCP/IP。SOAP是一种协议而非具体产品,微软也有自己的SOAP实现产品,而Java下比较流行的SOAP实现产品就是ApacheSOAP,不过它的下一个

2、版本已经改名成AXIS了。SOAP1用XML件来做为数据转输的载体的,走HTTP的线路。一般企业的防火墙都开放HTTP的80端口,所以SOAPf会被防火墙阻断,这算是SOAP勺一个优点。信息转输的双方都要求支持SOAPR务,因为XML文件发过去,则对方需要有SOAPR务来接收,然后对方会有反馈也是XML件,这时你也需要安装SOAPK务来接收。1,环境配置为了运行程序,我们首先必须配置好环境:共要下载四个软件包,它们都是开源免费的。其中,前两个是Apache的,后两个是SUM站的,如下所示:SOAPhttp:/apache.freelamp.cOm/ws/soap/version-2.3.1/X

3、erces:/dist/xerces-j/JavaMail:JAF:下载后将它们分别解压缩。分别在这四个包的解压目录中找到:xerces.jar、soap.jar、mail.jar、activation.jar(JAF的),则是四个jar文件是我们所需要的。本机安装环境:WindowsXP(SP2+JDK1.4.2_06+Tomcat5.0.28+SOAP2.3.1配置步骤:1、安装JDK和Tomcat。过程比较简单,这里不再详述。2、将刚才所找到的四个jar文件复制到Tomcat的“Tomcat5.0commonlib”目录下,这个目录是Tomcat的

4、默认包目录,在这个目录中的所有包在Tomcat启动时都会被自动加载。3、将路径下的tools.jar也复制到Tomcat的“Tomcat5.0commonlib”目录下。4、将soap解压目录的webapps目录下的soap.war文件,复制至UTomcat的“Tomcat5.0webapps”目录下,这个目录是Tomcat的WEEK用所在目录。重新启动Tomcat,Tomcat会自动将其解压,并配置好路径。可以尝试在浏览器中输入“http:localhost:8080/soap/,看SOAP!否安装好。5、注意在编写程序时,需要将所得到的四个jar文件路径设置到所使用的Java编程环境中,因

5、为在程序中需要用到其中的类文件。具体步骤略。6、重启Tomcat服务。这时Tomcat会将“Tomcat5.0commonlib”目录下新加入的包加载到内存中。到此,我们已经配置好了程序运行所需要的环境。2.基于SOA用勺XML文档网络传输SOA觊范主要定义了四个元素:SOA聆封规范,传输和协议绑定,编码规则和一个RPO定。用于实现消息的网络传输。SOA的封规范,SOAP言封规范对计算机间传递的数据如何封装定义了具体的规则。这包括应用特定的数据,如要调用的方法名,方法参数和返回值;还包括谁将处理封装内容,失败时如何编码错误消息等信息。数据编码规则,为了交换数据,计算机必须在编码特定数据类型的规

6、则上达成一致,SOA也有自己的一套编码数据类型的约定。大部分约定都基于W3CXMLSchema范。RPC&定,SOA唯用于单向和双向等各种消息接发系统。SOA的双向消息接发定义了一个简单的协定来进行远程过程调用和响应,这使得客户端应用可以指定远程方法名,获取任意多个参数并接受来自服务器的响应。传输和协议绑定,提供了更底层协议传输SOAP寸套的一套通用机制。而以上四个部分统称为一个SOAP!息。我们先来看一篇XML文档是如何变成SOAP勺。采用一个简单的购物订单文件PO.xml0内容为:JoeSmith14OakParkBedfordMA01730CandyCanes4441.68Iwantca

7、ndy!其对应的SOAP!息为:POST/ServletTemp/HTTPReceiveHTTP/1.0Host:localhostContent-Type:text/xml;charset=utf-8Content-Length:939SOAPAction:urn:oreilly-jaws-samplesMeYou9999JoeSmith14OakParkBedfordMA01730CandyCanes4441.68Iwantcandy!一个SOA月肖息包括:SOAP寸套,SOA以(可选),SOA印体。我们首先将XML档包装到一个SOA咻中,然后再把SOA咻包装到一个SOAP寸套中,可以在封

8、套中再添加一个SOA映(不是必须),最后将SOAP寸套绑定到一个协议中。我们来仔细分析一下代码。SOAP寸套SOAP寸套的声明在XM所签的最外层,它表明了一个SOAPC档的边界。下面的封套标签显示了三个必要的属性,这些属性指明了封套中使用的名字空间和语法。其中第一个属性:xmlns:SOAP-ENV=/soap/envelope/是一个名字空间声明,防止多个XML文件组合时发生标签名字的冲突。第二个属性声明了XMLM式实例的名字空间。前缀xsi必须放在这个名字空间定义的所有元素和属性之前。最后一个属性是另外一个名字空间声明,它定义了XMLSch

9、emag字空问,这个名字空间下的元素用来指定xsi:type属性的值(如xsd:string)。SOA以SOAPfe和体在语法上非常类似。SOAP1.1和SOAP1.2tB没有头里应该有些什么,它就是简单的存放一些指令,提供给接收消息的SOAPt理器。建立在SOA之上的更高级协议(比如ebXMU肖息服务)就通过定义一些特殊元素来规范头的格式。另外当对RPC8用SOAP寸,头部也可以用来表示一些底层信息。MeYou9999SOA庄体SOAPfc体用来存放实际数据或消息的有效负载(本例中为XML档),从而提供给最终的接受者使用或处理。soaPj、议绑定当绑定到一个HTTPa、议时,需要在SOAP寸

10、套前面添加HTTP头的信息。POST/ServletTemp/HTTPReceiveHTTP/1.0Host:localhostContent-Type:text/xml;charset=utf-8Content-Length:939SOAPAction:urn:oreilly-jaws-samples在SOAP1.1中SOAPAction是HTTPW定所必须的部分,它的目的是让那些路由或分派的信息知道该做些什么,即使它们根本不知道SOA城者没有解析SOAP封套的方法。而在SOAP1.2中SOAPAction已变成可选的了。SOAP肖息的发送与接收我们已经看到了一个SOAP肖息的各个组成块,接

11、下来我们要了解消息是怎样被创建的,以及怎样在两个端点之间进行传输的。SOAP勺发送端的代码:packagejavaSoap01;importjava.io.*;importjava.util.*;publicclassGenericHTTPSoapClient(PrivatestaticfinalStringDEFAULT_HOST_URL=http:/localhost:8080/ServletTemp/HTTPReceive;privatestaticfinalStringDEFAULT_DATA_FILENAME=./PO.xml;privatestaticfinalStringURI=

12、urn:oreilly-jaws-samples;privateStringm_hostURL;privateStringm_dataFileName;publicGenericHTTPSoapClient(StringhostURL,StringdataFileName)throwsException(m_hostURL=hostURL;m_dataFileName=dataFileName;System.out.println();System.out.println();System.out.println(StartingGenericHTTPSoapClient:);System.o

13、ut.println(hosturl=+m_hostURL);System.out.println(datafile=+m_dataFileName);System.out.println();System.out.println();/实际的传送工作是由sendSOAPMessage方法完成的publicvoidsendSOAPMessage()try/首先读取XML档,将其解析成DO飒。FileReaderfr=newFileReader(m_dataFileName);/通过调用ApachegetXMlDocBuilder()方法得到一个解析器,它返回一个DocumentBuilder对

14、象。javax.xml.parsers.DocumentBuilderxdb=org.apache.soap.util.xml.XMLParserUtils.getXMLDocBuilder();/通过解析器解析文档,得到一个Document对象。org.w3c.dom.Documentdoc=xdb.parse(neworg.xml.sax.InputSource(fr);if(doc=null)throwneworg.apache.soap.SOAPException(org.apache.soap.Constants.FAULT_CODE_CLIENT,parsingerror);/cr

15、eateavectorforcollectingtheheaderelementsVectorheaderElements=newVector();/Createaheaderelementinanamespaceorg.w3c.dom.ElementheaderElement=doc.createElementNS(URI,jaws:MessageHeader);headerElement.setAttributeNS(URI,SOAP-ENV:mustUnderstand,1);/CreatesubnodeswithintheMessageHeaderorg.w3c.dom.Element

16、ele=doc.createElement(From);org.w3c.dom.TexttextNode=doc.createTextNode(Me);org.w3c.dom.NodetempNode=ele.appendChild(textNode);tempNode=headerElement.appendChild(ele);ele=doc.createElement(To);textNode=doc.createTextNode(You);tempNode=ele.appendChild(textNode);tempNode=headerElement.appendChild(ele)

17、;ele=doc.createElement(MessageId);textNode=doc.createTextNode(9999);tempNode=ele.appendChild(textNode);tempNode=headerElement.appendChild(ele);headerElements.add(headerElement);/createavectorforcollectingthebodyelementsVectorbodyElements=newVector();/获取顶层DOME素,放到向量中。顶层节点的下层节点元素的创建和添加工作由DOM单析器负责。body

18、Elements.add(doc.getDocumentElement();/CreatetheSOAPenvelopeorg.apache.soap.Envelopeenvelope=neworg.apache.soap.Envelope();/AddtheSOAPheaderelementtotheenvelopeorg.apache.soap.Headerheader=neworg.apache.soap.Header();header.setHeaderEntries(headerElements);envelope.setHeader(header);/CreatetheSOAPbo

19、dyelementorg.apache.soap.Bodybody=neworg.apache.soap.Body();body.setBodyEntries(bodyElements);/AddtheSOAPbodyelementtotheenvelopeenvelope.setBody(body);/BuildtheM.apache.soap.messaging.Messagemsg=neworg.apache.soap.messaging.Message();msg.send(.URL(m_hostURL),URI,envelope);System.out.print

20、ln(SentSOAPMessagewithApacheHTTPSOAPClient.);/从传输中接受响应并将其打印到屏幕上System.out.println(Waitingforresponse.);org.apache.soap.transport.SOAPTransportst=msg.getSOAPTransport();BufferedReaderbr=st.receive();Stringline=br.readLine();if(line=null)(System.out.println(HTTPPOSTwassuccessful.n);)else(while(line!=n

21、ull)(System.out.println(line);line=br.readLine();)catch(Exceptione)(e.printStackTrace();)publicstaticvoidmain(Stringargs)/省略,)在上述程序中,当我们构造好SOAP寸套后,它需要被送到一个目的地去。在ApacheSOAP,有一个Message对象来处理异步的单向传送。Message.send()方法有三个参数:一个URL用于指明传送地点;一个URI,用于表示SOAPAction头的值;还有一个SOAP寸套。SOAPActionURI实际上是绑定HTTP勺一部分,用来指定当一

22、个消息到达传送目的地的时候调用哪个函数或服务。Message接口用于异步单向通信,Message.seng()函数的返回值为void型。但这并不妨碍它在双向同步会话中使用。当这个Message接口是基于一个双向传输协议(例如HTTP狭现的时候,SOAPTransport.receive()方法就能用来接收一个响应。在SOAPTransport是基于HTTP现的情况下,receive()方法阻塞并等待一个错误(例如一个HTTP青求超时),或者一个正确的返回代码(例如“HTTP1.0200OK)。soaPg收端代码:publicclassHTTPReceiveextendsHttpServlet/

23、SOAP请求以HTTPPOS死式接收publicvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse)throwslOException,ServletExceptionSystem.out.println(Receivedrequest.);System.out.println();/TraversetheHTTPheadersandshowthemonthescreenfor(Enumerationenum=request.getHeaderNames();enum.hasMoreElements();)Strin

24、gheader=(String)enum.nextElement();Stringvalue=request.getHeader(header);System.out.println(+header+=+value);)System.out.println();if(request.getContentLength()0)(try(java.io.BufferedReaderreader=request.getReader();/获取DocumentBuilderjavax.xml.parsers.DocumentBuilderxdb=org.apache.soap.util.xml.XMLP

25、arserUtils.getXMLDocBuilder();/接下来我们将文件解析为一个DOMf,得到一个Document对象。org.w3c.dom.Documentdoc=xdb.parse(neworg.xml.sax.InputSource(reader);if(doc=null)(/ErroroccuredSystem.out.println(Docisnull!);throwneworg.apache.soap.SOAPException(org.apache.soap.Constants.FAULT_CODE_CLIENT,parsingerror);else(/在接收端我们已经

26、有了一个发送过来的SOAP寸套。SOAP寸套是SOAPC档的最外层元素,也是根元素。我们可以遍历这个DOMf从而直接得到封套以及它的子节点。通过调用unmarshall()方法从文件中得到一个Envelope实例。org.apache.soap.Envelopeenv=org.apache.soap.Envelope.unmarshall(doc.getDocumentElement();/现在我们得到了一个封套,我们按照和前面相反的过程来操作它:从Envelope中取得BodyEntrys的向量Vector,然后从向量中取得B.apache.soap.Bodybody=env.

27、getBody();java.util.VectorbodyEntries=body.getBodyEntries();java.io.StringWriterwriter=newjava.io.StringWriter();for(java.util.Enumeratione=bodyEntries.elements();e.hasMoreElements();)org.w3c.dom.Elementel=(org.w3c.dom.Element)e.nextElement();在当前情况下,向量中只有一个条目:元素。从而我们也就得到了一个DOM寸象。这个DOM寸象和前面我们为建立PO.xm

28、l而建立的DOM寸象完全一样。我们调用静态方法DOM2Writer.serializeAsXML()将PurchaseOrder元素及其子元素全部序列化为一个StringWriter对象。org.apache.soap.util.xml.DOM2Writer.serializeAsXML(org.w3c.dom.Node)el,writer);System.out.println(writer.toString();catch(Exceptione)System.out.println(e);System.out.println();response.setContentType(text/x

29、ml);/NeedthistopreventApacheSOAPfromgacking带附件的SOAPT肖息XMLKSOARfg够很好的描述数据,但是许多应用程序的数据并不适合XML来描述,比如图像的二进制数据。SWA(SOAPWithAttachments)可以解决这个问题。SWAJSOA初议和MIMEB式组合到一起,从而使SOAP肖息可以包含任意的数据。这个模型和在email中包含附件的方法是一样的。MIM刖、议允许在消息中包含任意多个数据块。每个数据块都被一个MIME头分开。在SWAK整个消息包含多个MIME&B分,第一部分(部分0)是SOAP寸套,剩下的部分(1-n)都是附件。所有这些

30、部分都包装在底层协议中。构造带附件的SOAPSOAP寸套的创建和组装和以前一样,消息的创建议和以前一样。下面给出心田代码,它创建一个MimeBodyPart对象,然后我们从附件中读出文本作为它的内容体(假定附件为一个TXT文本文件)。/创建消息org.apache.soap.messaging.Messagemsg=neworg.apache.soap.messaging.Message();/添加附件if(m_attachment!=null)BufferedReaderattachmentReader=newBufferedReader(newFileReader(m_attachment

31、);StringBufferbuffer=newStringBuffer();for(Stringline=attachmentReader.readLine();line!=null;line=attachmentReader.readLine()buffer.append(line);MimeBodyPartattachment=newMimeBodyPart();attachment.setText(buffer.toString();接下来,我们需要让接收端能够引用附件。为了使接收端能够分析这个消息,我们在XM&档中添加了一个元素,它用the-attachment作为href的值。我们

32、用这个值作为附件的content-id.attachment.setHeader(Content-ID,the-attachment);最后,我们在消息中添加附件部分然后发送。ApacheSOA0知道你在消息中添加了附件,并且会正确的转化为消息格式:msg.addBodyPart(attachment);msg.send(.URL(m_hostURL),URI,envelope);System.out.println(SentSOAPMessagewithApacheHTTPSOAPClient.);接收带附件的SOAP/处理SOA咻org.apache.soap.Bodybody=reque

33、stEnvelope.getBody();java.util.VectorbodyEntries=body.getBodyEntries();writer.write(nBody=n);for(java.util.Enumeratione=bodyEntries.elements();e.hasMoreElements();)org.w3c.dom.Elementel=(org.w3c.dom.Element)e.nextElement();org.apache.soap.util.xml.DOM2Writer.serializeAsXML(org.w3c.dom.Node)el,writer

34、);我们通过XML文档中的元素来查找附件。首先我们通过名字查找attachment元素。然后我们取出href属性中的content-id的值。一旦我们得到了id,就能够使用SOAPContext对象中的getBodyPart()方法,通过content-id来查找MIME付件。org.w3c.dom.ElementattachmentEl=(org.w3c.dom.Element)el.getElementsByTagName(attachment).item(0);if(attachmentEl!=null)writer.write(nAttachment=n);cid=attachment

35、El.getAttribute(href).substring(4);/getridofcid:writer.write(Content-ID=+cid+n);MimeBodyPartattachment=requestContext.getBodyPart(cid);trywriter.write(Theattachmentis.n+attachment.getContent()+n);catch(Exceptionex)thrownewSOAPException(Constants.FAULT_CODE_SERVER,Errorwritingresponse,ex);elsewriter.

36、write(TheContent-IDisnull!n);System.out.println(writer.toString();3.基于SOAP勺远程过程调用(RPC)SOAP-RP使用SOA底层结构定义了一个用来表示RPCZ及RPC向应的模型。它并不要求一定要紧紧地绑定一个同步的请求/响应模型或者一个HTTPB议。实际上SOAP1.侪口1.2规范都明确声明了SOAP-RP的使用和协议的绑定是无关的。规范承认,当SOAP-RP绑定到HTTPM,RPCM用就自动和HTTP青求相匹配,但是这个匹配纯粹是偶然的。因此真正重要的是SOAPt义了一个统一的模型,来表示RPCS其一个或多个返回值。RP

37、CM用的基本要求是,体元素包含方法名和参数,并且参数可以通过存取方法来访问。SOAPS提供了对方法签名,头数据和代表目的地的URI进行编码的方法。我们先来看一个SOAP-RPCJ发送端内容:POST/soap/servlet/rpcrouterHTTP/1.0Host:localhost:5555Content-Type:text/xml;charset=utf-8Content-Length:678SOAPAction:A350001V万temA350002A350005可以看到,在封套体内包含了方法名以及过程调用所需的参数。如在这个SOAP肖息中,是自动产生的标签,它代表方法名。参数用xs

38、i:type=ns2:Array”类型表示。SOAP-Encoding属性SOAPS码是一套规则,说明线路上传输的数据类型如何进行编码或者序列化。在上面这个消息中,encodingStyle属性值设为这个特定的URL定义了基于/soap/encoding/SOAP1.1模式的编码规则。SOAR码包括了序列化任何数据类型的规则,从简单的标量类型到复杂的数据类型。SOAP-RP西法签名方法签名只是简单的声明body元素包含一个SOAP吉构。结构中的每一个元素都可被一个存取方法所引用。在SOAPK带有存取方法的元素能够直接用命名的标签或者一个顺序值来

39、标识。如果有多个参数,它们必须和所调用的方法中的参数列表的顺序一致,类型也必须匹配。响应的规则也是类似的。响应端返回的内容为:HTTP/1.1200OKSet-Cookie:JSESSIONID=AAD5E6B20535EDACC7637062DF663979;Path=/soapContent-Type:text/xml;charset=utf-8Content-Length:696Date:Wed,04May200514:01:35GMTServer:Apache-Coyote/1.1Connection:close54.9919.9936.24SOAP-RP的发送和接收下面是一个SOAP

40、-RPC送端的代码:publicdoublegetPriceList(Stringskus口)throwsSOAPException,MalformedURLExceptionParameterskuParam;/建立调用Callcall=newCall();/服务使用标准的SOAPS码call.setEncodingStyleURI(Constants.NS_URI_SOAP_ENC);/设置目标URIcall.setTargetObjectURI(urn:examples:pricelistservice);/设置调用方法的名称call.setMethodName(getPriceList

41、);/创建参数对象VectorparamList=newVector();Parameterparam=newParameter(sku,String.class,skus,Constants.NS_URI_SOAP_ENC);paramList.addElement(param);/设置参数call.setParams(paramList);/设置Web服务的URLURLurl=newURL(http:/localhost:8080/soap/servlet/rpcrouter);调用Web服务Responseresp=call.invoke(url,null);/查看响应if(!resp.generatedFault()/返回结果值Parameterresult=resp.getReturnValue();doublepriceList口=(double)result.getValue();returnpriceList;/查看错误elseFaultf=resp.getFault();StringfaultCode=f.getFaultCode();StringfaultString

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论