使用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()); } } //参考http://blog.csdn.net/oscar999/article/details/40340819 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); }
相关链接:我的Professional Java for Web Applications相关文章