• webService 发送soap请求,并解析返回的soap报文


    本例应用场景:要做一个webService测试功能,不局限于任何一种固定格式的webService,所以像axis,cxf等框架就不好用了。只有深入到webService的原理,通过发收soap报文,来调用服务返回结果。

    发送请求:

     /**
         * 通过httpClient发送soap报文
         * @param requestSoap 请求报文
         * @param serviceAddress 请求地址
         * @param charSet 字符集
         * @param contentType 返回的contentType
         * @return 响应报文
         * @throws WebServiceModuleRuntimeException
         */
        public String sendRequestSoap(String requestSoap, String serviceAddress, String charSet, String contentType)
                throws WebServiceModuleRuntimeException {
            String resultSoap = "";
            PostMethod postMethod = new PostMethod(serviceAddress);
            byte[] b = new byte[0];
            try {
                b = requestSoap.getBytes(charSet);
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            InputStream is = new ByteArrayInputStream(b, 0, b.length);
            RequestEntity re = new InputStreamRequestEntity(is, b.length, contentType);
            postMethod.setRequestEntity(re);
    
            HttpClient httpClient = new HttpClient();
            int statusCode = 0;
            try {
                statusCode = httpClient.executeMethod(postMethod);
                System.out.println("statusCode = " + statusCode);
            } catch (IOException e) {
                throw new WebServiceModuleRuntimeException("执行http请求失败", e);
            }
            if (statusCode == 200) {
                try {
                    resultSoap = postMethod.getResponseBodyAsString();
                } catch (IOException e) {
                    throw new WebServiceModuleRuntimeException("获取请求返回报文失败", e);
                }
            } else {
                throw new WebServiceModuleRuntimeException("请求失败:" + statusCode);
            }
    
            return resultSoap;
        }
    //调用请求方法,发送报文
    String responseSoap = "";
            try{
                responseSoap = webServiceService.sendRequestSoap(requestSoap,struct.getWebAddress(),"utf-8","text/xml; charset=utf-8");
            }catch (WebServiceModuleRuntimeException ex){
                throw new ModuleException("发动请求失败",ex);
            }

    解析返回报文:

    因没有固定格式,所以无法通过jaxb工具来xml转bean,更没有客户端代码可以用。所以只有解析返回报文中,可以标识返回结果的值,比如成功、success、ok等。

    此处考虑两种情况:第一种状态码放在标签的属性值中,第二种状态作为标签的内容:

    <result ResultCode="0" ResultCodeDesc="成功">
    <result_code>0</result_code>
    System.out.println(parseResponseSoap("result_code", "", responseSoap));
    
    /**
         * 解析返回报文
         * @param node 标记所在节点
         * @param attr 标记所在属性
         * @param soap 报文
         * @return 标记值
         * @throws WebServiceModuleRuntimeException
         */
        public static String parseResponseSoap(String node, String attr, String soap) throws WebServiceModuleRuntimeException {
            //然后用SOAPMessage 和 SOAPBody
            Document personDoc;
            try {
                personDoc = new SAXReader().read(new StringReader(soap));
                Element rootElt = personDoc.getRootElement(); // 获取根节点
                Iterator body = rootElt.elementIterator("Body");
                while (body.hasNext()) {
                    Element recordEless = (Element) body.next();
                    return nextSubElement(node,attr,recordEless);
                }
            } catch (DocumentException e) {
                throw new WebServiceModuleRuntimeException("解析返回报文失败", e);
            }
            return "";
        }
    /**
         * 递归方法,查找本节点是否有标记信息,如果没有就查找下一层,
         * 在下一层里同样查找本层节点,只要找到值,就层层返回。
         * @param node 节点标签名
         * @param attr 节点属性值
         * @param el 当前节点对象
         * @return 目标值
         */
        public static String nextSubElement(String node, String attr, Element el) {
            if (el.getName().equals(node)) {
                //说明 找到了目标节点
                //属性值为空说明取标签内容
                if (attr.equals("")) {
                    Iterator sub2 = el.elementIterator();
                    //有子节点说明标签内容不是单一值,需要拿到查询结果
                    if (sub2.hasNext()) {
                        while (sub2.hasNext()) {
                            Element s2 = (Element) sub2.next();
                            //如果返回的不是单一的标记值,而是查询结果,有些麻烦,
                            //查询结果应当是list<map>格式,但是map的key值不好确定,是标签名作为key还是属性值作为key
                            //todo
                        }
                    } else {
                        return  el.getText();
                    }
    
                } else {
                    Attribute attrbute = el.attribute(attr);
                    return attrbute.getText();
                }
            } else {
                Iterator sub2 = el.elementIterator();
                while (sub2.hasNext()) {
                    Element sub = (Element) sub2.next();
                    return nextSubElement(node, attr, sub);
                }
            }
            return "";
        }

    后记:本篇代码满足我自己的需求,但是看官的需求各异,本篇仅提供部分参考。

  • 相关阅读:
    PHP面试:实现动态获取函数参数的方法
    PHP面试:什么是类的多态性,请写出一个例子
    php相关操作
    客户端app支付宝登录接口
    商品分类设计
    Git连接远程服务器
    iptables/mysql设置指定主机访问指定端口
    CMake安装grpc生成gRPCTargets.cmake文件
    Linux下Springboot解决`APR based Apache Tomcat Native library`提示
    java双重检测或枚举类实现线程安全单例(懒汉模式)
  • 原文地址:https://www.cnblogs.com/opensesame/p/6018403.html
Copyright © 2020-2023  润新知