Hutool SoapClient 学习

时间:2024-10-09 07:47:42

一、由来

在接口对接当中,WebService接口占有着很大份额,而我们为了使用这些接口,不得不引入类似Axis等库来实现接口请求。

现在有了Hutool,就可以在无任何依赖的情况下,实现简便的WebService请求。

二、使用

使用SoapUI解析WSDL地址,找到WebService方法和参数。
我们得到的XML模板为:

<soapenv:Envelope xmlns:soapenv="/soap/envelope/" xmlns:web="/">
   <soapenv:Header/>
   <soapenv:Body>
      <web:getCountryCityByIp>
         <!--Optional:-->
         <web:theIpAddress>?</web:theIpAddress>
      </web:getCountryCityByIp>
   </soapenv:Body>
</soapenv:Envelope>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

按照SoapUI中的相应内容构建SOAP请求。
我们知道:

方法名为:web:getCountryCityByIp
参数只有一个,为:web:theIpAddress
定义了一个命名空间,前缀为web,URI为/
这样我们就能构建相应SOAP请求:

// 新建客户端
SoapClient client = SoapClient.create("/WebServices/")
    // 设置要请求的方法,此接口方法前缀为web,传入对应的命名空间
    .setMethod("web:getCountryCityByIp", "/")
    // 设置参数,此处自动添加方法的前缀:web
    .setParam("theIpAddress", "218.21.240.106");

    // 发送请求,参数true表示返回一个格式化后的XML内容
    // 返回内容为XML字符串,可以配合XmlUtil解析这个响应
    Console.log(client.send(true));

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

三、设置消息头

在业务中有遇到一个问题,就是使用CXF动态生成的SoapClient去访问WebService,在idea上运行没有问题,但是打包之后就各种问题了。于是立即换了Hutool的SoapClient,但是有个问题就是官方文档只给出了最简单的例子。比如如下的xml模板我们该怎么实现?

<soapenv:Envelope xmlns:soapenv="/soap/envelope/" xmlns:tem="/">
   <soapenv:Header>
      <tem:Header>
         <!--Optional:-->
         <tem:UserName>?</tem:UserName>
         <!--Optional:-->
         <tem:Password>?</tem:Password>
      </tem:Header>
   </soapenv:Header>
   <soapenv:Body>
      <tem:HelloWorld/>
   </soapenv:Body>
</soapenv:Envelope>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

我们按照日常习惯,看看SoapClient里面有哪些方法,于是就看到了header()方法,刚好有两个参数,于是直接拿来使用,然后并没有起效。

SoapClient client = SoapClient.create("http://localhost:65168/")
                .setMethod("tem:HelloWorld","/")
                .header("UserName","mes")
                .header("Password","123456");
        String soapXmlStr=client.send();
  • 1
  • 2
  • 3
  • 4
  • 5

查看源代码发现是被添加到了一个MessageHeader中去了。MessageHeader是消息请求头,嗯,所以不要搞混了,跟我们要添加的Header不是一回事。

 public void addRequestProperty(String key, String value) {
        checkConnected();
        if (key == null)
            throw new NullPointerException ("key is null");

        if (requests == null)
            requests = new MessageHeader();

        requests.add(key, value);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

四、设置Header

我们需要访问一个第三方WebService,需要我们传输一个MySoapHeader。使用SoapClient的 (name)方法,其他方法单独使用会报错。

<soapenv:Envelope xmlns:soapenv="/soap/envelope/" xmlns:tem="/">
   <soapenv:Header>
      <tem:MySoapHeader>
         <!--Optional:-->
         <tem:UserName>?</tem:UserName>
         <!--Optional:-->
         <tem:Password>?</tem:Password>
      </tem:MySoapHeader>
   </soapenv:Header>
   <soapenv:Body>
      <tem:HelloWorld/>
   </soapenv:Body>
</soapenv:Envelope>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

我们需要设置QName,然后自己创建xml子节点。

SoapClient.create("http://localhost:65168/")
                .setMethod("tem:HelloWorld","/")
       
    QName name = new QName("/","MySoapHeader","");
    SOAPHeaderElement mySoapHeader = client.addSOAPHeader(name);
    SOAPElement UserName=mySoapHeader.addChildElement("UserName");
    UserName.setTextContent("mes");
    SOAPElement PassWord=mySoapHeader.addChildElement("PassWord");
    PassWord.setTextContent("123456");

	String soapXmlStr=client.send();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

五、通过HttpClient进行访问

来自好心大哥的代码

HttpClient httpClient = new HttpClient();
         tring url = wsconfigVO.getUrl();
        String soapRequestData = "<soapenv:Envelope xmlns:soapenv=\"/soap/envelope/\" xmlns:web=\"/\"><soapenv:Header/><soapenv:Body><web:capitalPay><requestXml><![CDATA["
                + exportxml
                + "]]></requestXml></web:capitalPay></soapenv:Body></soapenv:Envelope>";
        Logger.error("[gzcg]bw:"+soapRequestData);
        PostMethod httppost = new PostMethod(url);
        /* 把Soap请求数据添加到PostMethod */
        try {
            httppost.setRequestHeader("Content-Type", "text/xml;charset=UTF-8");
            httppost.setRequestHeader("SOAPAction", "");
            byte[] b = soapRequestData.getBytes("utf-8");
            InputStream is = new ByteArrayInputStream(b, 0, b.length);
            RequestEntity re = new InputStreamRequestEntity(is, b.length,
                    "application/soap+xml; charset=utf-8");
            httppost.setRequestEntity(re);
            httpClient.executeMethod(httppost);

            InputStream rs = httppost.getResponseBodyAsStream();
            // 获取返回流并转换为Document
            Document document = new SAXReader().read(rs, "UTF-8");
            String result = document.asXML();
            Logger.error("[gzsyzr] backxml:"+result);
            // 符号转换
            result = result.replaceAll("&lt;", "<").replaceAll("&gt;", ">");
            result = result.substring(result.lastIndexOf("<?xml"));
            result = result.substring(0, result.indexOf("</MSG>") + 6);
            Logger.error("[gzsyzr] backxml1:"+result);
            return new Object[]{result.trim()};
        } catch (Exception e) {
            Logger.error("调用接口服务报错:" + e.getMessage(), e);
            throw new BusinessException("调用esburlssl接口服务报错:" + e.getMessage(), e);
        } finally {
            httppost.releaseConnection();
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 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
  • 35