问题
因为使用axis1.4的webservice客户端老是调用失败,所以,想使用HttpClient客户端,直接使用http协议请求接口。
思路
使用soapui客户端请求webservice,通过soapui工具,就可以了解Http协议的样子,然后就可以通过HttpClient客户端工具,直接用Http协议请求webservice。
步骤
这里我们以一个天气预报的webservice作为例子:
http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl
以wsdl创建soap项目:
打开一个请求接口例子:
使用soapui工具请求例子:
从这里就可以看出来,webservice实际上就是http请求。更加这个http请求,我们就可以直接使用任何一款http工具进行请求了。
http实现
httpclient核心调用方法如下:
static int socketTimeout = 30000;// 请求超时时间
static int connectTimeout = 30000;// 传输超时时间
public static String doPostSoap1_2(String postUrl, String soapXml,
String soapAction) throws Exception {
String retStr = "";
// 创建HttpClientBuilder
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
// HttpClient
CloseableHttpClient closeableHttpClient = httpClientBuilder.build();
HttpPost httpPost = new HttpPost(postUrl);
// 设置请求和传输超时时间
RequestConfig requestConfig = RequestConfig.custom()
.setSocketTimeout(socketTimeout)
.setConnectTimeout(connectTimeout).build();
httpPost.setConfig(requestConfig);
try {
httpPost.setHeader("Content-Type",
"application/soap+xml;charset=UTF-8");
httpPost.setHeader("Cache-Control",
"no-cache");
httpPost.setHeader("Pragma",
"no-cache");
httpPost.setHeader("SOAPAction", soapAction);
StringEntity data = new StringEntity(soapXml,
StandardCharsets.UTF_8);
httpPost.setEntity(data);
CloseableHttpResponse response = closeableHttpClient
.execute(httpPost);
HttpEntity httpEntity = response.getEntity();
if (httpEntity != null) {
// 打印响应内容
retStr = EntityUtils.toString(httpEntity, "UTF-8");
// logger.info("response:" + retStr);
}
// 释放资源
closeableHttpClient.close();
} catch (Exception e) {
throw e;
} finally {
if (closeableHttpClient != null){
closeableHttpClient.close();
}
}
return retStr;
}
该方法的具体使用如下:
result = doPostSoap1_2(wsdlUri, soapXml, "");
当前这个例子,之前使用的axis1.4客户端,所以,这里在原来的基础进行修改:
import org.apache.axis.Message;
import org.apache.axis.MessageContext;
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import org.apache.axis.description.OperationDesc;
import org.apache.axis.description.ParameterDesc;
import org.apache.axis.message.*;
import org.apache.axis.utils.Messages;
import org.apache.axis.utils.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import javax.xml.namespace.QName;
import javax.xml.rpc.JAXRPCException;
import javax.xml.rpc.ServiceException;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPException;
import java.nio.charset.StandardCharsets;
import java.rmi.RemoteException;
...
try {
Service s = new Service();
Call call = (Call) service.createCall();
call.setOperation(operation);
call.setTargetEndpointAddress(wsdlUri);
call.setTimeout(20000); // 1 second, in miliseconds
QName operationName = call.getOperationName();
RPCElement body = new RPCElement(operationName.getNamespaceURI(), operationName.getLocalPart(), getParamList(para, call));
MessageContext msgContext = call.getMessageContext();
SOAPEnvelope reqEnv =
new SOAPEnvelope(msgContext.getSOAPConstants(),
msgContext.getSchemaVersion());
body.setEncodingStyle(call.getEncodingStyle());
Message reqMsg = call.getResponseMessage();
call.setRequestMessage(reqMsg);
reqEnv.addBodyElement(body);
// result = (String) call.invoke(para);
// 弃用axis调用webservice,改用httpclient方式直接调用
result = doPostSoap1_2(wsdlUri, reqEnv.toString(), "");
/*
if (!StringUtils.isEmpty(result)){
int beginIndex = result.indexOf("<");
int endIndex = result.indexOf("</root>")+"</root>".length();
result = result.substring(beginIndex, endIndex)
.replace("&", "&")
.replace("<", "<")
.replace(">", ">")
.replace(""", "\"").replace("'", "'");
}*/
} catch (Exception e) {
throw e;
}
到这里就完成了Httpclient对axis1.4的替换。