以下工具集成了多种方式调用webservice,如http方式,axis方式,动态生成客户端方式等 ,是为笔者实际工作中提炼的,方便大家直接套用,常用方法都有调用示列。
一、整个工具类代码
java">package ***.gykjit.spd.edi.util;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynami***lientFactory;
import org.apache.cxf.transport.http.HTTPConduit;
import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import org.apache.axis.encoding.XMLType;
import org.apache.axis.encoding.ser.BeanDeserializerFactory;
import org.apache.axis.encoding.ser.BeanSerializerFactory;
import org.apache.axis.message.SOAPHeaderElement;
import org.apache.axis.types.Schema;
import org.apache.***mons.collections.MapUtils;
import ***.google.***mon.collect.Lists;
import org.springframework.util.StringUtils;
import javax.xml.namespace.QName;
import javax.xml.rpc.ParameterMode;
import java.io.*;
import java.***.HttpURLConnection;
import java.***.URL;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
/**
* @author hulei
* @Date 2022/9/8 18:31
*/
public class WebServiceUtil {
private final static Logger log = LoggerFactory.getLogger(WebServiceUtil.class);
/**
*
* @param url
* @param soapActionURI
* @param nameSpace
* @param operationName
* @param params
* @param clazz
* @param <T>
* @return
*/
@SuppressWarnings("unchecked")
public static <T> T call(String url,String soapActionURI, String nameSpace,String operationName, Map<String, String> params, Class<T> clazz) {
soapActionURI = StringUtils.isEmpty(soapActionURI)? nameSpace + operationName :soapActionURI;
try {
Service service = new Service();
SOAPHeaderElement header = new SOAPHeaderElement(nameSpace, operationName);
header.setNamespaceURI(nameSpace);
Call call = (Call) service.createCall();
call.setTargetEndpointAddress(url);
call.setOperationName(new QName(nameSpace, operationName));
// 添加参数
List<String> parameterList = Lists.newArrayList();
if (params != null) {
Set<String> paramsKey = params.keySet();
for (String key : paramsKey) {
call.addParameter(new QName(nameSpace, key), XMLType.XSD_STRING, ParameterMode.IN);
String pValue = MapUtils.getString(params, key);
header.addChildElement(key).setValue(pValue);
parameterList.add(pValue);
}
}
call.setUseSOAPAction(true);
call.setSOAPActionURI(soapActionURI);
call.addHeader(header);
//进行序列化 实体类也要序列化 implements Serializable
call.registerTypeMapping(clazz, new QName(nameSpace, soapActionURI),
new BeanSerializerFactory(clazz, new QName(nameSpace, soapActionURI)),
new BeanDeserializerFactory(clazz, new QName(nameSpace, soapActionURI)));
//设置输出的类
call.setReturnClass(clazz);
// 接口返回结果
T result = (T) call.invoke(parameterList.toArray());
log.info("调用 WebService 接口返回===>" + result);
return result;
} catch (Exception e) {
log.error("调用 WebService 接口错误信息==>" + e.getMessage());
}
return null;
}
/**
*
* @param url
* @param soapActionURI
* @param nameSpace
* @param operationName
* @param params
* @return
*/
public static String call(String url,String soapActionURI,String nameSpace,String operationName, Map<String, String> params) {
soapActionURI = StringUtils.isEmpty(soapActionURI)? nameSpace + operationName :soapActionURI;
try {
Service service = new Service();
SOAPHeaderElement header = new SOAPHeaderElement(nameSpace, operationName);
header.setNamespaceURI(nameSpace);
Call call = (Call) service.createCall();
call.setTargetEndpointAddress(url);
call.setOperationName(new QName(nameSpace, operationName));
// 添加参数
List<String> parameterList = Lists.newArrayList();
if (params != null) {
Set<String> paramsKey = params.keySet();
for (String key : paramsKey) {
call.addParameter(new QName(nameSpace, key), XMLType.XSD_STRING, ParameterMode.IN);
String pValue = MapUtils.getString(params, key);
header.addChildElement(key).setValue(pValue);
parameterList.add(pValue);
}
}
call.setUseSOAPAction(true);
call.setSOAPActionURI(soapActionURI);
call.addHeader(header);
// 设置返回类型
call.setReturnType(new QName(nameSpace, operationName), String.class);
// 接口返回结果
String result = (String) call.invoke(parameterList.toArray());
log.info("调用 WebService 接口返回===>" + result);
return result;
} catch (Exception e) {
log.error("调用 WebService 接口错误信息==>" + e.getMessage());
}
return null;
}
/**
* 设置参数模式(IN,OUT)
* @param url
* @param soapActionURI
* @param nameSpace
* @param operationName
* @param params
* @param ParameterModeType 参数模式(IN,OUT)
* @return
*/
public static String callAndSetParameterModeType(String url,String soapActionURI,String nameSpace,String operationName, Map<String, String> params,
Map<String,String> ParameterModeType) {
soapActionURI = StringUtils.isEmpty(soapActionURI)? nameSpace + operationName :soapActionURI;
try {
Service service = new Service();
SOAPHeaderElement header = new SOAPHeaderElement(nameSpace, operationName);
header.setNamespaceURI(nameSpace);
Call call = (Call) service.createCall();
call.setTargetEndpointAddress(url);
call.setOperationName(new QName(nameSpace, operationName));
// 添加参数
List<String> parameterList = Lists.newArrayList();
//设置参数模式处理函数
Function<String,ParameterMode> function = (key)->{
if("OUT".equals(key)){
return ParameterMode.OUT;
}
return ParameterMode.IN;
};
if (params != null) {
Set<String> paramsKey = params.keySet();
for (String key : paramsKey) {
call.addParameter(new QName(nameSpace, key), XMLType.XSD_STRING,function.apply(MapUtils.getString(ParameterModeType, key)));
String pValue = MapUtils.getString(params, key);
header.addChildElement(key).setValue(pValue);
parameterList.add(pValue);
}
}
call.setUseSOAPAction(true);
call.setSOAPActionURI(soapActionURI);
call.addHeader(header);
// 设置返回类型
call.setReturnType(new QName(nameSpace, operationName), String.class);
// 接口返回结果
String result = (String) call.invoke(parameterList.toArray());
log.info("调用 WebService 接口返回===>" + result);
return result;
} catch (Exception e) {
log.error("调用 WebService 接口错误信息==>" + e.getMessage());
}
return null;
}
/**
* WebService - 调用接口
*
* @param operationName 函数名
* @param params 参数
* @return 返回结果(String)
*/
public static String callReturnSchema(String url,String soapActionURI,String nameSpace,String operationName, Map<String, String> params) {
soapActionURI = StringUtils.isEmpty(soapActionURI)? nameSpace + operationName :soapActionURI;
try {
Service service = new Service();
SOAPHeaderElement header = new SOAPHeaderElement(nameSpace, operationName);
header.setNamespaceURI(nameSpace);
Call call = (Call) service.createCall();
call.setTargetEndpointAddress(url);
call.setOperationName(new QName(nameSpace, operationName));
// 添加参数
List<String> parameterList = Lists.newArrayList();
if (params != null) {
Set<String> paramsKey = params.keySet();
for (String key : paramsKey) {
call.addParameter(new QName(nameSpace, key), XMLType.XSD_STRING, ParameterMode.IN);
String pValue = MapUtils.getString(params, key);
header.addChildElement(key).setValue(pValue);
parameterList.add(pValue);
}
}
call.setUseSOAPAction(true);
call.setSOAPActionURI(soapActionURI);
call.addHeader(header);
// 设置返回类型
call.setReturnType(XMLType.XSD_SCHEMA);
// 接口返回结果
Schema schemaResult = (Schema)call.invoke(parameterList.toArray());
StringBuilder result = new StringBuilder();
for(int i = 0; i<schemaResult.get_any().length; i++){
result.append(schemaResult.get_any()[i]);
}
log.error("调用 WebService 接口返回===>" + result);
return result.toString();
} catch (Exception e) {
log.error("调用 WebService 接口错误信息==>" + e.getMessage());
}
return null;
}
/**
* 动态调用webService
* @param url
* @param operationName
* @param params
* @return
* @throws Exception
*/
public static Object dcfSoap(String url, String operationName, String... params) throws Exception {
/// 创建动态客户端
JaxWsDynami***lientFactory dcf = JaxWsDynami***lientFactory.newInstance();
Client client = dcf.createClient(url);
//超时等待设置,防止处理时间过长断开连接
HTTPConduit conduit = (HTTPConduit) client.getConduit();
HTTPClientPolicy policy = new HTTPClientPolicy();
long timeout = 10 * 60 * 1000;
policy.setConnectionTimeout(timeout);//连接时间
policy.setReceiveTimeout(timeout);//接受时间
conduit.setClient(policy);
// 需要密码的情况需要加上用户名和密码
// client.getOutInterceptors().add(new ClientLoginInterceptor(USER_NAME, PASS_WORD));
Object[] objects;
try {
// invoke("方法名",参数1,参数2,参数3....);
//这里注意如果是复杂参数的话,要保证复杂参数可以序列化
objects = client.invoke(operationName, (Object) params);
System.out.println("返回数据:" + objects[0]);
} catch (java.lang.Exception e) {
log.info("返回数据异常:"+e.getMessage());
return e.getMessage();
}
return objects[0];
}
/**
* http方式调用webService
* @param wsdlUrl 远程地址
* @param SOAPAction 标识http请求目的地
* @param soapXml 请求参数
* @return 返回的是soap报文(可用dom4j解析)
*/
public static String HttpSendSoapPost(String wsdlUrl,String SOAPAction,String soapXml){
HttpURLConnection connection = null;
InputStream is = null;
BufferedReader br = null;
String result = null;// 返回结果字符串
OutputStream out;
try {
// 创建远程url连接对象
URL url = new URL(wsdlUrl);
// 通过远程url连接对象打开一个连接,强转成httpURLConnection类
connection = (HttpURLConnection) url.openConnection();
// 设置连接方式:GET,POST
connection.setRequestMethod("POST");
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "text/xml;charset=utf-8");
//这里必须要写,否则出错,根据自己的要求写,默认为空
connection.setRequestProperty("SOAPAction", SOAPAction != null ? SOAPAction : "");
// 设置连接主机服务器的超时时间:15000毫秒
connection.setConnectTimeout(15000);
// 设置读取远程返回的数据时间:200000毫秒
connection.setReadTimeout(200000);
// 发送请求
connection.connect();
out = connection.getOutputStream(); // 获取输出流对象
connection.getOutputStream().write(soapXml.getBytes(StandardCharsets.UTF_8)); // 将要提交服务器的SOAP请求字符流写入输出流
out.flush();
out.close();
// 通过connection连接,获取输入流
if (connection.getResponseCode() == 200) {
is = connection.getInputStream();
// 封装输入流is,并指定字符集
br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
// 存放数据
StringBuilder sbf = new StringBuilder();
String temp;
while ((temp = br.readLine()) != null) {
sbf.append(temp);
sbf.append("\r\n");
}
result = sbf.toString();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 关闭资源
if (null != br) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != is) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// 关闭远程连接
if(connection != null){
connection.disconnect();
}
}
return result;
}
public static String sendWebService(String url, String xml) {
try {
URL soapUrl = new URL(url);
HttpURLConnection connection = (HttpURLConnection) soapUrl.openConnection();
connection.setRequestMethod("POST");
connection.setUseCaches(false);
//设置输入输出,新创建的connection默认是没有读写权限的
connection.setDoInput(true);
connection.setDoOutput(true);
//这里设置请求头类型为xml,传统http请求的是超文本传输格式text/html
connection.setRequestProperty("Content-Type", "text/xml; charset=utf-8");
connection.getOutputStream().write(xml.getBytes(StandardCharsets.UTF_8)); // 将要提交服务器的SOAP请求字符流写入输出流
log.info("写入xml入参:{}", xml);
InputStream inputStream = connection.getInputStream();
if (inputStream != null) {
byte[] bytes;
bytes = new byte[inputStream.available()];
int result = inputStream.read(bytes);
if(result == -1){
log.info("流读取完毕!");
}
//将字节数组转换为字符串输出
return new String(bytes, StandardCharsets.UTF_8);
}
} catch (Exception e) {
log.info("sendWebService方法报错:{}", e.getMessage());
return null;
}
return null;
}
}
二、pom依赖引入
可能有复制多了的依赖,可自己尝试去除,工具类不飘红报错就行
<dependency> <groupId>javax.jws</groupId> <artifactId>javax.jws-api</artifactId> <version>1.1</version> </dependency> <dependency> <groupId>javax.xml.ws</groupId> <artifactId>jaxws-api</artifactId> <version>2.3.1</version> </dependency> <dependency> <groupId>***.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.4.1</version> </dependency> <dependency> <groupId>***.sun.xml.bind</groupId> <artifactId>jaxb-xjc</artifactId> <version>2.2.11</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-transports-http</artifactId> <version>3.1.11</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxws</artifactId> <version>3.1.11</version> </dependency> <!--axis--> <dependency> <groupId>org.apache.axis</groupId> <artifactId>axis</artifactId> <version>1.4</version> </dependency> <dependency> <groupId>org.apache.axis</groupId> <artifactId>axis-jaxrpc</artifactId> <version>1.4</version> </dependency> <dependency> <groupId>org.dom4j</groupId> <artifactId>dom4j</artifactId> <version>2.1.1</version> </dependency> <dependency> <groupId>jaxen</groupId> <artifactId>jaxen</artifactId> <version>1.2.0</version> </dependency>
三、方法调用示列详解
3.1 以下调用的是工具类第二个方法,返回的是string字符串,具体是json还是xml,按照实际情况解析就行
具体参数解释
* @param url 第三方服务地址 * @param soapActionURI 自行百度soapAction * @param nameSpace 命名空间,自行百度soap * @param operationName 调用方法名 * @param params 调用参数,示例的参数名是xml
3.2 接着是 dcfSoap()方法
* 动态调用webService * @param url 第三方服务地址 * @param operationName 方法名 * @param params 动态参数,可以写多个
3.3 HttpSendSoapPost(此方法最常用,但是报文头需要自己拼,我一般用soapUI工具连好对方服务,会自动生成,参数自己拼接上,这个调用不太会出现一些乱七八糟的问题)
1是构建xml,2是把xml放在soapui生成的报文头的参数里,3直接调用工具类发送
实在不会调用的,评论区找我吧