一、由来
在接口对接当中,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("<", "<").replaceAll(">", ">");
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