webservice调试解析、soupui使用、xml代码开发、xpath获取数据

做项目的时候,经常遇到接口是webservice提供的,这个时候就需要会进行调试;
调试可以用soapui、postman/apipost等同类工具。
理解:webservice本身可以理解为一种xml格式,具有自描述特点的http post方式请求。可以完全适用http方式去调用。所以不要有任何压力。

webservice的几种解析调用方式

方式优势缺点上手难度链接
SoupUi只要获取到wsdl的xml文件的就可以一键解析出所有的方法;非常简单;软件支持windows、mac、linux需要多安装一个软件而已最简单,需要安装soapuisoupui.org download
Postman软件简单常见需要手工解析wsdl中的方法,请求参数、方式、手工粘贴到postman中,比较繁琐。首个接口难道大,webservice本质上就是一种特殊的Http请求,使用Http相关的工具完全适用第一个方法难度大postmanapipost
wsimportjava jdk自带需要懂jdk命令,不直观,有一定难度。最大使用JAVA命令wsimport生成WebService接口调用代码](https://blog.youkuaiyun.com/mc_linfen/article/details/83275184)

一、 webservice介绍

1.1.1 wsdl

wsdl:webservice中的核心概念,所有方法定义都在wsdl中,全程 webservice define language;
soap协议:soap协议是基于http协议,限制使用数据内容为xml,请求方式必须是Http Post的一个http协议的请求。具有:soap1.1、soap1.2两个版本。

wsdl在浏览器中打开示意图
wsdl保存到电脑桌面上面

1.1.2 webxml.com.cn公开的wsdl

上面几个几个wsdl的示例,这里介绍几个公开的wsdl链接示例,见公开网站 webxml.com.cn

wsdl作用endpoint
MobileCodeWS国内手机号归属地归属地wsdl网站
WeatherWS城市天气2500多个城市天气预报 WEB服务
ChildService.xmlxx免疫规划系统
baseInfoWebService.xmlxx冷链系统
externalWebService.xmlxx冷链系统
medicalWebService.xmlxx冷链系统
为防止,wsdl连接失效,我们copy一个wsdl定义:

1.1.3、wsdl示例1-baseInfoWebService.xml

baseInfoWebService.xml
原始地址(不可访问):https://yxxx.xa.gov.cn/ws/services/baseInfoWebService?wsdl
可访问地址:baseInfoWebService

二 工具使用

2.1 soupui 使用

soupui有免费开源版本,跨平台;

自己开发的webservice
soupui解析

2.2 postman或者同类工具apipost使用

postman调试 webservice
webservice版本
公开webservice

2.3 java自带命令行 wsimport

wsimport 使用方法具体解释

2.4 使用postman或者apipots等同类工具生成代码

2.4.1、getCountryCityByIp-SOAP1.1

getCountryCityByIp-SOAP1.1
getCountryCityByIp-SOAP1.1-content-type

curl --request POST \
  --url http://www.webxml.com.cn/WebServices/IpAddressSearchWebService.asmx \
  --header 'Content-Type: text/xml; charset=utf-8' \
  --header 'content-type: application/xml' \
  --data '<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <getCountryCityByIp xmlns="http://WebXml.com.cn/">
      <theIpAddress>222.91.66.232</theIpAddress>
    </getCountryCityByIp>
  </soap:Body>
</soap:Envelope>'

2.4.2、getCountryCityByIp-SOAP1.2

SOAP1.2-1
soup1.2-2

curl --request POST \
  --url http://www.webxml.com.cn/WebServices/IpAddressSearchWebService.asmx \
  --header 'Content-Type: application/soap+xml; charset=utf-8' \
  --header 'content-type: application/xml' \
  --data '<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
  <soap12:Body>
    <getCountryCityByIp xmlns="http://WebXml.com.cn/">
      <theIpAddress>222.91.66.232</theIpAddress>
    </getCountryCityByIp>
  </soap12:Body>
</soap12:Envelope>'

三、名词解释

名词作用链接
soap协议xml格式的post方式的http请求
wsdl定义就是soup协议的xml;协议版本有1.1和1.2两个版本l
cxf解析、发布soup xml的一个java的jar包apache cxf
hutool更加方便请求http请求Soap客户端-SoapClient

四、java一键解析xml成bean

4.1 json一键解析成java bean

json 一键解析成实体类

4.2 xml 一键解析成实体类

4.2.1 xml先转成json

使用在线转换工具,直接转换xml为json;  

xml2json

4.2.2 xml使用idea转成xml

idea xml 转实体类
xml直接转xsd格式

4.2.3 实体转xml工具类

1、JAXB "有两个名为 “" 的属性,类的两个属性具有相同名称 "”"解决方案
2、java实体 和 xml相互转换

/**
 1. 4.3 儿童信息上传接口 uploadChildrenInfo
 2. 日期统一 1991-10-08 00:00:00 这种格式
 3. 字符串长度的一半表示纯汉字长度
 */
@Data
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "children")
public class JwxVaccineDetailVo {

    @XmlElement(name = "child")
    private List<Child> children;
    
    @XmlElement(name = "bact_code", required = true)
    protected String bactCode;
    
    @XmlElementWrapper(name="inoculations")//指定父节点, = 等于多包裹了一层;
    @XmlElement(name = "inoculation")
    private List<Inoculation> inoculations;
}

4.3 idea根据xml直接生成实体类

webservice生成实体类是重复工作,使用idea自动生成

  1. 获取xml样例
  2. 使用idea根据xml生成xsd定义文件
  3. 使用idea根据xsd生成实体类(使用jaxb架构从xml生成java实体)
    webservice-01-xml-xsd
    webservice-02-xml-xsd--javabean
    webservice-03-xsd结构

五、研发webService的发布

webService开发完毕需要进行发布,发布需要借助:org.apache.cxf.jaxws.EndpointImpl.publish() 方法。

5. 1 需要引入的包

序号maven坐标常见类核心作用
1jakarta.jws-apijavax.jws.@WebService、@WebParam、@WebMethod标记该service是是webserice
2org.apache.cxforg.apache.cxf.jaxws.EndpointImpl对ws进行发布publish

5.2 使用示例

5.2.1 接口PacsService

/**
 * Pacs服务
 * @author li_chengyu
 */

@WebService(name = "PacsService", // 暴露服务名称
        targetNamespace = "http://service.listener.neusoft.com"// 命名空间,一般是接口的包名倒序
)
public interface PacsService {

    /**
     * (病理检查)报告结果信息接收服务
     *
     * @param xml
     * @return
     * @throws Exception
     */
    @WebMethod
    String receivePacsPathologicalRecord(@WebParam(name = "xml") String xml) throws Exception;
}

5.2.2 实现PacsServiceImpl

@Service
@WebService(name = "PacsService",
        serviceName = "PacsService",
        targetNamespace = "http://service.listener.neusoft.com",
        endpointInterface = "com.neusoft.listener.service.business.terminal.PacsService"
)
@Component
@MapperScan({"com.neusoft.base.dal.dao.*"})
public class PacsServiceImpl implements PacsService {
    @Override
	public String receivePacsPathologicalRecord(String content) throws Exception {
        SoapReturnDto returnDto = new SoapReturnDto();
         return XmlSerializer.bean2Xml(returnDto);
     }
 }

5.2.3 发布public ws

SpringBoot中使用WebService(简单的使用)

import com.neusoft.listener.service.business.terminal.PacsService;
import org.apache.cxf.Bus;
import org.apache.cxf.jaxws.EndpointImpl;
@Configuration
public class CxfConfig {
    @Autowired
    private PacsService pacsService;
    
     /**
     * 检验
     *
     * @author Tony
     * @date
     */
    @Bean
    public Endpoint normalService() {
        EndpointImpl endpoint = new EndpointImpl(bus, normalService);
        endpoint.publish("/NormalService");
        return endpoint;
    }
    
     /**
     * 检查
     *
     * @author Tony
     * @date
     */
    @Bean
    public Endpoint pacsService() {
        EndpointImpl endpoint = new EndpointImpl(bus, pacsService);
        endpoint.publish("/PacsService");
        return endpoint;
    }
}

六、xml读取和webservice请求

webService开发完毕需要进行发布,发布需要借助:org.apache.cxf.jaxws.EndpointImpl.publish() 方法。

6.1 发起webservice请求

/**
 * @author dazer
 */
@Getter
public enum JwxWsShengjiMethodEnum {
    /**
     * 接口文档来源:
     * xpath使用,见 hutool https://www.hutool.cn/docs/#/core/工具类/XML工具-XmlUtil?id=xml%e4%b8%8e%e5%af%b9%e8%b1%a1%e8%bd%ac%e6%8d%a2
     */
    UPLOAD_CHILDREN_INFO("2、儿童信息上传接口", "web:uploadChildrenInfo", "//soapenv:Envelope/soapenv:Body/ns1:uploadChildrenInfoResponse/uploadChildrenInfoReturn"),
    DOWNLOAD_VACC_BY_CHILD_NO("3、异地接种查询接口之一(任何接种点都可以根据【childNo=?chilCode 档案编码】下载接种信息)","web:downloadVaccByChildNo", "//soapenv:Envelope/soapenv:Body/ns1:downloadVaccByChildNoResponse/downloadVaccByChildNoReturn"),
    DOWNLOAD_VACC_BY_BIRTH_NO("4、异地接种查询接口之二【暂时没有找到出生证 T610289178】(任何接种点都可以根据【birthNo 儿童出生证号】下载接种信息)","web:downloadVaccByBirthNo", "//soapenv:Envelope/soapenv:Body/ns1:downloadVaccByBirthNoResponse/downloadVaccByBirthNoReturn"),
    DOWNLOAD_VACC_BY_CHILD_ID("5、异地接种查询接口之三(任何接种点都可以根据【childId身份证,身份证可能下载不到,如:18个8】下载接种信息)","web:downloadVaccByChildID", "//soapenv:Envelope/soapenv:Body/ns1:downloadVaccByChildIDResponse/downloadVaccByChildIDReturn"),
    DOWNLOAD_VACC_BY_NAME("6、异地接种查询接口之四(根据建档地址、孩子姓名、母亲姓名查询儿童信息)","web:downloadVaccByName", "//soapenv:Envelope/soapenv:Body/ns1:downloadVaccByNameResponse/downloadVaccByNameReturn"),
    DOWNLOAD_MIGRATION_CHILD_NO("7、已在异地接种儿童编码下载接口(返回本接种点的儿童在异地接种的记录)","web:downloadMigrationChildNo", "//soapenv:Envelope/soapenv:Body/ns1:downloadMigrationChildNoResponse/downloadMigrationChildNoReturn"),
    ;
    /**
     * webservice请求方法
     * @param method endPoint 端点, 如:http://10.5.97.108:10001/ws/services/baseInfoWebService.baseInfoWebServiceHttpSoap12Endpoint/
     * @param method 方法名称,如:ws:getBatchs
     * @param xPath 获取有效数据的path, 如://soapenv:Envelope/soapenv:Body/ns:getBatchsResponse/ns:return
     */
    JwxWsShengjiMethodEnum(String methodName, String method, String xPath) {
        this.methodName = methodName;
        this.method = method;
        this.xPath = xPath;
    }
    private final String methodName;
    private final String method;
    private final String xPath;

    @Override
    public String toString() {
        return this.getMethodName();
    }
}
public static void main(String[] args) {

    Map<String, Object> paramsMap = new HashMap();
	String methodName = methodEnum.getMethodName();
            // webservice请求方法,如:ws:getBat
            String method = methodEnum.getMethod();
            // 返回xml,获取我们需要数据的路径,如:"//soapenv:Envelope/soapenv:Body/ns:getBatchsResponse/ns:return";
            String xPath = methodEnum.getXPath();
            // 处理params
            // 新建客户端
            /**
             * 完整地址:https://yqpt.xa.gov.cn/ws/services/baseInfoWebService.baseInfoWebServiceHttpSoap11Endpoint/
             */
            int timeoutSecond = vficProperties.getArchives().getTimeout();
            String nameSpaceUrl = "http://webservices.web.vaccine.nipm.jwx.com";
            // 必须添加soap action
            SoapClient client = SoapClient.create(endPoint, SoapProtocol.SOAP_1_2).
                    // 设置要请求的方法,此接口方法前缀为web,传入对应的命名空间
                            setMethod(method, nameSpaceUrl).
                    // 设置参数,此处自动添加方法的前缀:web
                            setParams(paramsMap, false).
                    timeout(timeoutSecond * 1000);
            Map<String, String> header = new HashMap<>(1);
            header.put("SOAPAction", endPoint);
            client.addHeaders(header);
	

     // 发送请求,参数true表示返回一个格式化后的XML内容
     // 返回内容为XML字符串,可以配合XmlUtil解析这个响应
	 String xmlStr="";
	 Document docResult = null;
	 try {
	      docResult = XmlUtil.readXML(xmlStr);
	  } catch (UtilException | IllegalArgumentException e) {
	      //xml 出错
	      log.error("xml parse 错误");
	  }
	// xpath使用,见 hutool https://www.hutool.cn/docs/#/core/工具类/XML工具-XmlUtil?id=xml%e4%b8%8e%e5%af%b9%e8%b1%a1%e8%bd%ac%e6%8d%a2
	String value = XmlUtil.getByXPath(xPath, docResult, XPathConstants.STRING) + "";
	log.debug("xml getByXPath获取数据 " + value);  
}

6.2 根据xml xpath获取取值 (XmlUtil.getByXPath)

// 发送请求,参数true表示返回一个格式化后的XML内容
     // 返回内容为XML字符串,可以配合XmlUtil解析这个响应
	 String xmlStr="";
	 Document docResult = null;
	 try {
	      docResult = XmlUtil.readXML(xmlStr);
	  } catch (UtilException | IllegalArgumentException e) {
	      //xml 出错
	      log.error("xml parse 错误");
	  }
	// xpath使用,见 hutool https://www.hutool.cn/docs/#/core/工具类/XML工具-XmlUtil?id=xml%e4%b8%8e%e5%af%b9%e8%b1%a1%e8%bd%ac%e6%8d%a2
	String value = XmlUtil.getByXPath(xPath, docResult, XPathConstants.STRING) + "";
	log.debug("xml getByXPath获取数据 " + value);  

6.3 解析XMl报错

6.3.1、Nested exception: 对实体 “XXX” 的引用必须以 ‘;’ 分隔符结尾

分析:xml value中包含,特殊符号,如:< 小于号、> 大于号、& 和、’ 单引号、" 双引号
参考:记异常:对实体 ”XXX“ 的引用必须以 ‘;’ 分隔符结尾

问题:xml搜索不到,就需要从:originalText base64解密出来查看

xml分隔符结尾 分隔符结尾

在这里插入图片描述
特殊符号

6.3.2、The parse error. rowNo[1]xPath[]to[]msg[Error on line 1 of document : 元素内容必须由格式正确的字符数据或标记组成。 Nested exception: 元素内容必须由格式正确的字符数据或标记组成。]

问题分析:xml正文内容包含: < 小于号、> 大于号、& 和、’ 单引号、" 双引号

EncodeDecode
xml在线格式化、校验
在线XML验证

xml格式错误

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Dazer007

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值