通过HttpClien方式调用wsdl接口代码样例

309 阅读3分钟

该Demo用到了天气预报公共开放接口, 数据来源于中国气象局

Endpoint : www.webxml.com.cn/WebServices…
Disco : www.webxml.com.cn/WebServices…
WSDL : www.webxml.com.cn/WebServices…

什么是WSDL

WSDL(Web Services Description Language,Web服务描述语言)是一种用于描述Web服务接口的XML格式的语言。它定义了Web服务的功能、操作和消息格式,允许客户端应用程序了解如何与特定的Web服务进行交互。

主要组成部分包括:

  1. 服务定义(Service Definition) : 描述服务的名称、命名空间和服务的位置(URL)
  2. 端口类型(Port Type) : 定义一个抽象接口, 包含一组操作(operations)
  3. 绑定(Binding) : 将端口类型映射到具体的协议和消息格式, 如SOAP协议的HTTP绑定
  4. 消息(Message) : 定义数据元素和类型, 用于消息的结构

WSDL使得客户端能够理解如何构造有效的请求,并处理来自服务端的响应。它为Web服务提供了标准化的描述,使得不同平台和编程语言的应用程序可以互相通信和交互。

看不懂? 没关系, 因为我也看不懂

举个例子, 访问 www.webxml.com.cn/WebServices… 可以看到WSDL的文档, 如下图所示

image.png

啊这一大堆密密麻麻的是什么东西啊?! 看得我头皮发麻! 但实际上, 看WSDL文档需要从末尾看起, 我们把页面拉到最底下

image.png

我们能看到一些带有binding属性的标签, 以12结尾说明支持soap 1.2, 如果没有则说明只支持soap 1.1, 至于什么是SOAP, 这个我们一会再说, 接着来看WSDL文档

image.png

这种形式的就是接口定义了, 那么这东西要怎么看呢? 其实也很简单, name标签后为接口名, 例如图中第一个接口名为getSupportProvince

sequence标签下的内容展示了需要传递的参数, 例如getSupportProvince接口不需要传参, 而getSupportProvinceResponse接口需要传递String[]类型的参数getSupportProvinceResult

那么怎么传递参数呢? 这就要说到SOAP了

什么是SOAP

SOAP协议(Simple Object Access Protocol,简单对象访问协议)是一种用于交换结构化信息在分布式环境中进行通信的协议。它基于XML,用于在网络上通过HTTP或其他协议传输信息。SOAP协议主要用于不同系统之间的通信,可以支持不同平台和编程语言的互操作性。

SOAP消息通常由一个envelope(信封)、一个header(头)、一个body(主体)和一个fault(错误)组成。SOAP协议提供了一种标准的、简单的方法来访问Web服务,并且可以通过WSDL(Web Services Description Language,Web服务描述语言)定义服务接口。

啊怎么办, 我还是看不懂啊! 别急别急, 俗话说万事开头难, 然后中间难, 最后结尾难...要是不用上班也能拿工资就好了, 咳咳

扯远了, 还是回来看看SOAP, 协议其实大概就是这样一种形式

<?xml version="1.0"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
    soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
    <soap:Header>
      ...
      ...
    </soap:Header>
    <soap:Body>
          ...
          ...
          <soap:Fault>
            ...
            ...
          </soap:Fault>
    </soap:Body>
</soap:Envelope>

举个例子, 这里就不作详解了, 需要看详解的朋友可以看看站内的这篇文章

string替换为需要传参的内容即可, 如果传送的参数是XML字符串, 那么需要使用转义或者使用<![CDATA[ + xmlStr + ]]>, 建议使用<![CDATA[ + xmlStr + ]]>的方式

<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:xsd="http://www.w3.org/2001/XMLSchema"
	xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
  <soap12:Body>
    <getSupportCity xmlns="http://WebXml.com.cn/">
      <byProvinceName>string</byProvinceName>
    </getSupportCity>
  </soap12:Body>
</soap12:Envelope>

注意区分SOAP的版本和命名空间

SOAP 1.1 schemas.xmlsoap.org/soap/envelo…
SOAP 1.2 www.w3.org/2003/05/soa…

最后附上样例代码

代码样例

方法示例

public String httpClient(String url, String soap) {
    HttpClient httpClient = new HttpClient();
    PostMethod postMethod = new PostMethod(url);
    String result = null;
    byte[] bytes = soap.getBytes(StandardCharsets.UTF_8);
    try (BufferedInputStream bis = new BufferedInputStream(new ByteArrayInputStream(bytes, 0, bytes.length))) {
        // SOAP 1.1 uses "text/xml"
        // SOAP 1.2 uses "application/soap+xml"
        RequestEntity re = new InputStreamRequestEntity(bis, bytes.length, "application/soap+xml;charset=utf-8");
        postMethod.setRequestEntity(re);
        httpClient.executeMethod(postMethod);
        result = postMethod.getResponseBodyAsString();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        postMethod.releaseConnection();
    }
    return result;
}

调用示例

@Test
public void httpClient() {
    String url = "http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl";
    String soap = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
        "<soap12:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" +
        "    xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n" +
        "    xmlns:soap12=\"http://www.w3.org/2003/05/soap-envelope\">\n" +
        "    <soap12:Body>\n" +
        "        <getSupportCity xmlns=\"http://WebXml.com.cn/\">\n" +
        "            <byProvinceName>江苏</byProvinceName>\n" +
        "        </getSupportCity>\n" +
        "    </soap12:Body>\n" +
        "</soap12:Envelope>";
    String s = httpClient(url, soap);
    System.out.println(s);
}