一、背景
每个顾客都对应一个wsdl
二、实现原理
1、思路一:cxf JaxWsProxyFactoryBean 代理实现
通过把每个wsdl的配置信息提供给WsFactory动态生成client,缓存起来。然后根据传过来的类的信息反射调用方法。
参数有wsdl URL、接口类名、方法密码、参数类名、证书信息等
2、思路二:根据wsdl,为每个方法提供模板(velocity等),然后动态生成soap报文,通过httpClient调用wsdl的发布地址
三、思路一的代码实现
import java.io.Serializable;
/**
* WS 配置参数信息
*
*/
public class WsClientParams implements Serializable{
private static final long serialVersionUID = 5034854430789836177L;
/**
* 接口className
*/
private String interfaceName;
/**
* 调用方法名称
*/
private String methodName;
/**
* wsUrl
*/
private String wsUrl;
/**
* 请求参数
*/
private String requestData;
/**
* 参数实体类名
*/
private String requestClassName;
/**
* store证书路径
*/
private String storePath;
/**
* store证书密码
*/
private String storePwd;
/**
* trust证书路径
*/
private String trustPath;
/**
* trust证书密码
*/
private String trustPwd;
}
public class Holder<T> {
private volatile T value;
private volatile WsClientParams param;
public void set(T value) {
this.value = value;
}
public T get() {
return value;
}
public WsClientParams getParam() {
return param;
}
public void setParam(WsClientParams param) {
this.param = param;
}
}
import java.io.InputStream;
import java.security.KeyStore;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import org.apache.commons.lang3.StringUtils;
import org.apache.cxf.configuration.jsse.TLSClientParameters;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.apache.cxf.transport.http.HTTPConduit;
import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
import org.apache.poi.util.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class WsClientFactory {
private static final Logger LOGGER = LoggerFactory.getLogger(WsClientFactory.class);
private static final ConcurrentMap<String, Holder<Object>> cachedInstances = new ConcurrentHashMap<String, Holder<Object>>();
public static Object getClient(WsClientParams params) throws Exception {
String interfaceName = params.getInterfaceName();
Holder<Object> holder = cachedInstances.get(interfaceName);
if (holder == null) {
cachedInstances.putIfAbsent(interfaceName, new Holder<Object>());
holder = cachedInstances.get(interfaceName);
}
Object instance = holder.get();
if (instance == null) {
synchronized (holder) {
instance = holder.get();
if (instance == null) {
instance = createClient(params);
holder.set(instance);
holder.setParam(params);
}
}
}else {
synchronized (holder) {
if(isChange(params,holder)) {
instance = createClient(params);
holder.set(instance);
holder.setParam(params);
}
}
}
return instance;
}
private static boolean isChange(WsClientParams params,Holder<Object> holder) {
return !params.getWsUrl().equals(holder.getParam().getWsUrl());
}
private static Object createClient(WsClientParams params) throws Exception {
LOGGER.info("create ws Client...");
JaxWsProxyFactoryBean cxfFty = new JaxWsProxyFactoryBean();
Class<?> cz = Class.forName(params.getInterfaceName());
cxfFty.setServiceClass(cz);
cxfFty.setAddress(params.getWsUrl());
Object client = cxfFty.create();
if(StringUtils.isNotEmpty(params.getStorePath()) || StringUtils.isNotEmpty(params.getTrustPath())) {
Client proxy = ClientProxy.getClient(client);
HTTPConduit conduit = (HTTPConduit) proxy.getConduit();
HTTPClientPolicy policy = new HTTPClientPolicy();
TLSClientParameters tlsParams = conduit.getTlsClientParameters();
if (tlsParams == null) {
tlsParams = new TLSClientParameters();
}
if(StringUtils.isNotEmpty(params.getStorePath())) {
tlsParams.setKeyManagers(getKeyManagers(params.getStorePath(),params.getStorePwd()));
}
if(StringUtils.isNotEmpty(params.getTrustPath())) {
tlsParams.setTrustManagers(getTrustManagers(params.getTrustPath(),params.getTrustPwd()));
}
conduit.setTlsClientParameters(tlsParams);
conduit.setClient(policy);
}
return client;
}
public static KeyManager[] getKeyManagers(String path,String pwd) {
// 读取证书仓库输入流
InputStream is = null;
try {
// 信任仓库的默认算法X509
String alg = KeyManagerFactory.getDefaultAlgorithm();
// 获取信任仓库工厂
KeyManagerFactory factory = KeyManagerFactory.getInstance(alg);
// 读取信任仓库
is = WsClientFactory.class.getClassLoader().getResourceAsStream(path);
// 密钥类型
KeyStore ks = KeyStore.getInstance("JKS");
// 加载密钥
ks.load(is, pwd.toCharArray());
factory.init(ks,pwd.toCharArray());
KeyManager[] tms = factory.getKeyManagers();
return tms;
} catch (Exception e) {
LOGGER.error("wsClient_keyManager_init_error,STORE_CRE_path:"+path,e);
} finally {
IOUtils.closeQuietly(is);
}
return null;
}
public static TrustManager[] getTrustManagers(String path,String pwd) {
// 读取证书仓库输入流
InputStream is = null;
try {
// 信任仓库的默认算法X509
String alg = TrustManagerFactory.getDefaultAlgorithm();
// 获取信任仓库工厂
TrustManagerFactory factory = TrustManagerFactory.getInstance(alg);
// 读取信任仓库
is = WsClientFactory.class.getClassLoader().getResourceAsStream(path);
// 密钥类型
KeyStore ks = KeyStore.getInstance("JKS");
// 加载密钥
ks.load(is, pwd.toCharArray());
factory.init(ks);
TrustManager[] tms = factory.getTrustManagers();
return tms;
} catch (Exception e) {
LOGGER.error("wsClient_keyManager_init_error,TRUST_CRE_path:"+path,e);
} finally {
IOUtils.closeQuietly(is);
}
return null;
}
}
@Service
public class WsManager {
public Object execute(WsClientParams params) throws Exception {
Object client = WsClientFactory.getClient(params);
Object param = JaxbXmlUtil.xmlToBean(params.getRequestData(), Class.forName(params.getRequestClassName()));
return MethodUtils.invokeExactMethod(client, params.getMethodName(),param);
}
public static void main(String[] args) throws Exception {
WsClientParams params = new WsClientParams();
params.setInterfaceName("com.service.ReceivePortType");
params.setMethodName("receiveTnPayload");
params.setStorePath("keystore.jks");
params.setStorePwd("123456");
params.setTrustPath("test.truststore");
params.setTrustPwd("123456");
params.setWsUrl("http://localhost:9999/ws/receive");
String data = "参数转换后的xml文档";
params.setRequestClassName("com.dto.DocTradi");
params.setRequestData(data);
WsManager wsManager = new WsManager();
System.out.println(JSON.toJSONString(wsManager.execute(params)));
}
}