Webservice的wsdl文件解析与Soap消息的发送、接收(不生成java客
发布时间:2020-12-16 23:16:11 所属栏目:安全 来源:网络整理
导读:附件中附带页面jsp、js,还有dwr的action,service以及util,我的环境是spring、dwr、ext、jquery。由于整个工具牵扯的比较多,所以没有将完整的可运行的代码整理出来,只将所有核心的代码贴了出来,如果需要运行还需要解决些小问题 近段时间,需要为公司的Q
附件中附带页面jsp、js,还有dwr的action,service以及util,我的环境是spring、dwr、ext、jquery。由于整个工具牵扯的比较多,所以没有将完整的可运行的代码整理出来,只将所有核心的代码贴了出来,如果需要运行还需要解决些小问题
近段时间,需要为公司的QA测试人员提供一个Webservice的测试工具,具体要求为:测试人员提供webservice的url,测试工具根据url得到webservice发布的方法及方法的参数,然后测试人员在页面输入参数,并点击运行,工具运行后,在页面上显示返回的结果。其实测试人员可以用现成在测试框架soapui来测试webservice,不过测试人员仍觉得麻烦,Team Leader还要求工具不能用wsdl2java生成webservice的客户端代码。我想可能是不想在项目中存放过多的无用的临时文件吧。 测试工具支持参数和返回值的类型有:数组、List、java基本数据类型、java对象以及这些类型的相互嵌套。工具截图如下 下面说说工具的实现思路:
在看实现代码前,不懂wsdl和schema的朋友们可以根据以下网址,先熟悉一下wsdl和schema文件的结构,和各个属性字段
代码讲解: 用于在页面显示方法和方法参数的实体bean /** * @author zhengtian * * @date 2011-8-4 下午11:21:50 */ @SuppressWarnings("all") public class WebServiceMethod { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } import java.util.ArrayList; import java.util.List; public class ParameterInfo { private String name;// 参数名 private String value;// 参数值 private String type;// 参数类型 private String childType;// 如果是数组,那么该字段为数组元素的类型 private List<ParameterInfo> children = new ArrayList<ParameterInfo>(); public ParameterInfo() { } public ParameterInfo(String name,String type) { this.name = name; this.type = type; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } public String getType() { return type; } public void setType(String type) { this.type = type; } public List<ParameterInfo> getChildren() { return children; } public void setChildren(List<ParameterInfo> children) { this.children = children; } public String getChildType() { return childType; } public void setChildType(String childType) { this.childType = childType; } /** * 增加子参数 * * @param param */ public void addChild(ParameterInfo param) { children.add(param); } } 获取webservice发布的方法 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; } /** * 得到wsdl中所有的方法 * * @param wsdlUrl * @return * @throws Exception */ public static List<String> getOperationList(String wsdlUrl) throws Exception { Document document = getDefinitionDocument(wsdlUrl); XPath xpath = getXpath(document); 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)) { log.debug("解析" + wsdlUrl + "中的方法:" + operationName); operationList.add(operationName); } } return operationList; } 得到方法的参数 /** * 根据方法名称和webserviceUrl得到参数 * * @param methodName * @param webserviceUrl * @return * @throws Exception */ public List<ParameterInfo> getParamByMethodNameAndWsUrl(String methodName,String webserviceUrl) throws Exception { try { Document document = WsdlUtil.getDefinitionDocument(webserviceUrl); // 返回结果 List<ParameterInfo> inputParamList = new ArrayList<ParameterInfo>(); // 解析参数 StringBuilder xpathBuilder = new StringBuilder(); WsdlUtil.getInputParam(inputParamList,document,methodName,xpathBuilder,null,false); return inputParamList; } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } } 解析输入参数的核心方法 /** * 得到输入参数 * * @param inputParamList * @param document * @param operationName * @param xpathBuilder * @param parentParam * @param isSelfDefinition * @throws Exception */ public static void getInputParam(List<ParameterInfo> inputParamList,Document document,String operationName,StringBuilder xpathBuilder,ParameterInfo parentParam,boolean isSelfDefinition) throws Exception { // 得到complexTypeName String complexTypeName = ""; if (parentParam == null) { complexTypeName = operationName; } else { if (parentParam.getType().equals(SchemaDefaulyType.type_array.type)) { complexTypeName = parentParam.getChildType(); } else { complexTypeName = parentParam.getType(); } } // 得到所有的element结点 List<Node> children = getSequenceElementOfComplexType(document,parentParam,complexTypeName,isSelfDefinition); for (int i = 0; i < children.size(); i++) { // 子结点 Node child = children.get(i); String name = DOMUtil.getNodeName(child); // 参数 ParameterInfo param = new ParameterInfo(); param.setName(name); // 是否存在type属性(判断其type是引用还是自身定义) if (DOMUtil.assertNodeAttributeExist(child,"type")) {//type存在 String type = DOMUtil.getNodeType(child); if (DOMUtil.isArray(child)) { param.setType(SchemaDefaulyType.type_array.type); param.setChildType(type); // 如果是简单的数组,则为数组增加一个子参数 ParameterInfo childParam = new ParameterInfo("",type); param.addChild(childParam); // 复杂类型数组 if (!DOMUtil.isDefaultType(child)) { getInputParam(inputParamList,operationName,childParam,false); } } else { param.setType("anyType".equals(type) ? "object" : type); // 复杂类型 if (!DOMUtil.isDefaultType(child)) { StringBuilder complextXpath = new StringBuilder("wsdl:definitions/wsdl:types/xs:schema"); getInputParam(inputParamList,complextXpath,param,false); } } } else {// 如果type属性不存在,说明该结点的类型在其子结点中定义 String currentAppendStr = "/xs:complexType[@name='" + parentParam.getType() + "']/xs:sequence/xs:element[@name='" + name + "']"; xpathBuilder.append(currentAppendStr); Node inner = DOMUtil.findNode(document,xpathBuilder.toString() + "/xs:complexType/xs:sequence/xs:element[position()=1]"); if (DOMUtil.isArray(inner)) { // 得到数组的类型 String type = getSequenceElementType(document,inner); param.setType(SchemaDefaulyType.type_array.type); param.setChildType(type); // 为数组增加一个子参数 ParameterInfo childParam = new ParameterInfo("",type); param.addChild(childParam); if (!DOMUtil.isDefaultType(type)) {// 复杂类型数组 getInputParam(inputParamList,true); } } else { param.setType(name); // 遍历其子结点xs:element getInputParam(inputParamList,true); } // 将xpath还原 xpathBuilder.delete(xpathBuilder.length() - currentAppendStr.length(),xpathBuilder.length()); } if (parentParam == null) { inputParamList.add(param); } else { parentParam.addChild(param); } } } 当页面输入完参数后,执行方法 /** * 执行方法 * * @param webserviceUrl * @param methodName * @param paramStr * @return * @throws Exception */ public String executionMethod(String webserviceUrl,String methodName,String paramStr) throws Exception { String result = ""; try { // 将json参数转换为List<ParameterInfo> List<ParameterInfo> paramList = convertStrToListParam(paramStr); List<ParameterInfo> resultList = new SoapUtil().sendRequest(methodName,paramList,webserviceUrl); result = JSONArray.fromObject(resultList).toString(); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } return result; } 发送soap请求,然后获得返回的soap消息 /** * 发送请求 * * @param operation * @param params * @param wsdlUrl * @return * @throws Exception */ public List<ParameterInfo> sendRequest(String operation,List<ParameterInfo> paramList,String wsdlUrl) throws Exception { // 获取操作 Operation operationInst = getOperation(wsdlUrl,operation,null); // 组装请求消息 String message = buildRequest(wsdlUrl,operationInst,paramList); // 发送请求,得到返回的soap消息 String address = wsdlUrl.substring(0,wsdlUrl.indexOf("?wsdl")); String responseStr = sendRequest(address,message,operationInst.getAction()); Document soapDocument = getResponseDocument(responseStr); // 判断返回的soap消息是否为soap:Fault if (isFaultResponseSoap(soapDocument)) { processFaultResponseSoap(soapDocument); } // 解析返回结果 List<ParameterInfo> outPutParamList = new ArrayList<ParameterInfo>(); List<Map<String,Object>> wsdlMapSoapList = new ArrayList<Map<String,Object>>(); String complextTypeName = operation + "Response"; getOutPutParam(WsdlUtil.getDefinitionDocument(wsdlUrl),soapDocument,complextTypeName,wsdlMapSoapList,outPutParamList,null); return outPutParamList; } 将参数解析成发送的soap消息核心方法 /** * 构建soap消息 * * @param wsdlDocument * @param soapDocument * @param operationInst * @param paramList * @param parentNode * @throws Exception */ private void buildSOAPMessage(Document wsdlDocument,Document soapDocument,Operation operationInst,Node parentNode,ParameterInfo parentParam) throws Exception { // 操作名称 String operationName = operationInst.getName(); // 如果是操作方法的根节点,则清空其子节点 if (parentNode == null) { parentNode = getOperationNodeInRequestSoapDom(soapDocument,operationName); parentNode.setTextContent(""); } for (int i = 0; i < paramList.size(); i++) { // 得到参数的name、type、value ParameterInfo param = paramList.get(i); String value = param.getValue(); String name = param.getName(); String type = param.getType(); // 判断是否为基本类型 if (DOMUtil.isDefaultType(type) || (StringUtils.isNotEmpty(name) && StringUtils.isNotEmpty(type)) || ("entry".equals(type) || "JsonEntry".equals(type))) { if (StringUtils.isEmpty(name)) { if (i > 0) { Element ele = soapDocument.createElement(parentNode.getNodeName()); Text text = soapDocument.createTextNode(value); ele.appendChild(text); Node grandParentNode = parentNode.getParentNode(); grandParentNode.appendChild(ele); } else { if ("entry".equals(type) || "JsonEntry".equals(type)) { Element ele = soapDocument.createElement(type); parentNode.appendChild(ele); // 组装子结点 if (param.getChildren().size() > 0) { List<Node> childList = DOMUtil.getChildElementNodes(parentNode); Node lastChildNode = childList.get(childList.size() - 1); buildSOAPMessage(wsdlDocument,param.getChildren(),lastChildNode,param); } } else { Text text = soapDocument.createTextNode(value); parentNode.appendChild(text); } } } else { Element ele = soapDocument.createElement(name); Text text = soapDocument.createTextNode(value); ele.appendChild(text); parentNode.appendChild(ele); // 组装子结点 if (param.getChildren().size() > 0) { List<Node> childList = DOMUtil.getChildElementNodes(parentNode); Node lastChildNode = childList.get(childList.size() - 1); buildSOAPMessage(wsdlDocument,param); } } } else {// 如果不是基本类型,则直接组装该节点的子结点 if (i > 0) { Element ele = soapDocument.createElement(parentNode.getNodeName()); Node grandParentNode = parentNode.getParentNode(); grandParentNode.appendChild(ele); // 组装子结点 if (param.getChildren().size() > 0) { List<Node> childList = DOMUtil.getChildElementNodes(grandParentNode); Node lastChildNode = childList.get(childList.size() - 1); buildSOAPMessage(wsdlDocument,param); } } else { // 组装子结点 if (param.getChildren().size() > 0) { buildSOAPMessage(wsdlDocument,parentNode,param); } } } } } 将返回的soap消息解析成页面参数核心方法 /** * 解析返回的soap消息,然后将结果填充到outPutParamList中 * * @param wsdlDocument * @param soapDocument * @param operationResponseName * @param complextTypeName * @param wsdlMapSoapList * @param outPutParamList * @throws Exception */ public void getOutPutParam(Document wsdlDocument,String operationResponseName,String complextTypeName,List<Map<String,Object>> wsdlMapSoapList,List<ParameterInfo> outPutParamList,ParameterInfo parent) throws Exception { // 得到返回的参数 List<Node> outPutNodeList = WsdlUtil.getSequenceElementOfComplexType(wsdlDocument,complextTypeName); for (int i = 0; i < outPutNodeList.size(); i++) { Map<String,Object> wsdlMapSoap = new HashMap<String,Object>(); // 组装参数param Node outPutNode = outPutNodeList.get(i); String name = DOMUtil.getNodeName(outPutNode); String type = DOMUtil.getNodeType(outPutNode); ParameterInfo currentParam = new ParameterInfo(); currentParam.setName(name); if (DOMUtil.isDefaultType(outPutNode)) {// 该参数为基本类型 if (DOMUtil.isArray(outPutNode)) {// 数组 currentParam.setType(WsdlUtil.SchemaDefaulyType.type_array.getType()); currentParam.setChildType(type); // 组装映射关系 wsdlMapSoap.put("name",name); wsdlMapSoap.put("index",new Integer(-1)); wsdlMapSoapList.add(wsdlMapSoap); // 得到该数组在返回soap消息中的个数 int arrayLength = getArrayLengthFromResponseSoap(soapDocument,operationResponseName,wsdlMapSoapList); // 从soap消息中取出值 for (int j = 1; j <= arrayLength; j++) { ParameterInfo param = new ParameterInfo(); param.setName(name); param.setType(type); wsdlMapSoap.put("index",new Integer(j)); String value = getValueFromResponseSoap(soapDocument,operationResponseName); param.setValue(value); currentParam.addChild(param); } } else {// 不是数组 currentParam.setType(type); // 根据映射关系,从返回的soap消息中取值 wsdlMapSoap.put("name",new Integer(-1)); wsdlMapSoapList.add(wsdlMapSoap); String value = getValueFromResponseSoap(soapDocument,operationResponseName); currentParam.setValue(value); } } else {// 该参数为复杂类型 if (DOMUtil.isArray(outPutNode)) {// 数组 currentParam.setType(WsdlUtil.SchemaDefaulyType.type_array.getType()); currentParam.setChildType(type); // 组装映射关系 wsdlMapSoap.put("name",wsdlMapSoapList); // 从soap消息中取出值 for (int j = 1; j <= arrayLength; j++) { ParameterInfo param = new ParameterInfo(); param.setType(type); wsdlMapSoap.put("index",new Integer(j)); // 继续查找 getOutPutParam(wsdlDocument,type,param); currentParam.addChild(param); } } else {// 不是数组 currentParam.setType(type); // 根据映射关系,从返回的soap消息中取值 wsdlMapSoap.put("name",new Integer(-1)); wsdlMapSoapList.add(wsdlMapSoap); // 继续查找 getOutPutParam(wsdlDocument,currentParam); } } // 增加参数 if (parent == null) { outPutParamList.add(currentParam); } else { parent.addChild(currentParam); } // 在映射关系中除去当前的结点 wsdlMapSoapList.remove(wsdlMapSoapList.size() - 1); } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
相关内容
- 如何从webservice的URL获取wsdl文件
- Shell 流程控制
- vim YouCompleteMe unknown function pythoncomplete#compl
- 使用变量间接扩展的Bash数组扩展
- 从 UNIX 到 GitHub:十个关于自由和开源软件历史的重要事件
- *.ascx *.asax *.aspx.resx *.asax.resx是什么文件
- scala:在父类和子类中覆盖构造函数中的隐式var?
- twitter-bootstrap – Bootstrap 4 Navbar即使在切换时也保
- 结合流星,什么AngularJS可以做的Handlebars不能?
- Angular 2 – 一个组件触发刷新页面上的另一个组件