本人日常工作中经常与不同软件厂商进行接口对接,不同的厂商接口调用方式五花八门,但主要分为两大阵营:http和webservice。本文以Java为例,总结调用webservice服务的几种方式。
一、利用命令或工具将WebService提供的wsdl文件生成对应的java类,这样就可以像调用本地类一样调用webService提供的接口。这种方法的优点是调用简单,无需自己编写太多的东西。缺点同样很明显,生成的代码过于庞大,不便于阅读,显得很累赘。
二、AXIS远程调用,代码如下:
import ;
import ;
import ;
import ;
public class WebServiceTest {
public static void main(String[] args) {
//服务地址
String url = "http://127.0.0.1:8080/service-test/services/gateway?wsdl";
//命名空间
String namespaceURI = "/";
//方法名
String method = "invoke";
try {
Service service = new Service();
Call call = (Call) ();
(url);
//设置要调用的方法
(new QName(namespaceURI, method));
//设置要返回的数据类型
(new QName(namespaceURI, method), );
(true);
(namespaceURI + method);
//设置入参
(new QName(namespaceURI, "consumer"), Constants.XSD_STRING, );
(new QName(namespaceURI, "serviceName"), Constants.XSD_STRING, );
(new QName(namespaceURI, "params"), Constants.XSD_STRING, );
//调用方法并传递参数
String resultStr = (String) (new Object[]{"test", "queryOrder", "{\"tradeno\":\"1648100061001\",\"mchid\":\"10001\"}"});
("服务调用结果:" + resultStr);
} catch (Exception e) {
();
}
}
}
对应jar包的maven依赖:
<dependency>
<groupId></groupId>
<artifactId>axis</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId></groupId>
<artifactId>axis-jaxrpc</artifactId>
<version>1.4</version>
</dependency>
该种方式调用简单,一般不需要自己组织请求报文和解析返回报文 。
三、通过HttpURLConnection进行调用,代码如下:
import ;
import ;
import ;
import ;
import ;
import ;
public class WebServiceTest {
public static void main(String[] args) throws Exception {
//服务地址
String url = "http://127.0.0.1:8080/service-test/services/gateway?wsdl";
//第一步:创建服务地址
URL httpUrl = new URL(url);
//第二步:打开一个通向服务地址的连接
HttpURLConnection connection = (HttpURLConnection) ();
//第三步:设置参数
//3.1发送方式设置:POST必须大写
("POST");
//3.2设置数据格式:content-type,这个根据实际情况来确定
("content-type", "application/atom+xml;charset=utf-8");
//3.3设置输入输出,因为默认新创建的connection没有读写权限,
(true);
(true);
//第四步:组织SOAP数据,发送请求
String soapXML = getXML("test", "queryOrder", "{\"tradeno\":\"1648100061003\",\"mchid\":\"10001\"}");
//将信息以流的方式发送出去
OutputStream os = ();
(());
//第五步:接收服务端响应,打印
InputStream is = ();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
StringBuilder sb = new StringBuilder();
String temp = null;
while(null != (temp = ())){
(temp);
}
("服务调用结果:" + ());
();
();
();
}
/**
* @Author admin
* @Description 组装xml报文
* @Date 15:47 2022/5/1
* @Param [consumer, serviceName, para]
* @return
**/
public static String getXML(String consumer, String serviceName, String paraStr){
String soapXML = "<soapenv:Envelope xmlns:soapenv=\"/soap/envelope/\" xmlns:dar=\"/\">\n" +
" <soapenv:Header/>\n" +
" <soapenv:Body>\n" +
" <dar:invoke>\n" +
" <!--Optional:-->\n" +
" <dar:consumerId>" + consumer + "</dar:consumerId>\n" +
" <!--Optional:-->\n" +
" <dar:serviceName>" + serviceName + "</dar:serviceName>\n" +
" <!--Optional:-->\n" +
" <dar:params>" + paraStr + "</dar:params>\n" +
" </dar:invoke>\n" +
" </soapenv:Body>\n" +
"</soapenv:Envelope>";
return soapXML;
}
}
该种方式一般需要自己组织请求的xml报文,自己解析返回的xml报文。
四、通过HttpClient进行调用,代码如下:
import ;
import ;
import ;
import ;
import ;
import ;
public class WebServiceTest {
public static void main(String[] args) throws Exception {
//服务地址
String url = "http://127.0.0.1:8080/service-test/services/gateway?wsdl";
HttpClient httpClient = new HttpClient();
PostMethod postMethod = new PostMethod(url);
String soap = getXML("test", "queryOrder", "{\"tradeno\":\"1648100061003\",\"mchid\":\"10001\"}");
try {
byte[] b = ("utf-8");
InputStream is = new ByteArrayInputStream(b, 0, );
RequestEntity re = new InputStreamRequestEntity(is, ,
"application/atom;charset=utf-8");
(re);
(postMethod);
String soapResponseData = ();
("服务调用结果:" + soapResponseData);
();
} catch (Exception e) {
();
}
}
/**
* @Author admin
* @Description 组装xml报文
* @Date 15:47 2022/5/1
* @Param [consumer, serviceName, para]
* @return
**/
public static String getXML(String consumer, String serviceName, String paraStr){
String soapXML = "<soapenv:Envelope xmlns:soapenv=\"/soap/envelope/\" xmlns:dar=\"/\">\n" +
" <soapenv:Header/>\n" +
" <soapenv:Body>\n" +
" <dar:invoke>\n" +
" <!--Optional:-->\n" +
" <dar:consumerId>" + consumer + "</dar:consumerId>\n" +
" <!--Optional:-->\n" +
" <dar:serviceName>" + serviceName + "</dar:serviceName>\n" +
" <!--Optional:-->\n" +
" <dar:params>" + paraStr + "</dar:params>\n" +
" </dar:invoke>\n" +
" </soapenv:Body>\n" +
"</soapenv:Envelope>";
return soapXML;
}
}
该方式的特点同方式三。
五、通过CloseableHttpClient进行调用,代码如下:
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
public class WebServiceTest {
public static void main(String[] args) throws Exception {
//服务地址
String url = "http://127.0.0.1:8080/service-test/services/gateway?wsdl";
int timeout = 180000;
CloseableHttpClient httpClient = ();
RequestConfig defaultRequestConfig = ().setConnectTimeout(timeout).setConnectionRequestTimeout(timeout).setSocketTimeout(timeout).build();
HttpPost httpPost = null;
CloseableHttpResponse response = null;
HttpEntity resEntity = null;
try {
httpPost = new HttpPost(url);
(defaultRequestConfig);
String xmlStr = getXML("test", "queryOrder", "{\"tradeno\":\"1648100061003\",\"mchid\":\"10001\"}");
(new StringEntity(xmlStr, Consts.UTF_8));
response = (httpPost);
resEntity = ();
String resStr = (resEntity, Consts.UTF_8);
(resEntity);
("服务调用结果:" + resStr);
} catch (Exception e) {
();
} finally {
try {
if (response != null) {
();
}
} catch (IOException var21) {
();
}
}
}
/**
* @Author admin
* @Description 组装xml报文
* @Date 15:47 2022/5/1
* @Param [consumer, serviceName, para]
* @return
**/
public static String getXML(String consumer, String serviceName, String paraStr){
String soapXML = "<soapenv:Envelope xmlns:soapenv=\"/soap/envelope/\" xmlns:dar=\"/\">\n" +
" <soapenv:Header/>\n" +
" <soapenv:Body>\n" +
" <dar:invoke>\n" +
" <!--Optional:-->\n" +
" <dar:consumerId>" + consumer + "</dar:consumerId>\n" +
" <!--Optional:-->\n" +
" <dar:serviceName>" + serviceName + "</dar:serviceName>\n" +
" <!--Optional:-->\n" +
" <dar:params>" + paraStr + "</dar:params>\n" +
" </dar:invoke>\n" +
" </soapenv:Body>\n" +
"</soapenv:Envelope>";
return soapXML;
}
}
该方式的特点同方式三。
六、使用XFire调用,代码如下:
import ;
import ;
public class WebServiceTest {
public static void main(String[] args) {
try {
//服务地址
String url = "http://127.0.0.1:8080/service-test/services/gateway?wsdl";
//方法名
String method = "invoke";
Client client = new Client(new URL(url));
Object[] result = (method, new Object[]{"test", "queryOrder", "{\"tradeno\":\"1648100061003\",\"mchid\":\"10001\"}"});
("服务调用结果:" + result[0]);
} catch (Exception e) {
();
}
}
}
需要xfire-all-1.2.包,maven依赖如下:
<dependency>
<groupId></groupId>
<artifactId>xfire-all</artifactId>
<version>1.2.6</version>
</dependency>
该方式比较古老了,本文只做介绍,后面都用新版本CXF了。值得一提的是,在测试该方式的时候报了一个错误,如下:
Exception in thread "main" : ()Lorg/apache/ws/commons/schema/XmlSchemaObjectCollection;
at .(:662)
at .(:582)
at .(:392)
at .(:195)
at (:264)
at .<init>(:236)
at .<init>(:246)
方法不存在,原因其实是包冲突,xfire所依赖的低版本的XmlSchema-1.与cxf所依赖的高版本的xmlschema-core-2.2.冲突,删掉高版本的就解决了。
七、通过CXF调用,代码如下:
import ;
import ;
public class WebServiceTest {
public static void main(String[] args) {
//服务地址
String url = "http://127.0.0.1:8080/service-test/services/gateway?wsdl";
//方法名
String method = "invoke";
try {
DynamicClientFactory factory = ();
Client client = (url);
Object[] resultObject = (method, new Object[]{"test", "queryOrder", "{\"tradeno\":\"1648100061003\",\"mchid\":\"10001\"}"});
String resultStr = resultObject[0].toString(); //接口调用结果
("服务调用结果:" + resultStr);
} catch (Exception e) {
();
}
}
}
该种方式一般不需要自己组织请求报文和解析返回报文,比较简单。
总结,以上七种方式各有特点,推荐使用AXIS方式或CXF方式或者HTTP方式中的其中一种。