使用过soapUI开发工具的同学都知道,根据wsdl地址可以生成基于soap1.1协议和soap1.2协议两个版本的soap请求报文,便于开发或测试人员进行接口测试,不过遗憾的是不能对wsdl进行批量解析生成请求报文。基于此,本文在soapui源码的基础进行了二次开发,增加了对wsdl的批量解析。并且集成了mybatis,对mysql或oracle数据库进行读写操作,便于存储解析后的报文等信息。源码已上传至github,若需要请前往阅读和下载,有帮助顺便送上小星星哦!感谢!

一、需求背景

(一)soap报文格式修改:通常情况下,使用soapUI生成的请求报文标签之间是用“?”填充的,而根据业务需求,需要将其替换成“${标签名}”,譬如说由原来的“<xsd:bankCode>?</xsd:bankCode>"修改为“<xsd:bankCode>${bankCode}</xsd:bankCode>";其次,soapUI生成的请求报文具有一定的格式(换行、空格),所以将不必要的内容进行删除,包括无用的注释等信息,以免占用空间。
(二)批量解析wsdl文档:若是业务量不多,使用soapUI生成报文,然后手动修改即可,不过现在的业务量较大,需要对几百个wsdl进行解析,所以需要对源码进行修改,添加和封装来解决批量解析的问题。
(三)持久化数据库:最后需要对解析后的报文存储到数据库,以便后续开发使用。
二、代码简介
(一)soap报文格式修改
       首先解决第一个需求,这部分可以定位到soapui源码com.eviware.soapui.impl.wsdl.support.xsd.SampleXmlUtil工具类。分析源码可知,其主要思想就是将wsdl文档中的标签元素解析出来后,在标签之间插入“?”。因此将processElement()方法中解析出来的标签元素element.getName().getLocalPart()声明为全局变量myElement,然后将“?”替换成“${myElement}”即可,具体详见我的源码,点击SampleXmlUtil
(二)批量解析wsdl文档
       为了方便解析wsdl,所以在soapui源码的基础上二次开发,新增加了一个工具包com.founder.soapui,用来封装和解析wsdl。

1 package com.founder.soapui;
 2 import com.eviware.soapui.impl.wsdl.WsdlOperation;
 3 /**
 4  * @author :Mark Wang
 5  * @date :Created in 07/05/2020 10:07:06
 6  * @description: Encapsulates the necessary information of WsdlOperation
 7  * @modified By:
 8  * @version: 1.0
 9  */
10 public class OperationInfo {
11     private String operationName;
12     private String requestXml;
13     private String responseXml;
14 
15     public OperationInfo(WsdlOperation operation) {
16         operationName = operation.getName();
17         requestXml = operation.createRequest( true );
18         responseXml = operation.createResponse(true);
19     }
20 }
1 package com.founder.soapui;
 2 import com.eviware.soapui.impl.wsdl.WsdlInterface;
 3 import com.eviware.soapui.impl.wsdl.WsdlOperation;
 4 import java.util.ArrayList;
 5 import java.util.List;
 6 /**
 7  * @author :Mark Wang
 8  * @date :Created in 07/05/2020 10:07:06
 9  * @description: Encapsulates the necessary information of WsdlInterface
10  * @modified By:
11  * @version: 1.0
12  */
13 public class InterfaceInfo {
14     private String interfaceName;
15     private List<OperationInfo> operations;
16     private String[] address;
17 
18     public InterfaceInfo(WsdlInterface wsdlInterface) {
19         this.interfaceName = wsdlInterface.getName();
20         this.address = wsdlInterface.getEndpoints();
21         int operationNum = wsdlInterface.getOperationCount();
22         List<OperationInfo> operations = new ArrayList<OperationInfo>();
23 
24         for(int i = 0; i < operationNum; i++) {
25             WsdlOperation operation = ( WsdlOperation )wsdlInterface.getOperationAt( i );
26             OperationInfo operationInfo = new OperationInfo(operation);
27             operations.add(operationInfo);
28         }
29         this.operations = operations;
30     }
31 }
1 package com.founder.soapui;
 2 import com.eviware.soapui.impl.wsdl.WsdlInterface;
 3 import com.eviware.soapui.impl.wsdl.WsdlProject;
 4 import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlImporter;
 5 import java.util.ArrayList;
 6 import java.util.List;
 7 /**
 8  * @author :Mark Wang
 9  * @date :Created in 07/05/2020 10:07:06
10  * @description: Load information according to wsdl location
11  * @modified By:
12  * @version: 1.0
13  */
14 public class WsdlInfo {
15     private String wsdlName;
16     private List<InterfaceInfo> interfaces;
17 
18     public WsdlInfo(String path) throws Exception {
19         WsdlProject project = new WsdlProject();
20         WsdlInterface[] wsdlInterfaces = WsdlImporter.importWsdl( project, path );
21         this.wsdlName = path;
22         if(null != wsdlInterfaces)
23         {
24             List<InterfaceInfo> interfaces = new ArrayList<InterfaceInfo>();
25             for(WsdlInterface wsdlInterface : wsdlInterfaces)
26             {
27                 InterfaceInfo interfaceInfo = new InterfaceInfo(wsdlInterface);
28                 interfaces.add(interfaceInfo);
29             }
30             this.interfaces = interfaces;
31         }
32     }
33  }
1 package com.founder.soapui;
 2 import java.util.ArrayList;
 3 import java.util.List;
 4 /**
 5  * @author :Mark Wang
 6  * @date :Created in 07/05/2020 10:07:06
 7  * @description: Batch parsing WSDL to generate request message
 8  * @modified By:
 9  * @version: 1.0
10  */
11 public class BatchWsdlParse {
12     private static List<String> soapRequest = new ArrayList<>();
13 
14     /**
15      * Parsing WSDL to get request message
16      * @param wsdlLocation
17      * @return
18      * @throws Exception
19      */
20     public static List<String> wsdlParse (String wsdlLocation) throws Exception {
21         WsdlInfo wsdlInfo = new WsdlInfo(wsdlLocation);
22         for (InterfaceInfo interfaceInfo : wsdlInfo.getInterfaces()) {
23             soapRequest.add(parseInterfaceInfo (interfaceInfo));
24         }
25         return soapRequest;
26     }
27 
28     /**
29      * Batch wsdl parse
30      * @param String
31      * @return
32      * @throws Exception
33      */
34     public static List<String> batchWsdlParse (List<String> wsdlList) throws Exception {
35         for (WsdlUrl wsdlUrl : wsdlList) {
36             WsdlInfo wsdlInfo = new WsdlInfo(wsdlUrl);
37             for (InterfaceInfo interfaceInfo : wsdlInfo.getInterfaces()) {
38                 soapRequest.add(parseInterfaceInfo (interfaceInfo));
39             }
40         }
41         return soapRequest;
42     }
43 
44     /**
45      * parse InterfaceInfo
46      * @param interfaceInfo
47      * @param serviceId
48      * @return
49      */
50     public static String parseInterfaceInfo (InterfaceInfo interfaceInfo) {
51         return interfaceInfo.getOperations().get(0).getRequestXml();
52     }
53 }
1 /**
 2  * @author :Mark Wang
 3  * @date :Created in 07/05/2020 10:07:06
 4  * @description: Test to parse wsdl
 5  * @modified By:
 6  * @version: 1.0
 7  */
 8 public class WSDLParseTest {
 9     private String wsdlLocation = "http://192.168.1.18:8001/CHNAppxServices/services/XfaceSellingTransactionWrapper?wsdl";
10     
11     @Test
12     public void wsdlParseTest () throws Exception {
13         List<String> requestList = BatchWsdlParse.wsdlParse(wsdlLocation);
14         for (String request : requestList) {
15             System.out.println(request);
16         }
17     }
18 
19     @Test
20     public void batchWsdlParseTest() throws Exception {
21         List<String> wsdlList = new ArrayList<>();
22         wsdlList.add(wsdlLocation);
23         List<String> requestList = BatchWsdlParse.batchWsdlParse(wsdlList);
24         for (String request : requestList) {
25             System.out.println(request);
26         }
27     }
28 }

 

(三)持久化数据库
       根据以上代码足以完成对wsdl的批量解析(get和set方法省略),至于将解析后必要的信息持久化数据库,主要是集成了mybatis,若是需要可以参考我的源码,这里就不啰嗦了!
三、个人总结
       其实研究过soapui源码的同学肯定知道,其实它也是基于wsdl4j,所以我们完全可以用wsdl4j对wsdl进行解析。之所以研究soapui源码,主要是为了学习学习!