Webservice接口对接

 

  因为近期处理了很多关于Webservice的接口对接,所以这篇文章是对近期自己的学习做一个简单的总结。

  对于接口对接,建议首先需要了解一下WSDL文件,以及入参的SOAP报文的阅读,各节点的含义。有时候对接的开发直接扔给你一个wsdl服务文件,或者一串soap报文让你调用,这种情况下,如果不了解如何阅读该文件包括相关节点的含义,就会很尴尬;其次,需要问清楚接口提供方,对方的接口有没有访问认证等,如果没有,可以采用自动生成客户端的形式处理,这种方式不再赘述,网上有一大堆的资料。我这里介绍一下我遇到的需要接口认证的方式,废话少说直接看代码:

  1.  
  1. //直接AXIS调用
  1. public class WebserviceUtil {
  2. public static String getResult(ServiceInfoDto serviceInfoDto, String jsoninfo)
  3. throws ServiceException, MalformedURLException, RemoteException, SOAPException {
  4. //调用接口//标识Web Service的具体路径
  5. String endpoint = serviceInfoDto.getEndpoint();
  6. String namespace = serviceInfoDto.getNamespace();
  7. String soapaction = serviceInfoDto.getSoapaction();
  8. String username = new String("***");
  9. String password = new String("***");
  10. String HU_SENDR = new String("***");
  11. String HU_JSON = jsoninfo;
  12. String result = "";
  13. try {
  14. // 创建 Service实例
  15. Service service = new Service();
  16. QName qname = new QName(namespace, serviceInfoDto.getLocalPart());
  17. // 通过Service实例创建Call的实例
  18. Call call = (Call) service.createCall(); //为Call设置服务的位置
  19. call.setTargetEndpointAddress(endpoint);
  20. call.setOperationName(qname);
  21. call.setEncodingStyle("UTF-8");
  22. call.setSOAPActionURI(soapaction);
  23. call.setUsername(username);
  24. call.setPassword(password);
  25. call.addParameter(new QName("HU_JSON"),
  26. org.apache.axis.encoding.XMLType.XSD_STRING,
  27. javax.xml.rpc.ParameterMode.IN);
  28. call.addParameter(new QName("HU_SENDR"),
  29. org.apache.axis.encoding.XMLType.XSD_STRING,
  30. javax.xml.rpc.ParameterMode.IN);
  31. call.setReturnType(XMLType.XSD_STRING); // 返回值类型:String
  32. Object[] obj = {HU_JSON, HU_SENDR};
  33. result = (String) call.invoke(obj);// 远程调用
  34. // System.out.println("result is " + result);
  35. } catch (Exception e) {
  36. e.printStackTrace();
  37. }
  38. return result;
  39. }
  40. }
  1. public class ServiceInfoDto {
  2. private String endpoint;
  3. private String namespace;
  4. private String soapaction;
  5. private String localPart;
  6. public String getEndpoint() {
  7. return endpoint;
  8. }
  9. public void setEndpoint(String endpoint) {
  10. this.endpoint = endpoint;
  11. }
  12. public String getNamespace() {
  13. return namespace;
  14. }
  15. public void setNamespace(String namespace) {
  16. this.namespace = namespace;
  17. }
  18. public String getSoapaction() {
  19. return soapaction;
  20. }
  21. public void setSoapaction(String soapaction) {
  22. this.soapaction = soapaction;
  23. }
  24. public String getLocalPart() {
  25. return localPart;
  26. }
  27. public void setLocalPart(String localPart) {
  28. this.localPart = localPart;
  29. }
  30. }
  1. 解读一下入参和几个重要的参数:
  2. ServiceInfoDto对象:是对相关节点入参的汇总,这里的endpointnamespacesoapactionlocalPart在对方提供的wsdl文件中都可查到;
  3. jsoninfo:接口方要求的入参对象(转成json字符串形式入参)
  4. String username = new String("***"); 接口方提供的认证登录名(不需要可忽略)
  5. String password = new String("***"); 接口方提供的认证登录密码(不需要可忽略)
  6. String HU_SENDR = new String("***"); HU_SENDR需要按对方要求的字段名称处理,入参值接口方提供(不需要可忽略);
  7. String HU_JSON = jsoninfo;HU_JSON;需要按对方要求的字段名称处理,入参值是前面处理过的json对象;
  1. 第二种对接是拼接SOAP报文入参,并且解析返回的SOAP报文,获取返回信息;
    这种方式必须要清楚的知道对方入参的soap报文格式,相关节点一定要清晰,拿到对方的报文信息进行拼接即可:
    soap报文拼接,由于我用到的地方比较多,所以提取的代码块处理
  1. public class SoapAppendXml {
  2. public static StringBuffer soapXml(String arg2,String arg4,String method,String id) {
  3. StringBuffer sendSoapString = new StringBuffer();
  4. sendSoapString.append("<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:web=\"http://webservice.**.com/\">");
  5. sendSoapString.append(" <soapenv:Header/>");
  6. sendSoapString.append(" <soapenv:Body>");
  7. sendSoapString.append(" <web:"+method+">");
  8. sendSoapString.append(" <arg0>*</arg0>");
  9. sendSoapString.append(" <arg1>false</arg1>");
  10. sendSoapString.append(" <arg2>"+arg2+"</arg2>");
  11. sendSoapString.append(" <arg3>[]</arg3>");
  12. sendSoapString.append(" <arg4>"+arg4+"</arg4>");
  13. sendSoapString.append(" </web:"+method+">");
  14. sendSoapString.append(" </soapenv:Body>");
  15. sendSoapString.append("</soapenv:Envelope>");
  16. return sendSoapString;
  17. }
  18. }

    入参可根据实际接口的需要进行修改,各节点可查看接口的soap入参要求,动态处理或者写死都行;
    由于我的调用服务只有一个,并且有多个方法,所以入参method需要动态处理;

下面是接口调用:

  1. public class SoapUtil {
  2. public static String getWebServiceAndSoap(String url,String isClass,String isMethod,StringBuffer sendSoapString) throws IOException {
  3. String result = "";
  4. String soap = sendSoapString.toString();
  5. if (soap == null) {
  6. return null;
  7. }
  8. URL soapUrl = new URL(url);
  9. URLConnection conn = soapUrl.openConnection();
  10. conn.setUseCaches(false);
  11. conn.setDoInput(true);
  12. conn.setDoOutput(true);
  13. conn.setRequestProperty("Content-Length",
  14. Integer.toString(soap.length()));
  15. conn.setRequestProperty("Content-Type", "text/xml; charset=utf-8");
  16. // 调用的接口方法是
  17. conn.setRequestProperty(isClass,isMethod);
  18. OutputStream os = conn.getOutputStream();
  19. OutputStreamWriter osw = new OutputStreamWriter(os, "utf-8");
  20. osw.write(soap);
  21. osw.flush();
  22. osw.close();
  23. // 获取webserivce返回的流
  24. InputStream is = conn.getInputStream();
  25. if (is!=null) {
  26. byte[] bytes = new byte[0];
  27. bytes = new byte[is.available()];
  28. is.read(bytes);
  29. String str = new String(bytes);
  30. return str;
  31. }else {
  32. return null;
  33. }
  34. }
    }
  1. 解读一下上面的工具类:
  1. url:是对接服务地址,以"?wsdl"结尾的地址;
  1. isClass:接口类名,在对方提供的wsdl文件中可以查到,我这里的是"LvYunkangWebservice"
  1. isMethod:调用方法名
  1. sendSoapString:拼接好的soap报文

    该工具类在实际测试中,发现最终返回的报文,会出现乱码现象,查阅得知,应该是跟InputStream按字节解析有关。所以,对上述工具类进行简单的修改,也就是对返回结果部分做一下修改(标红的部分)


  1. public class SoapUtil {

    public static String getWebServiceAndSoap(String url,String isClass,String isMethod,StringBuffer sendSoapString) throws IOException {
    String result = "";
    String soap = sendSoapString.toString();
    if (soap == null) {
    return null;
    }
    URL soapUrl = new URL(url);
    URLConnection conn = soapUrl.openConnection();
    conn.setUseCaches(false);
    conn.setDoInput(true);
    conn.setDoOutput(true);
    conn.setRequestProperty("Content-Length",
    Integer.toString(soap.length()));
    conn.setRequestProperty("Content-Type", "text/xml; charset=utf-8");
    // 调用的接口方法是
    conn.setRequestProperty(isClass,isMethod);
    OutputStream os = conn.getOutputStream();
    OutputStreamWriter osw = new OutputStreamWriter(os, "utf-8");
    osw.write(soap);
    osw.flush();
    osw.close();
    // 获取webserivce返回的流
    InputStream is = conn.getInputStream();
    if (is != null) {
    InputStreamReader isr = new InputStreamReader(is, "UTF-8");
    BufferedReader br = new BufferedReader(isr);

    StringBuilder sb = new StringBuilder();
    String temp = null;
    while(null != (temp = br.readLine())) {
    sb.append(temp);
    }
    result = sb.toString();
    is.close();
    isr.close();
    br.close();
    }
    return result;
    }
    }

解析返回的报文:

这里先给大家看一下,我的拿到的报文返回示例:

  1. <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  2. <soap:Body>
  3. <ns2:getResultResponse xmlns:ns2="http://webservice.taikang.com/">
  4. <return>
  5. <message>访问成功</message>
  6. <result>true</result>
         </return>
    </ns2:getResultResponse >
    </soap:Body>
    </soap:Envelope>

按节点分级解析的方式,返回Map即可

  1. public static Map<String,String> XMLtoData(String xml) throws DocumentException {
  2. Map map = new HashMap();
  3. List<Data> dataList = new ArrayList<>();
  4. Document doc = DocumentHelper.parseText(xml);
  5. //获取根元素,准备递归解析这个XML树
  6. Element root = doc.getRootElement();
  7. //获取到data的集合
  8. List<Element> mzList = root.element("Body").element("getResultResponse").elements("return");
  9. //遍历data集合
  10. for (Element e : mzList) {
  11. List<Element> elements = e.elements();
  12. //遍历将元素中的key和value存到map中
  13. for (Element item : elements) {
  14. if (!StringUtils.isEmpty(item.getText())) {
  15. map.put(item.getName(), item.getText());
  16. }
  17. }
  18. }
  19. return map;
  20. }


    注意:
  1. List<Element> mzList = root.element("Body").element("getResultResponse").elements("return");
    节点可以按需求获取,即:root.element("**").element("**")................elements("**")
  1.  
  1. 上述是两种工具类调用Webservice接口的方式,请多指教!
  1.  

 

版权声明:本文为zeropc原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/zeropc/p/14257859.html