当前位置: 老葡京网站娱乐 > 网页设计 > XML教程 > 正文

简单SOAP客户机:通用Java SOAP客户机

时间:2012-09-17 IBM Bob DuCharme

老葡京网站娱乐 www.sdguanhua.com SOAP(简单对象访问协议)是 IBM、Microsoft、DevelopMentor 和 UserLand Software 为在网络上交换信息而开发的一种已在发展的 W3C 标准。随着 Web 上 可以公开使用的 SOAP 服务器的不断增加,SOAP 几乎对用任何语言编写的程序― ― 即使是用流行的简单语言(如 Visual Basic、JavaScript 和 perl)编写的 非常短小的程序――执行着 HTML 对 Web 浏览器所做的事:它为这些程序提供一 个简单的方法来利用万维网上不断增加的可用信息源。

与 HTML 类似,SOAP 提供一套标记来表示在 Web 上使用 HTTP 传输协议(从 SOAP 1.1 以来,SMTP 也可以)发送的不同信息块的作用。但是,SOAP 向您提供 的能力远远强于 HTML。使用 SOAP,您的程序向 SOAP 服务器发送“SOAP 请求” (一个简短的 XML 文档,描述在远程机器上要调用的方法和所有要传递给它的参 数)。SOAP 服务器将尝试用那些参数执行该方法,并将 SOAP 响应发回程序。响 应可以是执行的结果,也可以是相应的错误消息??梢允褂霉?SOAP 服务器为 提出请求的客户机提供股票价格、最新的货币兑换率、FedEx 包裹跟踪信息、 代 数表达式的解决方案以及其它各类信息。

在 SOAP 存在之前,尝试使用这种信息的程序必须先捕获 Web 页面,然后“ 刮下”HTML,以查找适当的文本。对这些 Web 页面进行可视的重新设计(例如, 将当前股票价格放到表中第三列而不是第二列中)就可以使这些程序无用。SOAP 规范以及它所携带的简要的 SOAP 请求和响应模式为客户机和服务器之间的联络 提供了一个框架, 该框架是那些强健得多的信息收集工具的基础。

有许多 SOAP 客户机可用于大多数的流行编程语言;有关详尽列表,请参阅 SOAP::Lite for Perl 主页上的 SOAP Toolkits 部分。大多数 SOAP 客户机都提 供类库、COM 对象或从您自己程序调用的等同对象。通常,使用这些客户机库遵 循以下模式:

程序传递要调用的远程方法的名称和所有必需参数。

库组装 SOAP 请求的适当 XML 文档以将这一信息打包。

库将这一 XML 文档传递给 SOAP 端点 URL 标识的 SOAP 服务器,这与通过指 定服务器的 URL 将浏览器指向 Web 服务器地址很类似。

SOAP 服务器尝试执行方法后,它组装包含执行结果的 SOAP 响应 XML 文档, 并将它发回 SOAP 客户机。

接收 SOAP 响应时,客户机库对 XML 进行语法分析以获得方法调用的结果, 并将结果传递给使用库的程序。

SOAPClient4XG

SOAP 的介绍(请参阅 developerWorks 上 Graham Glass 编写得极佳的“ Web 服务革命”专栏)总是讨论用于 SOAP 请求和响应的 XML 的结构, 但是我 接触到的 SOAP 客户机总是会暗中进行 XML 组装和语法分析,所以我从来不用知 道。作为使用 XML 的人员,我 曾想自己执行 XML 部分;我认为如果 SOAP 这样 简单, 那么我应该能够编写一个简单的 SOAP 客户机来读取 SOAP 请求的 XML 文档、将它发送到命令行上指定的 SOAP 端点 URL、 读回响应文档并输出该响应 。这将使它成为一个真正的通用 SOAP 客户机,因为它调用任何 SOAP 服务器上 的任何方法。

清单 1中显示的 SoapClient4XG(“SOAP Client for XML Geeks”)Java 类 执行该任务, 而不使用早先提到的 SOAP Toolkits 页面上列出的任何专用 Java SOAP 类。检查了必需的 SOAP 端点 URL 和 SOAP XML 文档文件名参数及可选的 SOAP 操作参数后,读入文件,将它发送到 SOAP 服务器,读回响应,然后将其输 出到标准出口。

因为该 SOAP 客户机使用 HTTP 协议发送 XML SOAP 请求,所以大量必需做的 工作就是 HTTP 设置。Java 提供了一个 HttpURLConnection 类, 它有许多“设 置”方法来正确设置每个 HTTP 参数,并且可以用简单的字符串来设置大多数参 数。需要一点额外代码的一个 HTTP 参数是 Content-Length ,所以 SoapClient4XG 通过在读取 XML 请求之后将它放到一个字节数组中,然后检查字 节数组的 长度 特性来计算 XML 请求的长度。

可使用其它会代您设置这些 HTTP 参数的 HTTP 实现。Sun 开放源码的 Brazil Web 应用程序框架会自动处理 HTTP 问题, 并使处理适当 SOAP 错误更 为容易,因为(不象早期的 HttpURLConnection 类)它是一个没有经过特定编写 以用 Java 小应用程序减轻装入图像和其它 Web 资源工作的通用 HTTP 类。

请参考“清单 1”,获取 完整的 SOAP 客户机。

Listing 1. The complete SOAP client

/**
  * SOAPClient4XG. Read the SOAP envelope file passed as  the second
  * parameter, pass it to the SOAP endpoint passed as the  first parameter, and
  * print out the SOAP envelope passed as a response. with  help from Michael
  * Brennan 03/09/01
  *
  *
  * @author Bob DuCharme
  * @version 1.1
  * @param  SOAPUrl   URL of SOAP Endpoint to send  request.
  * @param  xmlFile2Send A file with an XML document of  the request.
  *
  * 5/23/01 revision: SOAPAction added
*/
import java.io.*;
import java.net.*;
public class SOAPClient4XG {
   public static void main(String[] args) throws Exception  {
     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 = "";
     if (args.length > 2)
   SOAPAction = args[2];

     // 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);
     }
    }
   }
  }
}