跳转到内容

XML - 数据交换/Web服务管理

来自Wikibooks,开放世界的开放书籍



上一章 下一章
AJAX XMLHTTP



学习目标

  • 了解Web服务及其功能。
  • 了解SOAP是什么,以及Web服务如何使用它。
  • 了解Web服务描述语言是什么,以及如何阅读WSDL文件。
  • 了解通用描述、发现和集成(UDDI)标准是什么。
  • 了解如何使用Java连接到Web服务。

赞助商

佐治亚大学

特里商学院

管理信息系统系

Web服务概述

[编辑 | 编辑源代码]

Web服务是新一代的Web应用程序。它们是自包含的、自描述的、模块化的应用程序,可以在Web上发布、定位和调用。Web服务执行功能,这些功能可以是简单的请求到复杂的业务流程。一旦部署了Web服务,其他应用程序(和其他Web服务)就可以发现并调用已部署的服务。Web服务利用XML来描述请求和响应,并使用HTTP作为其网络传输。

Web服务和Web应用程序之间的主要区别在于协作。Web应用程序只是使用Web协议定位或调用的业务应用程序。类似地,Web服务也在网络上远程执行计算功能。但是,Web服务使用互联网协议,其目的是实现可互操作的机器到机器协调。

Web服务已成为解决分布式计算相关问题的解决方案。分布式计算是使用多个系统来执行功能,而不是让单个系统执行功能。以前在分布式计算中使用的技术,主要是公共对象请求代理体系结构(CORBA)和分布式组件对象模型(DCOM),存在一些局限性。例如,两者都没有实现完全的平台独立性或易于通过防火墙传输。此外,DCOM不是供应商独立的,它是微软的产品。

分布式计算标准的一些主要需求是

  • 跨平台支持企业对企业以及内部通信。
  • 尽可能符合现有的互联网基础设施。
  • 可扩展性,包括节点数量和复杂性。
  • 国际化。
  • 容错性。
  • 供应商独立性。
  • 适用于简单和非简单的请求。

随着时间的推移,业务信息系统变得高度配置和差异化。这不可避免地使系统交互变得极其昂贵和耗时。开发人员开始认识到标准化Web服务开发的好处。使用Web标准似乎是实现这些目标的直观且合乎逻辑的步骤。Web标准已经为系统通信提供了一种平台独立的方式,并且被信息系统用户广泛接受。

最终结果是开发了Web服务。Web服务形成一个分布式环境,其中可以通过标准化接口远程访问对象。它使用三层模型,定义服务提供者、服务消费者和服务代理。这使得Web服务成为一种松散的关系,因此,如果服务提供者宕机,代理始终可以将消费者引导到另一个提供者。类似地,有很多代理,因此消费者总是可以找到一个可用的代理。为了进行通信,Web服务使用开放的Web标准:TCP/IP、HTTP和基于XML的SOAP。

在更高层次上,可能会添加诸如XAML、XLANG(涉及多个Web服务的复杂Web事务的事务支持)和XKMS(微软和Verisign正在进行的工作,以支持身份验证和注册)等技术。

SOAP结构

简单对象访问协议 (SOAP) 是一种以可扩展格式向Web服务发送和接收信息的方法。SOAP可用于发送信息或作为XML编码的远程过程调用。从本质上讲,SOAP充当了与Web服务进行通信的普遍接受的方法。企业遵守SOAP约定是为了简化与Web服务交互的过程。

<SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/">
 <SOAP:Header>

  <!-- SOAP header -->

 </SOAP:Header>
 <SOAP:Body SOAP:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">

  <!-- SOAP body -->

 </SOAP:Body>
</SOAP:Envelope>

SOAP消息包含用于调用Web服务的请求方法,或包含对Web服务请求的响应信息。

在开发独立的Web服务时遵循此布局为企业提供了显著的好处。由于Web应用程序旨在被众多参与者使用,因此开发人员希望它们易于采用。使用既定且熟悉的通信标准最终减少了用户有效交互Web服务所需的工作量。

SOAP信封用于定义和组织Web服务消息中包含的内容。主要的是,SOAP信封用于指示指定文档将用于服务交互。它包含一个可选的SOAP头和一个SOAP主体。消息在SOAP主体中发送,SOAP头用于发送主体中不期望的其他信息。例如,如果SOAP:actor属性存在于SOAP头中,则表示消息的接收者应该是谁。

Web服务事务涉及SOAP请求和SOAP响应。我们将使用的示例是Weather.gov提供的Web服务。输入是纬度、经度、开始日期、所需的预报信息天数以及数据的格式。SOAP请求如下所示

  <?xml version="1.0" encoding="UTF-8" standalone="no"?/>
  <SOAP-ENV:Envelope
      SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" 
      xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
     
     <SOAP-ENV:Body>
        <m:NDFDgenByDayRequest xmlns:SOAPSDK1="http://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl">
           <latitude xsi:type="xsd:decimal">33.955464</latitude>
           <longitude xsi:type="xsd:decimal">-83.383245</longitude>
           <startDate xsi:type="xsd:date"></startDate>
           <numDays xsi:type="xsd:integer">1</numDays>
           <format>24 Hourly</format>
        </m:NDFDgenByDayRequest>
     </SOAP-ENV:Body>
     
  </SOAP-ENV:Envelope>

startDate被留空,因为这将自动获取最新数据。格式数据类型未定义,因为它在WSDL文档中定义。

响应SOAP如下所示。

  <?xml version="1.0" encoding="UTF-8" standalone="no"?/>
  <SOAP-ENV:Envelope
      SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" 
      xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
     
     <SOAP-ENV:Body>
        <NDFDgenByDayResponse xmlns:SOAPSDK1="http://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl">
           <dwmlByDayOut xsi:type="xsd:string">.....</dwmlByDayOut>
        </NDFDgenByDayResponse>
     </SOAP-ENV:Body>
     
  </SOAP-ENV:Envelope>

SOAP通过在发送方对其进行编码并在接收方对其进行解码来处理数据。SOAP处理的数据类型基于W3C XML Schema规范。简单类型包括字符串、整数、浮点数和双精度数,而复合类型由基本类型组成。

  <element name="name" type="xsd:string" />
  <SOAP:Array SOAP:arrayType="xsd:string[2]">
     <string>Web</string>
     <string>Services</string>
  </SOAP:Array>

由于它们是基于文本的,因此SOAP消息通常不会遇到通过防火墙或其他障碍的问题。它们是向Web服务传递和接收信息的理想方式。

服务描述 - WSDL

[编辑 | 编辑源代码]

Web服务描述语言 (WSDL) 旨在提供有关如何连接到特定Web服务并对其进行查询的信息。此文档也遵循严格的格式和组织指南。但是,方法、参数和服务信息是特定于应用程序的。Web服务执行不同的功能并包含独立的信息,但它们都以相同的方式组织。通过为这些服务创建标准的组织架构,开发人员可以有效地调用和利用它们,而无需太多熟悉。要使用Web服务,开发人员可以遵循WSDL的设计标准,轻松确定与其使用相关的所有信息和过程。

从本质上讲,WSDL文档充当与Web服务交互的说明。它不包含任何应用程序逻辑,从而使服务具有一定的自主性。这使用户能够有效地与服务交互,而无需了解其内部工作原理。

以下是提供给定美国邮政编码的温度的Web服务的WSDL文件的示例。

<?xml version="1.0"?>
<definitions xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" 
xmlns:si="http://soapinterop.org/xsd" xmlns:tns="http://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl" 
xmlns:typens="http://www.weather.gov/forecasts/xml/DWMLgen/schema/DWML.xsd" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns="http://schemas.xmlsoap.org/wsdl/" 
targetNamespace="http://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl>
 
 <types>
    <xsd:schema targetNamespace="http://www.weather.gov/forecasts/xml/DWMLgen/schema/DWML.xsd">
       <xsd:import namespace="http://schemas.xmlsoap.org/soap/encoding/" />
       <xsd:import namespace="http://schemas.xmlsoap.org/wsdl/" />
       <xsd:simpleType name="formatType">
          <xsd:restriction base="xsd:string">
             <xsd:enumeration value="24 hourly" />
             <xsd:enumeration value="12 hourly" />
          </xsd:restriction>
       </xsd:simpleType>
       <xsd:simpleType name="productType">
          <xsd:restriction base="xsd:string">
             <xsd:enumeration value="time-series" />
             <xsd:enumeration value="glance" />
          </xsd:restriction>
       </xsd:simpleType>
       <xsd:complexType name="weatherParametersType">
          <xsd:all>
             <xsd:element name="maxt" type="xsd:boolean" />
             <xsd:element name="mint" type="xsd:boolean" />
             <xsd:element name="temp" type="xsd:boolean" />
             <xsd:element name="dew" type="xsd:boolean" />
             <xsd:element name="pop12" type="xsd:boolean" />
             <xsd:element name="qpf" type="xsd:boolean" />
             <xsd:element name="sky" type="xsd:boolean" />
             <xsd:element name="snow" type="xsd:boolean" />
             <xsd:element name="wspd" type="xsd:boolean" />
             <xsd:element name="wdir" type="xsd:boolean" />
             <xsd:element name="wx" type="xsd:boolean" />
             <xsd:element name="waveh" type="xsd:boolean" />
             <xsd:element name="icons" type="xsd:boolean" />
             <xsd:element name="rh" type="xsd:boolean" />
             <xsd:element name="appt" type="xsd:boolean" />
          </xsd:all>
       </xsd:complexType>
    </xsd:schema>
</types>

<message name="NDFDgenRequest">  
   <part name="latitude" type="xsd:decimal"/>
   <part name="longitude" type="xsd:decimal" />
   <part name="product" type="typens:productType" />
   <part name="startTime" type="xsd:dateTime" />
   <part name="endTime" type="xsd:dateTime" />
   <part name="weatherParameters" type="typens:weatherParametersType" />
</message>

<message name="NDFDgenResponse">
   <part name="dwmlOut" type="xsd:string" />
</message>

<message name="NDFDgenByDayRequest">  
   <part name="latitude" type="xsd:decimal" />
   <part name="longitude" type="xsd:decimal" />
   <part name="startDate" type="xsd:date" />
   <part name="numDays" type="xsd:integer" />
   <part name="format" type="typens:formatType" />
</message>

<message name="NDFDgenByDayResponse">
   <part name="dwmlByDayOut" type="xsd:string" />
</message>

<portType name="ndfdXMLPortType">
   <operation name="NDFDgen">
      <documentation> Returns National Weather Service digital weather forecast data </documentation>
      <input message="tns:NDFDgenRequest" />
      <output message="tns:NDFDgenResponse" />
   </operation>
   <operation name="NDFDgenByDay">
      <documentation> Returns National Weather Service digital weather forecast data summarized over either 24- or 12-hourly periods </documentation>
      <input message="tns:NDFDgenByDayRequest" />
      <output message="tns:NDFDgenByDayResponse" />
   </operation>
</portType>

<binding name="ndfdXMLBinding" type="tns:ndfdXMLPortType">
   <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />
   <operation name="NDFDgen">
      <soap:operation soapAction="http://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl#NDFDgen" style="rpc" />
      <input>
         <soap:body use="encoded" namespace="http://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl" 
             encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
      </input>
      <output>
         <soap:body use="encoded" namespace="http://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl" 
             encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
      </output>
   </operation>
   <operation name="NDFDgenByDay">
      <soap:operation soapAction="http://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl#NDFDgenByDay" style="rpc" />
      <input>
         <soap:body use="encoded" namespace="http://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl" 
             encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
      </input>
      <output>
         <soap:body use="encoded" namespace="http://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl" 
             encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
      </output>
   </operation>
</binding>

<service name="ndfdXML">
   <documentation>The service has two exposed functions, NDFDgen and NDFDgenByDay. 
                        For the NDFDgen function, the client needs to provide a latitude and 
                        longitude pair and the product type. The client also needs to provide 
                        the start and end time of the period that it wants data for. For the 
                        time-series product, the client needs to provide an array of boolean values 
                        corresponding to which weather values should appear in the time series product. 
                        For the NDFDgenByDay function, the client needs to provide a latitude and longitude 
                        pair, the date it wants to start retrieving data for and the number of days worth 
                        of data. The client also needs to provide the format that is desired.</documentation>
   <port name="ndfdXMLPort" binding="tns:ndfdXMLBinding">
      <soap:address location="http://www.weather.gov/forecasts/xml/SOAP_server/ndfdXMLserver.php" />
   </port>
  </service>
</definitions>

WSDL文件定义了一个服务,该服务由称为端口的不同端点组成。端口由网络地址和绑定组成。

<service name="ndfdXML">
   <documentation>The service has two exposed functions, NDFDgen and NDFDgenByDay. 
                        For the NDFDgen function, the client needs to provide a latitude and 
                        longitude pair and the product type. The client also needs to provide 
                        the start and end time of the period that it wants data for. For the 
                        time-series product, the client needs to provide an array of boolean values 
                        corresponding to which weather values should appear in the time series product. 
                        For the NDFDgenByDay function, the client needs to provide a latitude and longitude 
                        pair, the date it wants to start retrieving data for and the number of days worth 
                        of data. The client also needs to provide the format that is desired.</documentation>
   <port name="ndfdXMLPort" binding="tns:ndfdXMLBinding">
      <soap:address location="http://www.weather.gov/forecasts/xml/SOAP_server/ndfdXMLserver.php" />
   </port>
</service>

绑定标识每个操作的绑定样式和协议。在这种情况下,它使用远程过程调用样式绑定,使用SOAP。

   <binding name="ndfdXMLBinding" type="tns:ndfdXMLPortType">
   <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />
   <operation name="NDFDgen">
      <soap:operation soapAction="http://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl#NDFDgen" style="rpc" />
      <input>
         <soap:body use="encoded" namespace="http://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl" 
             encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
      </input>
      <output>
         <soap:body use="encoded" namespace="http://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl" 
             encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
      </output>
   </operation>
   <operation name="NDFDgenByDay">
      <soap:operation soapAction="http://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl#NDFDgenByDay" style="rpc" />
      <input>
         <soap:body use="encoded" namespace="http://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl" 
             encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
      </input>
      <output>
         <soap:body use="encoded" namespace="http://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl" 
             encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
      </output>
   </operation>
</binding>

端口类型是操作的抽象集合。在这种情况下,操作是getTemp。

   <portType name="ndfdXMLPortType">
      <operation name="NDFDgen">
         <documentation> Returns National Weather Service digital weather forecast data     </documentation>
         <input message="tns:NDFDgenRequest" />
         <output message="tns:NDFDgenResponse" />
      </operation>
      <operation name="NDFDgenByDay">
         <documentation> Returns National Weather Service digital weather forecast data summarized over either 24- or 12-hourly periods </documentation>
         <input message="tns:NDFDgenByDayRequest" />
         <output message="tns:NDFDgenByDayResponse" />
      </operation>
   </portType>

最后,消息由操作用于通信——换句话说,用于传递参数和返回值。

   <message name="NDFDgenByDayRequest">  
      <part name="latitude" type="xsd:decimal" />
      <part name="longitude" type="xsd:decimal" />
      <part name="startDate" type="xsd:date" />
      <part name="numDays" type="xsd:integer" />
      <part name="format" type="typens:formatType" />
   </message>

   <message name="NDFDgenByDayResponse">
      <part name="dwmlByDayOut" type="xsd:string" />
   </message>

从WSDL文件,消费者应该能够访问Web服务中的数据。

有关此特定Web服务的更详细分析,请访问Weather.gov

服务发现 - UDDI

[编辑 | 编辑源代码]

您已经了解了如何使用WSDL来共享Web服务的接口定义,但是您如何首先找到Web服务呢?有无数的独立Web服务由同样多的不同组织开发和维护。在采用Web服务实践和方法后,开发人员试图促进其系统的参与和创造性重用。很快发现,需要对这些服务及其各自的位置进行枚举记录。此信息将使开发人员能够快速轻松地利用Web服务的最佳实践和流程。此外,拥有当前Web服务功能的中央参考使开发人员能够避免开发冗余应用程序。

UDDI 定义了可以发布和查找服务的注册中心。UDDI 规范是由微软、Ariba 和 IBM 创建的。UDDI 定义了一种数据结构和应用程序编程接口 (API)。

在之前提到的三层模型中,UDDI 是服务代理。它的功能是使服务消费者能够找到合适的服务提供者。

可以使用 Java API for XML Registries (JAXR) 通过 Java 连接到 UDDI 注册中心。JAXR 创建了一个抽象层,因此它可以与 UDDI 和其他类型的 XML 注册中心一起使用,例如 ebXML 注册和存储库标准。

使用 Java 与 Web 服务

[编辑 | 编辑源代码]

要执行 SOAP 消息,必须使用应用程序与服务提供者通信。由于其灵活性,几乎任何编程语言都可以用来执行 SOAP 消息。但是,为了我们的目的,我们将重点关注使用 Java 与 Web 服务进行交互。

使用 Java 与 Web 服务需要一些外部库。

  • Apache SOAP 工具包
  • Java 邮件框架
  • JavaBeans 激活框架
  • Xerces XML 解析器

让我们一起学习如何使用 Java 查询我们之前讨论过的温度 Web 服务。

import java.io.*;
import java.net.*;
import java.util.*;
import org.apache.soap.util.xml.*;
import org.apache.soap.*;
import org.apache.soap.rpc.*;

public class TempClient
{

 public static float getTemp (URL url, String zipcode) throws Exception 
 {

  Call call = new Call ();

  // Service uses standard SOAP encoding
  String encodingStyleURI = Constants.NS_URI_SOAP_ENC;
  call.setEncodingStyleURI(encodingStyleURI);

  // Set service locator parameters
  call.setTargetObjectURI ("urn:xmethods-Temperature");
  call.setMethodName ("getTemp");

  // Create input parameter vector
  Vector params = new Vector ();
  params.addElement (new Parameter("zipcode", String.class, zipcode, null));
  call.setParams (params);

  // Invoke the service ....
  Response resp = call.invoke (url,"");

  // ... and evaluate the response
  if (resp.generatedFault ()) 
  {
   throw new Exception();
  } 
  else 
  {
   // Call was successful. Extract response parameter and return result
   Parameter result = resp.getReturnValue ();
   Float rate=(Float) result.getValue();
   return rate.floatValue();
  }
 }

 // Driver to illustrate service invocation
 public static void main(String[] args)
 {
  try
  {
   URL url=new URL("http://services.xmethods.net:80/soap/servlet/rpcrouter");
   String zipcode= "30605";
   float temp = getTemp(url,zipcode);
   System.out.println(temp);
  }
  catch (Exception e) 
  {
   e.printStackTrace();
  }
 }
}

此 Java 代码有效地隐藏了用户的所有 SOAP。它通过名称和 URL 调用目标对象,并设置参数zipcode。但是底层的 SOAP 请求是什么样子的呢?

  <?xml version="1.0" encoding="UTF-8"?>
  <soap:Envelope xmlns:n="urn:xmethods-Temperature"
      xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
      xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
      xmlns:xs="http://www.w3.org/2001/XMLSchema" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

     <soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
        <n:getTemp>
           <zipcode xsi:type="xs:string">30605</zipcode>
        </n:getTemp>
     </soap:Body>

  </soap:Envelope>

如您所见,SOAP 请求使用 Java 调用传递的参数来填充 SOAP 信封并指导消息。类似地,响应作为“70.0”返回到 Java 程序中。响应 SOAP 也被 Java 程序隐藏。

  <?xml version='1.0' encoding='UTF-8'?>
  <SOAP-ENV:Envelope 
      xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xmlns:xsd="http://www.w3.org/2001/XMLSchema">

     <SOAP-ENV:Body>
        <ns1:getTempResponse xmlns:ns1="urn:xmethods-Temperature" 
            SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
           <return xsi:type="xsd:float">70.0</return>
        </ns1:getTempResponse>
     </SOAP-ENV:Body>

  </SOAP-ENV:Envelope>

这是使用 Java 和 SOAP 与 Web 服务交互的另一个示例。此特定 Web 服务称为“美国邮编验证器”,它以邮政编码作为参数,然后返回相应的经度和纬度。在开发与 Web 服务交互的应用程序时,第一步应该是查看 WSDL 文档。

此服务的 WSDL 文档位于此处:http://www.webservicemart.com/uszip.asmx?WSDL

此文档将包含与“美国邮编验证器”Web 服务交互所需的所有说明。

SOAPClient4XG

修改者 - Duncan McAllister 来自:http://www.ibm.com/developerworks/xml/library/x-soapcl/

import java.io.*;
import java.net.*;
import java.util.*;

public class SOAPClient4XG {
    
    public static void main(String[] args) throws Exception {

        args = new String[2];
        
        args[0] = "http://services.xmethods.net:80/soap/servlet/rpcrouter";
        args[1] = "SOAPrequest.xml";
        
        if (args.length  < 2) {
            System.err.println("Usage:  java SOAPClient4XG " +
                               "http://soapURL soapEnvelopefile.xml" +
                               " [SOAPAction]");
				System.err.println("SOAPAction is optional.");
            System.exit(1);
        }

        String SOAPUrl      = args[0];
        String xmlFile2Send = args[1];

		  String SOAPAction = "";

				
        // Create the connection where we're going to send the file.
        URL url = new URL(SOAPUrl);
        URLConnection connection = url.openConnection();
        HttpURLConnection httpConn = (HttpURLConnection) connection;

        // Open the input file. After we copy it to a byte array, we can see
        // how big it is so that we can set the HTTP Cotent-Length
        // property. (See complete e-mail below for more on this.)

        FileInputStream fin = new FileInputStream(xmlFile2Send);

        ByteArrayOutputStream bout = new ByteArrayOutputStream();
    
        // Copy the SOAP file to the open connection.
        copy(fin,bout);
        fin.close();

        byte[] b = bout.toByteArray();

        // Set the appropriate HTTP parameters.
        httpConn.setRequestProperty( "Content-Length",
                                     String.valueOf( b.length ) );
        httpConn.setRequestProperty("Content-Type","text/xml; charset=utf-8");
		  httpConn.setRequestProperty("SOAPAction",SOAPAction);
        httpConn.setRequestMethod( "POST" );
        httpConn.setDoOutput(true);
        httpConn.setDoInput(true);

        // Everything's set up; send the XML that was read in to b.
        OutputStream out = httpConn.getOutputStream();
        out.write( b );    
        out.close();

        // Read the response and write it to standard out.

        InputStreamReader isr =
            new InputStreamReader(httpConn.getInputStream());
        BufferedReader in = new BufferedReader(isr);

        String inputLine;

        while ((inputLine = in.readLine()) != null)
            System.out.println(inputLine);

        in.close();
    }

  // copy method from From E.R. Harold's book "Java I/O"
  public static void copy(InputStream in, OutputStream out) 
   throws IOException {

    // do not allow other threads to read from the
    // input or write to the output while copying is
    // taking place

    synchronized (in) {
      synchronized (out) {

        byte[] buffer = new byte[256];
        while (true) {
          int bytesRead = in.read(buffer);
          if (bytesRead == -1) break;
          out.write(buffer, 0, bytesRead);
        }
      }
    }
  } 
}

此 Java 类引用了一个 XML 文档 (SOAPRequest.xml),该文档用作 SOAP 消息。此文档应包含在调用服务的 Java 应用程序的同一项目文件夹中。

在查看了“美国邮编验证器”WSDL 文档后,很明显我们想调用“getTemp”方法。此信息包含在 SOAP 主体中,并包含相应的参数。

SOAPRequest.xml

<?xml version="1.0" encoding="UTF-8"?>
  <soap:Envelope xmlns:n="urn:xmethods-Temperature"
      xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
      xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
      xmlns:xs="http://www.w3.org/2001/XMLSchema" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

     <soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
        <n:getTemp>
           <zipcode xsi:type="xs:string">30605</zipcode>
        </n:getTemp>
     </soap:Body>

  </soap:Envelope>

成功交互后,Web 服务提供商将提供一个格式类似于用户请求的响应。在 NetBeans 中开发时,运行此项目并在 Tomcat 输出窗口中检查随后的 SOAP 消息响应。


使用 Netbeans 的 Web 服务

[编辑 | 编辑源代码]

此说明中使用的 Netbeans 版本为 5.0。

打开 Netbeans 后,单击左侧窗格中的“运行时”选项卡,然后右键单击“Web 服务”并选择“添加 Web 服务”。在“URL”字段中,输入 Web 服务 WSDL 文件的地址,在上面的示例中为“http://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl”,然后单击“获取 Web 服务描述”。这将显示 Web 服务的信息。

Web 服务是使用 XML 与许多不同系统通信以执行任务的应用程序。为了促进 Web 服务的使用,开发了允许它们灵活且可扩展的协议。SOAP 用于发送和定义信息,而 WSDL 用于提供有关如何连接和查询 Web 服务的信息。UDDI 描述了这些 Web 服务可以在哪里找到。
[编辑 | 编辑源代码]
华夏公益教科书