Version: Next

WebService

WebService 详解

  • WebService = HTTP + XML

  • HTTP 的高级语言实现基于 socket

  • Socket 是对 TCP/IP 和 UDP 协议的实现

  • 名词1:XML. Extensible Markup Language -扩展性标记语言

    • XML,用于传输格式化的数据,是Web服务的基础。
    • namespace-命名空间。
    • xmlns=“http://itcast.cn” 使用默认命名空间。
    • xmlns:itcast=“http://itcast.cn”使用指定名称的命名空间。
  • 名词2:WSDLWebService Description Language – Web服务描述语言。

    • 通过XML形式说明服务在什么地方-地址。
    • 通过XML形式说明服务提供什么样的方法 – 如何调用。
  • 名词3:SOAP-Simple Object Access Protocol(简单对象访问协议)

    • SOAP作为一个基于XML语言的协议用于有网上传输数据。
    • SOAP = 在HTTP的基础上+XML数据。
    • SOAP是基于HTTP的。
    • SOAP的组成如下:
      • Envelope – 必须的部分。以XML的根元素出现。
      • Headers – 可选的。
      • Body – 必须的。在body部分,包含要执行的服务器的方法。和发送到服务器的数据。

wsdl文件,详细说明了WebService请求段需要接收的参数形式

  • 以自定义格式的报文(定义在docx文件的5.3.31章节中)请求WebService地址,自己组装的报文是一种xml文件的格式,包含,最终转换为JSON格式在网络上传输(明文或加密)

  • 返回的也是这种报文格式,在docx文件中也规定了返回报文的格式,以JSON的形式返回

  • 业务关心的是中封装的数据

image-20200708151142510

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="http://www.sxylzinfo.com/">
<soapenv:Header/>
<soapenv:Body>
<web:transaction>
<reqdata>{"YWZT":"","YWFHID":"","YWJYNO":"3100","INPUT":"AAAAgMUvoJLpnla4eWx1xjUqxiKlmsW++820J5xl6Epi0Og6/9yPfDiAkW3FmmebLCz/ncfYVakm\r\n1e6jCEiUBdKMDi6cTsm+hDjPfN9/rARIPsusNhuprozS5tT4zcw062niRoy5Mm2CPdmOZU4CGrPN\r\nSintiUVnSBfwaIkGFb5I3cp8+LlVgQoVzEVrPuMf3sFyia0ZFFt8qM+Xv4ZsfBap3jMw/YaRd57P\r\n8qLBgUOK2T99YUxMqlnDnKFlofCcTUUPGHr60uhiucOfsqlv+9q1X1GCxNIomFkiupt2LT2wHDTX\r\nREGCfAsL5AkyeD3LloGajb1qpl3VWZXvOSy7krJdfMmzUcYrqHlWd+KGqer8m6B7e2MPvnOue5I=\r\n","APPREG":"jcyb1405310","ERRMSG":"","YWJYID":"140531020200708154036000000064","VERSION":"V1.0","USERID":"jcyb1405310","USERPW":"d410d7bcb7a4ea5dca16238142363297","SIGNATURE":"WArhnlmICimLPKzxQJPtejjh6IO6bVk2NUaAZ6ESdFEEn3zigADN3g9KncfjXOn0TvDzYIjdiEXP\r\nVCd2atAoz91NPoG1mS5okdtk8rywqtd9L0px5Yu9DCUUvgRqdt/aCi4NogR1PWicu+yPRtz+LMNe\r\nxtQy6k1AMtmBO1WAtsM=\r\n","FHTIME":""}</reqdata>
</web:transaction>
</soapenv:Body>
</soapenv:Envelope>
  • 单行soap响应
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="http://www.sxylzinfo.com/"><soapenv:Header/><soapenv:Body><web:transaction><reqdata>{"root":{"head":{"ReceiverAddress":"ReceiverAddress","SenderAddress":"SenderAddress","SenderName":"SenderName","TransactionSubCode":"TransactionSubCode","BusinessType":"BusinessType","TransRefGUID":"TransRefGUID","MessageDateTime":"MessageDateTime","TotalRecord":"TotalRecord","TransactionCode":"TransactionCode","StandardVersionCode":"StandardVersionCode","CorrelationId":"CorrelationId","SenderCode":"SenderCode","ReceiverName":"ReceiverName","ReceiverCode":"ReceiverCode","MessageId":"MessageId"},"body":{"MioQueryResponse":{"MessageStatusCode":"MessageStatusCode","Message":"Message","BusinessProcessStatus":{"PersonGUID":"PersonGUID","BusinessName":"BusinessName","ClaimNo":"ClaimNo","BusinessMessage":"BusinessMessage","MioInfoLst":{"AccCustName":"AccCustName","MioFlag":"MioFlag","MioDate":"MioDate","BankCode":"BankCode","PlnmioDate":"PlnmioDate","BankAccNo":"BankAccNo","MioAmnt":"MioAmnt"},"BusinessKeyNo":"BusinessKeyNo","BusinessStatus":"BusinessStatus","Name":"Name"}}}}}</reqdata></web:transaction></soapenv:Body></soapenv:Envelope>

WebService核心组件

  • XMLHTTP
  • SOAP:简单对象访问协议 Simple Object Access Protocal
  • WSDL: WebService 描述语言 Web Services Describe Language
  • UDDI:统一描述、发现和集成协议

WebService的实现框架

  • Axis1
  • Axis2
  • XFire
  • CXF

CXF

Apache CXF = Celtix + XFire

Apache CXF的前身叫做Apache CeltXFire,现在正是更名为Apache CXF。

CFX继承了Celtix和XFire两大开源项目的精华,提供了对JAX-WS全面的支持,并且提供了多种BindingDataBindingTransport以及各种Format的支持,并且可以根据实际项目的需要,采用代码优先Code First或者WSDL优先WSDL First来轻松的实现Web Services 的发布和使用

  • 代码优先 Code First
  • 契约优先 WSDL First

@WebService (服务端)

在interface上使用这个注解,将接口暴露为一个WebService服务

JaxWsServerFactoryBean

  • setAddress(url)——设置暴露WebService的url
  • setServiceCLass(Xxx.class)——设置WebService中实际处理业务的类,就是使用@WebService注解的接口的实现类的.class对象
  • create()——返回一个Server对象
  • server.start()——启动WebService服务

直接访问暴露的url+?wsdl,即url?wsdl,例如http://localhost:8080/myWebService?wsdl,就可以直接看到响应的wsdl xml文件

直接访问暴露的url,例如http://localhost:8080/myWebService,就可以直接看到响应的soap xml文件 (会抛个异常出来)

使用MyEclipse自测

  • Web Services Explorer
  • 右上角WSDL Page
  • WSDL Page
  • Navigator栏中选择WSDL Main
  • 输入WebService的url,单击go
  • Status中显示successfully opened

客户端

  • 建立JaxWsProxyFactoryBean对象
  • setAddress(url)——设置要访问的WebService url
  • setServiceClass(接口.class)——设置处理WebService的接口的.class对象,之所以填接口,是因为服务器向外暴露接口,而不暴漏实现类,是规范
  • create()——返回Object,强制类型转换为上面设置的接口
  • 调用接口方法

SOAP协议解析

SOAP协议 + TCP/IPMoniter监控

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="http://www.sxylzinfo.com/">
<soapenv:Header/>
<soapenv:Body>
<web:transaction>
<reqdata>{"YWZT":"","YWFHID":"","YWJYNO":"3100","INPUT":"AAAAgMUvoJLpnla4eWx1xjUqxiKlmsW++820J5xl6Epi0Og6/9yPfDiAkW3FmmebLCz/ncfYVakm\r\n1e6jCEiUBdKMDi6cTsm+hDjPfN9/rARIPsusNhuprozS5tT4zcw062niRoy5Mm2CPdmOZU4CGrPN\r\nSintiUVnSBfwaIkGFb5I3cp8+LlVgQoVzEVrPuMf3sFyia0ZFFt8qM+Xv4ZsfBap3jMw/YaRd57P\r\n8qLBgUOK2T99YUxMqlnDnKFlofCcTUUPGHr60uhiucOfsqlv+9q1X1GCxNIomFkiupt2LT2wHDTX\r\nREGCfAsL5AkyeD3LloGajb1qpl3VWZXvOSy7krJdfMmzUcYrqHlWd+KGqer8m6B7e2MPvnOue5I=\r\n","APPREG":"jcyb1405310","ERRMSG":"","YWJYID":"140531020200708154036000000064","VERSION":"V1.0","USERID":"jcyb1405310","USERPW":"d410d7bcb7a4ea5dca16238142363297","SIGNATURE":"WArhnlmICimLPKzxQJPtejjh6IO6bVk2NUaAZ6ESdFEEn3zigADN3g9KncfjXOn0TvDzYIjdiEXP\r\nVCd2atAoz91NPoG1mS5okdtk8rywqtd9L0px5Yu9DCUUvgRqdt/aCi4NogR1PWicu+yPRtz+LMNe\r\nxtQy6k1AMtmBO1WAtsM=\r\n","FHTIME":""}</reqdata>
</web:transaction>
</soapenv:Body>
</soapenv:Envelope>

什么是SOAP协议

  • 简单对象访问协议SOAP Simple Object Access Protocal,是一种轻量的、简单的、基于XML的协议,它被设计成在WEB上交换结构化的和固化的信息
  • SOAP是基于XML的简易协议。可使用应用程序在HTTP之上进行信息交换

SOAP长什么样子(报文格式)

  • 一条SOAP消息就是一个普通的XML文档
  • 必需的Envelope元素,可以把此XML文档表示为一条SOAP消息
  • 可选的Header元素,包含头部信息
  • 必须的Body元素,包含所有的调用和响应信息
  • 可选的Fault元素,提供有关在处理此消息时发生的错误信息

抓包查看

使用MyEclipse的 TCP/IP Monitor

设置一个端口号,将WebService客户端访问的端口更改为TCP/IP Monitor设置的端口

结论:SOAP是用于访问网络服务的协议

一次WebService的调用,不是方法的调用,而是SOAP消息(XML格式规范的文档片段)之间的输入输出

  1. 客户端到UDDI上寻找Service目录 (地址、端口、具体服务)
  2. 客户端获得WSDL文件
  3. 客户端按照WSDL文件的约束和规范创建SOAP客户端
  4. 客户端通过SOAP访问Service

image-20200709091249020


WSDL报文解析

可以使用MyEcplise的WSDL Editor查看图形化的WSDL文件

image-20200709100457327

根元素:

  • definitions——命名空间:根元素

子标签:

  • types——WebService使用的数据类型
  • message两个——WebService使用的消息 SOAP中的输入输出数据
  • portType——WebService执行的操作,规定格式
  • binding——WebService使用的通信协议
  • service——WebService对外暴露的服务
<definitions>
<types>
定义WebService使用的数据类型
</types>
<message>
每个消息均有一个或多个部件组成,可以把它当作Java中一个函数调用的参数,两条,请求和返回
</message>
<portTyoe>
它类似Java中的一个函数库(或一个模块,或一个类)
WebService中暴露的接口名
</portTyoe>
<binding>
为每个端口定义消息格式和协议细节
</binding>
</definitions>

definitions

子标签含义
xmlns:tns相当于Java中的import,包名反转
name在Java程序中服务接口的实现类,SEI定义是。服务接口类+Service后缀,Service会自动追加
targetNamespace命令空间:相当于Java里面的package,它刚好和Java定义报名相反
其他不变化、不关心

types

Java定义的服务接口中某方法的输入参数和返回值

xs:schema -> xs:element

xs:complexType 复杂类型 | 指定方法名

要求参数传入顺序,与定义顺序一致

xs:sequence

-> 还可以继续接xs:sequence

image-20200709094318303

还有个sayHelloResponse,里面写的是接口方法的返回值类型信息

说白了就是把WebService的接口名字,接口参数,返回类型写了一遍

  • 问题:WSDL中的形参都写成了arg0arg1这样的形式,如果参数多了,读起来一脸懵逼
  • 配置别名映射

使用别名映射

  • 在WebService的服务接口内,在其接口方法上使用@WebMethod注解
  • 在方法上使用@webResult(name = "your name"),更改方法名字
  • 方法的参数上使用@WebParam("别名")给参数起别名
@WebService
public interface HelloWorld {
@WebMethod
@WebResult(name = "sayHelloRetValue")
public String sayHello(@WebParam(name = "username") String name, @WebParam(name = "userage") int age);
}

message

通信消息的数据结构的抽象类型化定义。使用Types所定义的类型来定义整个消息的数据结构

<wsdl:message name="sayHelloResponse">
<wsdl:part element="tns:sayHelloResponse" name="parameters"></wsdl:part>
</wsdl:message>
<wsdl:message name="sayHello">
<wsdl:part element="tns:sayHello" name="parameters"></wsdl:part>
</wsdl:message>

WebService中每个方法包含两部分:

  • 方法输入参数
  • 方法输出参数

实质上都是基于SOAP协议将其封装为消息,所以每个方法对应有两个消息,一个输入一个输出回应。简单而言,就是方法和Message的关系是N:2N的关系,一对二

Message中的具体内容是part,结合前面可知,message中的part内容请到前面types中去看,它会引用之前types相关内容

portType——暴露出的WebService接口名字

<wsdl:portType name="HelloWorld">
<wsdl:operation name="sayHello">
<wsdl:input message="tns:sayHello" name="sayHello"></wsdl:input>
<wsdl:output message="tns:sayHelloResponse" name="sayHelloResponse"></wsdl:output>
</wsdl:operation>
</wsdl:portType>
  • portType——接口名
  • operation——接口中定义的方法

binding

特定端口类型的具体协议和数据格式规范的绑定

image-20200709102356644

<wsdl:binding name="HelloWorldImplServiceSoapBinding" type="tns:HelloWorld">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="sayHello">
<soap:operation soapAction="" style="document"/>
<wsdl:input name="sayHello">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="sayHelloResponse">
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>

service

暴露主机信息

<wsdl:service name="tns:HelloWorldImplService">
<wsdl:port binding="tns:HelloWorldImplServiceSoapBinding" name="HelloWorldImplPort">
<soap:address location="http://localhost:9999/cxf1022_server"/>
</wsdl:port>
</wsdl:service>

干活怎么看WSDL

  • 先看wsdl service,可以找到暴露的主机地址
  • 再看portType,可以找到这个主机上暴露的WebService接口的名字
  • 再看portType里的operation,就是接口里定义的方法,根据operationname找到对应的message
  • 根据messageparameters找到对应的Types
  • 再看Types,里面是接口方法的传入形参和返回值类型