1. 程式人生 > >根據WebService地址展示方法列表、入參和返回值(解析wsdl)

根據WebService地址展示方法列表、入參和返回值(解析wsdl)

主要使用XPATH來解析wsdl文件,dom4j解析xsd

建議先了解一下WSDL的一些元素所代表的含義

效果(返回值暫時沒做,邏輯是一樣的)


獲取Document方法:

/**
     * 得到wsdl檔案的根結點的document
     *
     * @param wsdlUrl
     * @return
     * @throws Exception
     */
    public static Document getDefinitionDocument(String wsdlUrl) throws Exception {
        Definition def = getDefinition(wsdlUrl);

        WSDLWriter writer = getWsdlFactory().newWSDLWriter();
        Document document = writer.getDocument(def);

        return document;
    }

獲取Xpath方法:

   /**
     * 得到document的查詢工具xpath
     *
     * @param document
     * @return
     * @throws Exception
     */
    public static XPath getXpath(Document document) throws Exception {
        XPath xpath = XPathFactory.newInstance().newXPath();
        xpath.setNamespaceContext(new UniversalNamespaceCache(document, false));
        return xpath;
    }

Controller層:

/**
 * @author: 徐楚若
 * @date: 2018/1/22 14:01
 */

@RestController
@RequestMapping("webserviceForm")
public class CustomForm {

    /**
     * 獲取指定webservice的所有方法
     *
     * @param webserviceUrl
     * @return
     * @throws Exception
     */
    @RequestMapping("findMethods")
    public List<WebServiceMethod> getAllMethod(Model model, String webserviceUrl) throws Exception {
        // 如果接收的URL為空,返回
        if (webserviceUrl == null) {
            return null;
        }
        List<WebServiceMethod> list = new BmWsTestBoImpl().getAllMethodByServiceUrl(webserviceUrl);
        model.addAttribute("methodList", list);
        return list;
    }

    /**
     * 根據方法名稱和webserviceUrl得到入參和型別
     *
     * @param methodName
     * @param webserviceUrl
     * @return
     * @throws Exception
     */
    @RequestMapping("getParamByMethodNameAndWsUrl")
    public List<ParameterInfo> getParamByMethodNameAndWsUrl(String methodName, String webserviceUrl,Model model) throws Exception {
        List<ParameterInfo> list = new BmWsTestBoImpl().getParamByMethodNameAndWsUrl(methodName, webserviceUrl);
        model.addAttribute("paramList",list);
        return list;
    }

}

Service實現類(工具方法較多)
 @Override
    public List<WebServiceMethod> getAllMethodByServiceUrl(String webserviceUrl) throws Exception {
        // 結果
        List<WebServiceMethod> list = new ArrayList<WebServiceMethod>();
        try {
            // 將url修正為合法的url,即帶wsdl字尾的
            webserviceUrl = getWebserviceUrl(webserviceUrl);
            if (StringUtils.isNotEmpty(webserviceUrl)) {
                List<String> methodList = WsdlUtil.getOperationList(webserviceUrl);
                for (String methodName : methodList) {
                    WebServiceMethod webServiceMethod = new WebServiceMethod();
                    webServiceMethod.setName(methodName);

                    list.add(webServiceMethod);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
        return list;
    }

/**
     * 將webserviceUrl路徑轉為合法的路徑
     *
     * @param webserviceUrl
     * @return
     * @throws Exception
     */
    public String getWebserviceUrl(String webserviceUrl) {
        if (StringUtils.isNotEmpty(webserviceUrl)) {
            // 判斷url裡面是否存在wsdl字尾
            if (webserviceUrl.indexOf("?") >= 0) {
                if (!webserviceUrl.endsWith("wsdl")) {
                    webserviceUrl = new StringBuilder(webserviceUrl).append("wsdl").toString();
                }
            } else {
                webserviceUrl = new StringBuilder(webserviceUrl).append("?wsdl").toString();
            }
            return webserviceUrl;
        } else {
            return "";
        }
    }
/**
     * 得到wsdl中所有的方法
     *
     * @param wsdlUrl
     * @return
     * @throws Exception
     */
    public static List<String> getOperationList(String wsdlUrl) throws Exception {
        Document document = getDefinitionDocument(wsdlUrl);

        NodeList operations = DOMUtil.findNodeList(document, "wsdl:definitions/wsdl:portType/wsdl:operation");

        // 返回的結果集list
        List<String> operationList = new ArrayList<String>();
        for (int i = 0; i < operations.getLength(); i++) {
            Node operation = operations.item(i);
            String operationName = DOMUtil.getNodeName(operation);
            if (operationName != null && !"".equals(operationName)) {
                operationList.add(operationName);
            }
        }
        return operationList;
    }
 /**
     * 在document中查詢結點
     *
     * @param document
     * @param xpathStr
     * @return
     * @throws Exception
     */
    public static NodeList findNodeList(Document document, String xpathStr) throws Exception {
        XPath xpath = WsdlUtil.getXpath(document);
        NodeList nodeList = (NodeList) xpath.evaluate(xpathStr, document, XPathConstants.NODESET);
        return nodeList;
    }
    /**
     * 得到結點的屬性值
     *
     * @param node
     * @param attributeName
     * @return
     * @throws Exception
     */
    public static String getAttributeValue(Node node, String attributeName) throws Exception {
        String attributeValue = "";
        if (node != null) {
            NamedNodeMap attributeMap = node.getAttributes();
            Node attributeNode = attributeMap.getNamedItem(attributeName);
            if (attributeNode != null) {
                attributeValue = attributeNode.getNodeValue();
            }
        }
        return attributeValue;
    }

    /**
     * 得到結點的name屬性值
     *
     * @param node
     * @return
     * @throws Exception
     */
    public static String getNodeName(Node node) throws Exception {
        return getAttributeValue(node, "name");
    }

獲取入參和型別:

/**
     * 根據方法名稱和webserviceUrl得到引數
     *
     * @param methodName
     * @param webserviceUrl
     * @return
     * @throws Exception
     */
    @Override
    public List<ParameterInfo> getParamByMethodNameAndWsUrl(String methodName, String webserviceUrl) throws Exception {
        try {
            // 將url修正為合法的url,即帶wsdl字尾的
            webserviceUrl = getWebserviceUrl(webserviceUrl);
            Document document = WsdlUtil.getDefinitionDocument(webserviceUrl);
            XPath xpath = WsdlUtil.getXpath(document);
            // 查詢import元素
            NodeList nodeList = (NodeList) xpath.evaluate("/wsdl:definitions/wsdl:types/xsd:schema/xsd:import", document, XPathConstants.NODESET);
            // 獲取指定名稱的值
            Node schemaLocationNode = nodeList.item(0).getAttributes().getNamedItem("schemaLocation");
            // 讀取xsd
            String xsdURL = schemaLocationNode.getNodeValue();
            SAXReader saxReader = new SAXReader();
            org.dom4j.Document dom4j_Document = saxReader.read(xsdURL);
            // 查詢指定方法名稱的元素
            Element element = (Element) dom4j_Document.selectSingleNode("//xs:element[@name='" + methodName + "']");
            // 獲取資料
            List<ParameterInfo> list = new ArrayList<ParameterInfo>();
            List<ParameterInfo> parameterInfo = treeWalk(element, list);
            return parameterInfo;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    /**
     * 獲取所有元素名稱
     */
    public static List<ParameterInfo> treeWalk(Element element, List<ParameterInfo> list) {
        // 獲取根元素下的所有子元素
        List<Element> es = element.elements();
        for (Element e : es) {
            if (e.attribute("name") != null) {
                // 封裝資料
                ParameterInfo parameterInfo = new ParameterInfo();
                // 入參
                Attribute name = e.attribute("name");
                parameterInfo.setName(name.getValue());
                // 方法型別
                Attribute type = e.attribute("type");
                parameterInfo.setType(type.getValue().split(":")[1]);
                list.add(parameterInfo);
                treeWalk(e, list);
            } else {
                treeWalk(e, list);
            }
        }
        return list;
    }

程式碼需要根據wsdl結構來修改xpath的查詢語法

程式碼中

NodeList operations = DOMUtil.findNodeList(document, "wsdl:definitions/wsdl:portType/wsdl:operation");

表示的意義即為從根節點wsdl:definitions層層往下找到子節點,再用AIP獲取到方法名


可能wsdl結構會有不同,方法的入參和返回值沒在wsdl裡,所以要去xsd文件裡取

直接取import裡的第一個值即為方法引數.....(自己根據wsdl結構去檢視方法在哪個xsd)

// 查詢import元素
NodeList nodeList = (NodeList) xpath.evaluate("/wsdl:definitions/wsdl:types/xsd:schema/xsd:import", document, XPathConstants.NODESET);


// 查詢指定方法名稱的元素
Element element = (Element) dom4j_Document.selectSingleNode("//xs:element[@name='" + methodName + "']");

這裡直接使用[//]來定位到元素位置,視情況使用,如果你的檔案裡有多個相同的,還需要判斷

//title[@*] 選取所有帶有屬性的 title 元素。 

到這裡就完成了~

有一點需要注意的是,如果你跟我一樣也要解析xsd才能獲取到入參和型別

xsd我不是用的XPATH,是用的dom4j,在用它的API的時候,必須要新增外部的一個jar包,不然會報錯.

<!-- https://mvnrepository.com/artifact/jaxen/jaxen -->
<dependency>
    <groupId>jaxen</groupId>
    <artifactId>jaxen</artifactId>
    <version>1.1.1</version>
</dependency>

如果對錶達式不清楚的可以看: