使用Eclipse自动生成Soap Client的代码
在项目按右键,选择New -> Other ->Web Services -> Web Service Client,进入向导。
加入自有代码,例如加入Envelope Header
在xxxxStub.java文件相应的方法中加入:
public com.example.api.ApiStatus.EchoResponse echo(com.example.api.ApiStatus.Echo echo) throws java.rmi.RemoteException {
if (super.cachedEndpoint == null) {
throw new org.apache.axis.NoEndPointException();
}
org.apache.axis.client.Call _call = createCall();
_call.setOperation(_operations[0]);
_call.setUseSOAPAction(true);
_call.setSOAPActionURI("");
_call.setEncodingStyle(null);
_call.setProperty(org.apache.axis.client.Call.SEND_TYPE_ATTR, Boolean.FALSE);
_call.setProperty(org.apache.axis.AxisEngine.PROP_DOMULTIREFS, Boolean.FALSE);
_call.setSOAPVersion(org.apache.axis.soap.SOAPConstants.SOAP11_CONSTANTS);
_call.setOperationName(new javax.xml.namespace.QName("", "echo"));
setRequestHeaders(_call);
setAttachments(_call);
//这里是加入的Header的内容
SoapUtils.addAuthSoapHeader(_call);
try {
。。。。。。
public class SoapUtils {
private static final Logger log = LogManager.getLogger();
private static SOAPFactory soapFactory;
static{
try {
soapFactory = SOAPFactory.newInstance();
} catch (SOAPException e) {
log.fatal("[FATAL] create SOAP Factory error : {}",e.toString());
}
}
private static SOAPHeaderElement createDcpSoapHeader(String userName, String password){
try {
String AUTH_PREFIX = "wsse";
String AUTH_NS = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
SOAPElement wsSecHeaderElm = soapFactory.createElement("Security", AUTH_PREFIX, AUTH_NS);
SOAPElement userNameTokenElm = soapFactory.createElement("UsernameToken", AUTH_PREFIX, AUTH_NS);
SOAPElement userNameElm = soapFactory.createElement("Username", AUTH_PREFIX, AUTH_NS);
SOAPElement passwdElm = soapFactory.createElement("Password", AUTH_PREFIX, AUTH_NS);
userNameElm.addTextNode(userName);
passwdElm.addTextNode(password);
userNameTokenElm.addChildElement(userNameElm);
userNameTokenElm.addChildElement(passwdElm);
wsSecHeaderElm.addChildElement(userNameTokenElm);
SOAPHeaderElement soapHeaderElement = new SOAPHeaderElement(wsSecHeaderElm);
soapHeaderElement.setMustUnderstand(true);
return soapHeaderElement;
} catch (Exception e) {
return null;
}
}
public static void addAuthSoapHeader(org.apache.axis.client.Call call,String userName, String password){
SOAPHeaderElement header = createDcpSoapHeader(userName,password);
if(header != null)
call.addHeader(header);
}
}
更好的方式还可以参考 Web Service SOAP Client 设置 SOAP Header,那里给出更通用的解决方式,而这里需要对每个接口都进行设置。主要是了解一下soap client的代码。
网络出现问题,多次重发的实现
利用Java的Function类,在SoapUtils实现通用的多次重发方法。
public class SoapUtils {
private static final Logger log = LogManager.getLogger();
......
//在log上显示错误,并判断是否因为网络连接问题而需要重复
public static boolean showAndCheckRetryEAxisFault(Exception e){
if( e instanceof ConnectException)
return true;
if( e instanceof AxisFault){
AxisFault fault = (AxisFault)e;
if(fault.getFaultString().startsWith("java.net.ConnectException"))
return true;
log.error( fault.dumpToString());
return false;
}
return false;
}
//在log上显示错误
public static void showAxisFault(Exception e){
if( e instanceof AxisFault){
AxisFault fault = (AxisFault)e;
log.error( fault.dumpToString());
}
}
// 根据重复后退的retriesDelay参数,在网络出现故障时,进行重复。其中SoapUtils.ThrowingFunction<T, R> func就是soap proxy中的具体某个方法。这个func因为抛出异常,不能直接使用Function<T,R>,需要通过ThrowingFunction<T,R> extends Function<T,R>来实现。
public static <T, R> R funcApplyWithThrow(SoapUtils.ThrowingFunction<T, R> func,T param, Long ... retriesDelay) throws AxisFault,Exception{
if(retriesDelay != null){
for(int i = 0 ; i< retriesDelay.length ; i ++){
try {
return func.applyThrows(param);
} catch (Exception e) {
if(!SoapUtils.showAndCheckRetryEAxisFault(e))
throw e;
log.debug("Try to fix {}, resend({}) after {}ms", e.toString(), i+1, retriesDelay[i]);
}
NormalUtils.sleep(retriesDelay[i]);
}
}
try{
return func.applyThrows(param);
}catch(Exception e){
SoapUtils.showAxisFault(e);
throw e;
}
}
//参考slieb.org/blog/throwable-interfaces/
@FunctionalInterface
public static interface ThrowingFunction<T,R> extends Function<T,R> {
@Override
default R apply(T t){
try{
return applyThrows(t);
}catch (RemoteException e){
throw new RuntimeException(e);
}
}
R applyThrows(T t) throws RemoteException;
}
}
具体某个重发的实现:
private final MySoapProxy proxy = new MySoapProxy(url);
@Override
public QueryResponse query(Long ...retriesDelay) throws AxisFault,Exception{
QueryParam param = new QueryParam();
return SoapUtils.funcApplyWithThrow(proxy::query, param, retriesDelay);
}