• 关于Webservice接口对接相关总结


    Webservice接口对接

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

      一:

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

    
    
    //直接AXIS调用
    public class WebserviceUtil {
    
        public static String getResult(ServiceInfoDto serviceInfoDto, String jsoninfo)
                throws ServiceException, MalformedURLException, RemoteException, SOAPException {
            //调用接口//标识Web Service的具体路径
            String endpoint = serviceInfoDto.getEndpoint();
            String namespace = serviceInfoDto.getNamespace();
            String soapaction = serviceInfoDto.getSoapaction();
            String username = new String("***");
            String password = new String("***");
            String HU_SENDR = new String("***");
            String HU_JSON = jsoninfo;
    
            String result = "";
            try {
                // 创建 Service实例
                Service service = new Service();
                QName qname = new QName(namespace, serviceInfoDto.getLocalPart());
    
                // 通过Service实例创建Call的实例
                Call call = (Call) service.createCall();  //为Call设置服务的位置
                call.setTargetEndpointAddress(endpoint);
                call.setOperationName(qname);
                call.setEncodingStyle("UTF-8");
                call.setSOAPActionURI(soapaction);
                call.setUsername(username);
                call.setPassword(password);
    
                call.addParameter(new QName("HU_JSON"),
                        org.apache.axis.encoding.XMLType.XSD_STRING,
                        javax.xml.rpc.ParameterMode.IN);
    
                call.addParameter(new QName("HU_SENDR"),
                        org.apache.axis.encoding.XMLType.XSD_STRING,
                        javax.xml.rpc.ParameterMode.IN);
    
                call.setReturnType(XMLType.XSD_STRING);    // 返回值类型:String
    
                Object[] obj = {HU_JSON, HU_SENDR};
                result = (String) call.invoke(obj);// 远程调用
    //            System.out.println("result is " + result);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return result;
        }
    }
    public class ServiceInfoDto {
        private String endpoint;
        private String namespace;
        private String soapaction;
        private String localPart;
    
        public String getEndpoint() {
            return endpoint;
        }
    
        public void setEndpoint(String endpoint) {
            this.endpoint = endpoint;
        }
    
        public String getNamespace() {
            return namespace;
        }
    
        public void setNamespace(String namespace) {
            this.namespace = namespace;
        }
    
        public String getSoapaction() {
            return soapaction;
        }
    
        public void setSoapaction(String soapaction) {
            this.soapaction = soapaction;
        }
    
        public String getLocalPart() {
            return localPart;
        }
    
        public void setLocalPart(String localPart) {
            this.localPart = localPart;
        }
    }
    解读一下入参和几个重要的参数:
    ServiceInfoDto对象:是对相关节点入参的汇总,这里的endpoint,namespace,soapaction,localPart在对方提供的wsdl文件中都可查到;
    jsoninfo:接口方要求的入参对象(转成json字符串形式入参)
    String username = new String("***"); 接口方提供的认证登录名(不需要可忽略)
    String password = new String("***"); 接口方提供的认证登录密码(不需要可忽略)
    String HU_SENDR = new String("***"); HU_SENDR需要按对方要求的字段名称处理,入参值接口方提供(不需要可忽略);
    String HU_JSON = jsoninfo;HU_JSON;需要按对方要求的字段名称处理,入参值是前面处理过的json对象;
    

      二:

    第二种对接是拼接SOAP报文入参,并且解析返回的SOAP报文,获取返回信息;
    这种方式必须要清楚的知道对方入参的soap报文格式,相关节点一定要清晰,拿到对方的报文信息进行拼接即可:
    soap报文拼接,由于我用到的地方比较多,所以提取的代码块处理
    public class SoapAppendXml {
    
        public static StringBuffer soapXml(String arg2,String arg4,String method,String id) {
            StringBuffer sendSoapString = new StringBuffer();
            sendSoapString.append("<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="http://webservice.**.com/">");
            sendSoapString.append(" <soapenv:Header/>");
            sendSoapString.append(" <soapenv:Body>");
            sendSoapString.append(" <web:"+method+">");
            sendSoapString.append(" <arg0>*</arg0>");
            sendSoapString.append(" <arg1>false</arg1>");
            sendSoapString.append(" <arg2>"+arg2+"</arg2>");
            sendSoapString.append(" <arg3>[]</arg3>");
            sendSoapString.append(" <arg4>"+arg4+"</arg4>");
            sendSoapString.append(" </web:"+method+">");
            sendSoapString.append(" </soapenv:Body>");
            sendSoapString.append("</soapenv:Envelope>");
            return sendSoapString;
        }
    }

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

    下面是接口调用:

    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) {
        byte[] bytes = new byte[0];
        bytes = new byte[is.available()];
        is.read(bytes);
        String str = new String(bytes);
        return str;
    }else {
        return null;
    }
        }
    }
    解读一下上面的工具类:
    url:是对接服务地址,以"?wsdl"结尾的地址;
    isClass:接口类名,在对方提供的wsdl文件中可以查到,我这里的是"LvYunkangWebservice";
    isMethod:调用方法名
    sendSoapString:拼接好的soap报文

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


    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;
    }
    }

    解析返回的报文:

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

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

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

    public static Map<String,String> XMLtoData(String xml) throws DocumentException {
            Map map = new HashMap();
            List<Data> dataList = new ArrayList<>();
            Document doc = DocumentHelper.parseText(xml);
            //获取根元素,准备递归解析这个XML树
            Element root = doc.getRootElement();
            //获取到data的集合
            List<Element> mzList = root.element("Body").element("getResultResponse").elements("return");
            //遍历data集合
            for (Element e : mzList) {
                List<Element> elements = e.elements();
                //遍历将元素中的key和value存到map中
                for (Element item : elements) {
                    if (!StringUtils.isEmpty(item.getText())) {
                        map.put(item.getName(), item.getText());
                    }
                }
            }
            return map;
        }


    注意:
    List<Element> mzList = root.element("Body").element("getResultResponse").elements("return");
    节点可以按需求获取,即:root.element("**").element("**")................elements("**")
    
    
    上述是两种工具类调用Webservice接口的方式,请多指教!
     
  • 相关阅读:
    api封装
    计算字符串内的字出现几次
    Generator 函数的语法
    js原型链的看法
    购物车之上线版思路
    Java并发多线程面试题 Top 50
    Java NIO和IO的区别
    【转载】线程池的原理及实现
    【转载】关于SimpleDateFormat安全的时间格式化线程安全问题
    【转载】Java对象的生命周期
  • 原文地址:https://www.cnblogs.com/zeropc/p/14257859.html
Copyright © 2020-2023  润新知