Java使用Hutool调用WebService接口详解
大家WebService接口还在使用生成的类去实现调用的吗?其实Hutool的WebService工具很厉害,但是文档写的不太清楚,或者示例不够多,我主要做医疗业务,对接方基本都是WebService接口,刚开始使用hutool的时候确实花费了挺长时间研究,最终失败告终,奈何业务多,有丰富的机会去尝试,现在基本啥格式的都可以克服了。一、WebService是什么?
提示:本文显示baidu.com,皆为脱敏用,并非真正地址。
目录
前言
大家WebService接口还在使用生成的类去实现调用的吗?
其实Hutool的WebService工具很厉害,但是文档写的不太清楚,或者示例不够多,我主要做医疗业务,对接方基本都是WebService接口,刚开始使用hutool的时候确实花费了挺长时间研究,最终失败告终,奈何业务多,有丰富的机会去尝试,现在基本啥格式的都可以克服了。
一、WebService是什么?
Web Service是一个平台独立的,低耦合的,自包含的、基于可编程的web的应用程序,可使用开放的XML(标准通用标记语言下的一个子集)标准来描述、发布、发现、协调和配置这些应用程序,用于开发分布式的交互操作的应用程序。
二、使用步骤
1.验证链接。
拿到三方提供的链接后,需要进行验证下
例如:第三方提供链接:http://localhost:8080/XXX/services/xxxxxxImpl
需要改成:第三方提供链接:http://localhost:8080/XXX/services/xxxxxxImpl?wsdl
然后用浏览器打开能像下图展示即可:
2.Soap调用测试
使用SoapUI进行接口调用一次(没有SoapUI的自己去安装下)
如下图进行创建
打开,选择要调用的接口,点开request后,后边会出现一个框,里面有调用入参和请求地址
3.获取需要用到的数据
- 接口请求地址:http://localhost:8080/xxxxx/services/xxxxServiceImpl
- 请求头:SOAPAction:""
- 请求方法/接口:ser:ReceiveDataAll
- 前缀命名空间:http://service.mocire.baidu.com/
- 入参:
<![CDATA[<request><type>1</type></request>]]>
4.Hutool工具类调用
针对上面的数据,我这边写好工具类,先上干货,然后一一为大家讲解:
package com.ceshi;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.XmlUtil;
import cn.hutool.http.webservice.SoapClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Map;
/**
* @author 饭团
* @version 1.0
* @description: TODO
* @date 2022/10/24 14:14
*/
public class a {
private static Logger log = LoggerFactory.getLogger(a.class);
public static void main(String[] args) {
StringBuilder params = new StringBuilder("<![CDATA[<request>");
params.append("<type>0</type></request>]]>");
request("ReceiveDataAll",params.toString());
}
/**
* @description: 请求方法
* @param: method 请求方法
* @param: params 入参字符串
* @return: java.util.Map<java.lang.String,java.lang.Object>
* @author 周培武
* @date: 2022/10/24 14:23
*/
private static Map<String, Object> request(String method, String params){
String result = "";
String requestId = UUID.randomUUID().toString();
try{
String url = "http://localhost:8080/xxxxxx/services/xxxxServiceImpl";
SoapClient client = SoapClient.create(url)
.header("SOAPAction","")
// 设置要请求的方法,此接口方法前缀为web,传入对应的命名空间
.setMethod("ser:"+method, "http://service.mocire.baidu.com/")
.setParam("message",params,false);//此处写true,会自动填写命名空间
log.info("[请求ID:{}]CSDN测试方法字符串接口:{},入参:{}",requestId,url,client.getMsgStr(true));
// 发送请求,参数true表示返回一个格式化后的XML内容
// 返回内容为XML字符串,可以配合XmlUtil解析这个响应
result = client.send(false);
log.info("[请求ID:{}]CSDN测试方法字符串出参:{}",requestId,result);
if(result.contains("<![CDATA[")){
result = result.substring(result.indexOf("<![CDATA[")+9,result.indexOf("]]>"));
}else{
result = result.substring(result.indexOf("Result>")+7,result.indexOf("}</")+1);
}
Map<String, Object> resultMap = XmlUtil.xmlToMap(result);
return resultMap;
}catch (Exception ex){
log.error("[请求ID:{}]CSDN测试方法字符串出现异常,入参:{},出参:{},{}",requestId,params,result,ex);
throw ex;
}
}
}
- 接口地址:好理解,就放在create()方法入参里,如果接口地址动态变动,可以请求方法加入参:接口,然后这块随之变动
- 请求头:header(),左边填写SOAPAction,右边由于我这边是空的,我就默认留空,实际按照你们的soapui上显示的填写。
- 请求方法:setMethod(),左边填写带前缀的请求方法,右边填写对应的前缀命名空间
- 入参:setParam(),填写字段名,入参(我这边就一个入参,里面包含的是一个xml字符串),是否自动填写前缀,我这边这个字段是不带前缀的,所以填写false,大家按照自己的来.
如果是多个入参,可以选用setParams,写入一个map,键值对,然后统一配置是否添加前缀
- 获取生成后的入参:client.getMsgStr(true),此处参数是否是格式化后的参数,大家可以自己测试。
我这边只是拿这个接口做了一个测试,下面会给大家整理下我这边遇到的各种不通类型的请求信息和工具类
三、示例
1.单个入参
请求数据:
接口地址:http://localhost:8080/xxxxxx/services/xxxxServiceImpl
请求头:SOAPAction: ""
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://service.mocire.baidu.com/">
<soapenv:Header/>
<soapenv:Body>
<ser:ReceiveDataAll>
<!--Optional:-->
<message><![CDATA[<request><type>1</type></request>]]></message>
</ser:ReceiveDataAll>
</soapenv:Body>
</soapenv:Envelope>
请求方法:
public static void main(String[] args) {
StringBuilder params = new StringBuilder("<![CDATA[<request>");
params.append("<type>0</type></request>]]>");
request("ReceiveDataAll",params.toString());
}
/**
* @description: 请求方法
* @param: method 请求方法
* @param: params 入参字符串
* @return: java.util.Map<java.lang.String,java.lang.Object>
* @author 周培武
* @date: 2022/10/24 14:23
*/
private static Map<String, Object> request(String method, String params){
String result = "";
String requestId = UUID.randomUUID().toString();
try{
String url = "http://localhost:8080/xxxxxx/services/xxxxServiceImpl";
SoapClient client = SoapClient.create(url)
.header("SOAPAction","")
// 设置要请求的方法,此接口方法前缀为web,传入对应的命名空间
.setMethod("ser:"+method, "http://service.mocire.baidu.com/")
.setParam("message",params,false);//此处写true,会自动填写命名空间
log.info("[请求ID:{}]CSDN测试方法字符串接口:{},入参:{}",requestId,url,client.getMsgStr(true));
// 发送请求,参数true表示返回一个格式化后的XML内容
// 返回内容为XML字符串,可以配合XmlUtil解析这个响应
result = client.send(false);
log.info("[请求ID:{}]CSDN测试方法字符串出参:{}",requestId,result);
if(result.contains("<![CDATA[")){
result = result.substring(result.indexOf("<![CDATA[")+9,result.indexOf("]]>"));
}else{
result = result.substring(result.indexOf("Result>")+7,result.indexOf("}</")+1);
}
Map<String, Object> resultMap = XmlUtil.xmlToMap(result);
return resultMap;
}catch (Exception ex){
log.error("[请求ID:{}]CSDN测试方法字符串出现异常,入参:{},出参:{},{}",requestId,params,result,ex);
throw ex;
}
}
2.多个入参
请求数据:
接口地址:http://localhost:8080/xxxxxx/services/xxxxServiceImpl
请求头:SOAPAction: "http://tempuri.org/GetThirdAppData"
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/">
<soapenv:Header/>
<soapenv:Body>
<tem:GetThirdAppData>
<tem:strPatientId>1000001</tem:strPatientId>
<tem:strHospitalNo>1</tem:strHospitalNo>
<tem:strXML><![CDATA[<HOSPITAL_NO>1</HOSPITAL_NO><PATIENT_ID>1000001</PATIENT_ID>]]></tem:strXML>
</tem:GetThirdAppData>
</soapenv:Body>
</soapenv:Envelope>
请求示例:
public static Map<String, Object> write(String param){
String result = "";
String requestId = UUID.randomUUID().toString();
try{
String hospitalNo = "1";
String patientId = "1000001";
//拼接strXML
Map<String,Object> paramMap = new HashMap<>();
paramMap.put("HOSPITAL_NO", hospitalNo);//医院编码
paramMap.put("PATIENT_ID",patientId);//患者ID
String paramStr = "<![CDATA["+XmlUtil.mapToXmlStr(paramMap)+"]]>";
//拼接外层入参
Map<String,Object> params = new HashMap<>();
params.put("strPatientId",patientId);
params.put("strHospitalNo",hospitalNo);
params.put("strXML",paramStr);
//新建客户端
String url = "";
SoapClient client = SoapClient.create("http://localhost:8080/xxxxxx/services/xxxxServiceImpl")
.header("SOAPAction","http://tempuri.org/GetThirdAppData")
// 设置要请求的方法,此接口方法前缀为web,传入对应的命名空间
.setMethod("tem:GetThirdAppData", "http://tempuri.org/")
.setParams(params,true);
log.info("[请求ID:{}]CSDN测试方法字符串接口:{},入参:{}",requestId,url,client.getMsgStr(true));
// 发送请求,参数true表示返回一个格式化后的XML内容
// 返回内容为XML字符串,可以配合XmlUtil解析这个响应
result = client.send(false);
log.info("[请求ID:{}]CSDN测试方法字符串出参:{}",requestId,result);
if(result.contains("<![CDATA[")){
result = result.substring(result.indexOf("<![CDATA[")+9,result.indexOf("]]>"));
}else{
result = result.substring(result.indexOf("Result>")+7,result.indexOf("}</")+1);
}
Map<String, Object> resultMap = XmlUtil.xmlToMap(result);
return resultMap;
}catch (Exception ex){
log.error("[请求ID:{}]CSDN测试方法字符串出现异常出参:{},{}",requestId,result,ex);
throw ex;
}
}
3.动态地址
请求数据:
接口地址:http://localhost:8080/xxxxxx/services/xxxxServiceImpl.cls?CfgItem=A101查询患者信息接口
请求头:SOAPAction: "http://baidu.com/BS.XmlService.Send"
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:bjg="http://baidu.com">
<soapenv:Header/>
<soapenv:Body>
<bjg:Send>
<bjg:pInput><![CDATA[<request><idNo>0</type></idNo>]]></bjg:pInput>
</bjg:Send>
</soapenv:Body>
</soapenv:Envelope>
请求示例:
public static void main(String[] args) {
StringBuilder params = new StringBuilder("<![CDATA[<request>");
params.append("<idNo>0</idNo></request>]]>");
request("A101查询患者信息接口",params.toString());
}
/**
* @description: 请求方法
* @param: method 请求方法
* @param: params 入参字符串
* @return: java.util.Map<java.lang.String,java.lang.Object>
* @author 周培武
* @date: 2022/10/24 14:23
*/
private static Map<String, Object> request(String method, String params){
String result = "";
String requestId = UUID.randomUUID().toString();
try{
String url = "http://localhost:8080/xxxxxx/services/xxxxServiceImpl.cls?CfgItem="+method;
SoapClient client = SoapClient.create(url)
.header("SOAPAction","http://baidu.com/BS.XmlService.Send")
// 设置要请求的方法,此接口方法前缀为web,传入对应的命名空间
.setMethod("bjg:Send", "http://baidu.com")
.setParam("pInput",params,true);
log.info("[请求ID:{}]CSDN请求方法字符串接口:{},入参:{}",requestId,url,client.getMsgStr(true));
// 发送请求,参数true表示返回一个格式化后的XML内容
// 返回内容为XML字符串,可以配合XmlUtil解析这个响应
result = client.send(false);
log.info("[请求ID:{}]CSDN请求方法字符串出参:{}",requestId,result);
if(result.contains("<![CDATA[")){
result = result.substring(result.indexOf("<![CDATA[")+9,result.indexOf("]]>"));
}else{
result = result.substring(result.indexOf("Result>")+7,result.indexOf("}</")+1);
}
Map<String, Object> resultMap = XmlUtil.xmlToMap(result);
return resultMap;
}catch (Exception ex){
log.error("[请求ID:{}]CSDN请求方法字符串出现异常,接口:{},入参:{},出参:{},{}",requestId,method,params,result,ex);
throw ex;
}
}
4.多命名空间
请求数据:
接口地址:http://localhost:8080/xxxxxx/services/xxxxServiceImpl.cls
请求头:SOAPAction: "http://tempuri.org/ITJTCService/SubmitReservationExam"
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/" xmlns:ly="http://schemas.datacontract.org/2004/07/LY.WebService.Service.Models">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<tem:SubmitReservationExam xmlns:tem="http://tempuri.org/">
<tem:info>
<ly:CardNo>111111111111</ly:CardNo>
</tem:info>
</tem:SubmitReservationExam>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
请求示例:
private static Map<String, Object> request(String params) throws SOAPException {
String result = "";
String requestId = UUID.randomUUID().toString();
try{
//新建客户端
String url = "http://localhost:8080/xxxxxx/services/xxxxServiceImpl";
SoapClient client = SoapClient.create(url)
.header("SOAPAction","http://tempuri.org/ITJTCService/SubmitReservationExam")
// 设置要请求的方法,此接口方法前缀为web,传入对应的命名空间
.setMethod("tem:SubmitReservationExam","http://tempuri.org/");
//修改一级和二级前缀为tem
SOAPBodyElement soapBodyElement = client.getMethodEle();
soapBodyElement.getParentElement().getParentElement().addNamespaceDeclaration("tem","http://tempuri.org/").addNamespaceDeclaration("ly","http://schemas.datacontract.org/2004/07/LY.WebService.Service.Models");
SOAPElement soapElement = soapBodyElement.addChildElement(new QName("http://tempuri.org/","info","tem"));
soapElement.addChildElement("CardNo","ly").setValue("111111111111111111");
log.info("[请求ID:{}]CSDN测试方法字符串接口:{},入参:{}",requestId,url,client.getMsgStr(true));
// 发送请求,参数true表示返回一个格式化后的XML内容
// 返回内容为XML字符串,可以配合XmlUtil解析这个响应
result = client.send(false);
log.info("[请求ID:{}]CSDN测试方法字符串出参:{}",requestId,result);
if(result.contains("<![CDATA[")){
result = result.substring(result.indexOf("<![CDATA[")+9,result.indexOf("]]>"));
}else{
result = result.substring(result.indexOf("Result>")+7,result.indexOf("}</")+1);
}
Map<String, Object> resultMap = XmlUtil.xmlToMap(result);
return resultMap;
}catch (Exception ex){
log.error("[请求ID:{}]CSDN请求方法字符串出现异常,入参:{},出参:{},{}",requestId,params,result);
throw ex;
}
}
此入参类型方法特别难调用,之前反馈过hutool,hutool暂不打算深入优化,我这边提供的解决方案hutool推荐使用。
总结
其实大部分入参类型都包含在这里面了,如果还有新的,无法使用的可以将wsdl页面右键查看源文件把html代码发给我,我这边研究下,有啥问题也欢迎在下面提问,我这边看见就会回答的。
更多推荐
所有评论(0)