WebService原理及重要术语
作者:互联网
WebService就该这么学
一:WebService简介
1:WebService介绍
WebService是一个平台独立的、低耦合的、自包含的、基于可编程的web应用程序,可使用开放的XML来描述、发布、发现、协调和配置这些应用程序,用于开发分布式交互操作的应用程序。
WebService技术,能运行在不同机器上的不同应用无须借助附加的、专门的第三方软件或硬件,就可相互交换数据或集成。依据WebService规范实施的应用之间,无论它们所使用的语言、平台或内部协议是什么,都可以相互交换数据。这么说吧,其实WebService就是一种跨编程语言和跨操作系统平台的远程调用技术(RPC的一种实现方式)。所谓可跨编程语言,就是说服务端程序和客户端程序可以以不同的语言编写也可以利用WebService互相调用;跨操作系统平台则是指服务端程序和客户端程序可以在不同的操作系统上运行。远程调用,就是一台计算机的应用可以调用其他计算机上的应用。例如:我自己编写一个网站,里面想要个天气预报的功能,这个时候我肯定去调用气象局的接口服务而不是我自己发射卫星来监测天气,再引入我网站里。
2:为什么使用WebService
WebService能解决跨平台调用、跨语言调用、远程调用(RPC)
以各个网站显示天气预报功能为例,气象中心的管理系统将收集的天气信息并将数据暴露出来(通过WebService Server),而各大站点的应用就去调用它们得到天气信息并以不同的样式去展示(WebService Client),我们网站虽然提供了天气预报的服务,但其实它们什么也没有做,只是简单的调用了一下气象中心服务器服务接口而已。
3:WebService原理及重要术语
XML、SOAP、WSDL 是构成WebService平台的三大技术
一:基本术语
UDDI:Universal Description, Discovery, and Integration(统一描述、发现和集成) UDDI是OASIS发起的一个开放项目,它使企业在互联网上可以互相发现并且定义业务之间的交互。 SOAP:simple object access protocal(简单对象访问协议) ①:是一种简单的、基于HTTP和XML的协议, 用于在WEB上交换结构化的数据,结构化数据实际上就是xml的数据 ②:SOAP消息:请求消息和响应消息 ③:HTTP+XML片断 WSDL:web service definition language(WebService定义语言) ①:对应一种类型的文件.wsdl ②:定义了WebService的服务器端与客户端应用交互传递请求和响应数据的格式和方式 ③:一个WebService对应一个唯一的wsdl文档(理解为接口说明书) SEI:WebService EndPoint Interface(终端,WebService的终端接口) ①:就是WebService服务器端用来处理请求的接口;我们可以理解为是xxxWebService的各个xxxWebServiceImpl实现类 CXF:Celtix + XFire,一个apache的用于开发webservice服务器端和客户端的框架
WebService基本原理
①:WebService是采用HTTP协议在客户端和服务端之间传输数据 ②:WebService传输的数据是使用XML封装后再传输交互,XML的优点在于它的跨平台性(因为市面上的语言基本上都支持xml解析) ③:WebService发送的请求内容和响应内容都采用XML格式封装,并增加了一些特定的HTTP消息头,以说明HTTP消息的内容格式,这些特定
的HTTP消息头和XML内容格式就是SOAP协议规定的 ④:WebService服务器端首先要通过一个WSDL文件来说明自己有什么服务可以对外调用。简单的说,WSDL就像是一个说明书,用于
描述WebService及其方法、参数和返回值。 WSDL文件保存在Web服务器上,通过一个url地址就可以访问到它。客户端要调用
一个WebService服务之前,要知道该服务的WSDL文件的地址。 ⑤:WebService交互的过程就是,WebService遵循SOAP协议通过XML封装数据,然后由Http协议来传输数据。 注:WebService服务提供商可以通过两种方式来暴露它的WSDL文件地址: 1:注册到UDDI服务器,以便被人查找 2:直接告诉给客户端调用者 总结:要想编写WebService接口就一定要以SOAP请求来传输数据(HTTP+XML),编写完成后把服务暴露到UDDI服务器上,这时调用者
可以通过指定的URL来生成WSDL
4:WebService两种开发方式
1:JAX-WS(Java API for XML Web Service): JAX-WS规范是一组XML web services的JAVA API,JAX-WS允许开发者可以选择RPC-oriented或者message-oriented 来实现自己的web services。 在JAX-WS中,一个远程调用可以转换为一个基于XML的协议例如SOAP,在使用JAX-WS过程中,开发者不需要编写任何生成和处 理SOAP消息的代码。JAX-WS的运行时实现会将这些API的调用转换成为对应的SOAP消息 缺点:我们必须借助WSDL说明书来生成一个java客户端代码,后期就像调用方法一样调用 2:JAX-RS(Java API for RESTful Web Servicecs): 是一个Java编程语言的应用程序接口,支持按照表述性状态转移(REST)架构风格创建Web服务。JAX-RS使用了JavaSE5引入 的Java标注来简化Web服务的客户端和服务端的开发和部署。 优点:不用编写客户端,只需要服务端提供RESTFul的URL调用即可
二:WebService服务端和客户端的开发(了解)
注:本章节案例用的全部注解在后面专门介绍(此章只是入门案例,具体在文章后面集成说明)!!!!!
此章里面的方式了解即可,因为在实际开发中都是以Spring来集成CXF方式开发服务端和客户端;
JAX-WS就是我们俗称的JDK(JDK版本1.6+才可以)开发,因为JDK自带这种方式开发客户端和服务端
Apache CXF = Celtix + XFire,ApacheCXF 的前身叫 Apache CeltiXfire,现在已经正式更名为 Apache CXF 了,以下简称为 CXF。CXF 继承了 Celtix 和XFire 两大开源项目的精华,提供了对 JAX-WS 全面的支持,并且提供了多种 Binding 、DataBinding、Transport 以及各种 Format 的支持,并且可以根据实际项目的需要,采用代码优先(Code First)或者 WSDL 优先(WSDL First)来轻松地实现 Web Services 的发布和使用。
1:使用JAX-WS开发服务端 (熟悉流程)
基本实体类Student、Dog SEI接口及接口实现类 服务发布完成到这一步后我们的服务端就编写好了,接下来我们就要测试我们当前发布的服务是否可以访问,这时候我们就要访问我们当前编写服务的WSDL说明书,WSDL服务访问必须是我们发布的服务地址后加上?wsdl才可访问;我们通过阅读wsdl可以确定客户端要怎么调用该服务端,wsdl定义了接口、方法、参数、返回值,告知我们以指定规范来调用服务端
说明:使用JDK自带的WebService是没有拦截器的,在这里大家知道它没有拦截器功能即可!!!!!!!
2:使用JAX-WS开发客户端(熟悉流程)
其实客户端调用服务端的方法有很多,但在大多情况下我们都是用工具生成客户端代码,这里我们就用到wsimport.exe工具(JDK的bin目录下自带此工具,因为JAX-WS写的服务本身就是JDK拥有的,所以也有生成客户端工具)是jdk自带的webservice客户端工具可以根据wsdl文档生成客户端调用代码(java代码)。当然,无论服务器端的WebService是用什么语言写的,都可以生成调用webservice的客户端代码
客户端调用 TestClient类3:使用CXF_WS开发服务端(WS方式)
基本实体类Student、Dog SEI接口及接口实现类 pom.xml坐标文件 TestMain服务端发布代码 log4j.properties日志配置文件 完成到这一步后我们访问 http://127.0.0.1:9999/WebService/student?wsdl 来查看我们的wsdl说明书(注SEI接口不要添加@WebService),查询到wsdl我们就可以开发客户端了
4:使用CXF_WS开发客户端(WS方式)
在上面我们介绍了JDK自带的wsimport.exe执行文件,其实用此工具也是可以生成CXF_WS的客户端代码,但是我们既然都知道是CXF写的了,何必不用CXF自家的客户端生成工具呢?所以我就介绍一些CXF特有的生成客户端工具 wsdl2java
cxf是Apache的,所以我们要去下载一个 apache-cxf-x.x 按照自己合适的版本来,我下载的是apache-cxf-3.4.4.zip ,解压后在bin目录下就有wsdl2java工具,此时如果想随时随地cmd使用我们就得去配置环境变量,大家自己像maven的配置方式配置,保证可以找到cxf的bin目录里面(我就不配置了,直接访问到此文件夹里)
基本使用wsdl2java 基本语法:wsdl2java -d '生成客户端的位置' -client '?wsdl地址或者wsdl文件' -p: 指定其wsdl的命名空间,也就是要生成代码的包名 -d: 指定要产生代码所在目录 -client: 生成客户端测试web service的代码 -server: 生成服务器启动web service的代码 -impl: 生成web service的实现代码 -ant: 生成build.xml文件 -all: 生成所有开始端点代码:types,service proxy,,service interface, server mainline, client mainline, implementation object, and an Ant build.xml file. 如我当前使用: wsdl2java -d C:\Users\xiaof\Desktop\client -client http://127.0.0.1:9999/WebService/student?wsdl wsdl2java -d C:\Users\xiaof\Desktop\client -client C:\Users\xiaof\Desktop\student.wsdl
说到这,我们就可以生成客户端代码在我们的项目中了,关于cxf_ws的项目我们要引入一些指定的坐标
pom.xml坐标文件 客户端调用代码5:使用CXF_RS开发服务端(restful方式)
此结构与CXF-WS目录是一样的定义,只是代码改变,此方式是没有wsdl说明书的,客户端无需使用WSDL来生成客户端代码可以直接调用
基本实体类Student、Dog SEI接口及接口实现类 服务发布TestMain pom.xml坐标文件 log4j.properties日志文件注意:
①:我们在访问时界面出现这种错误提示
提示内容:此页面包含以下错误:第1列第1行上的错误:文档为空。下面是直到第一个错误的页面呈现
此原因是因为我们没有在对应的实体类上添加@XmlRootElement注解导致无法映射为XML,从而导致文档为空
# 因为CXF_RS开发的服务端,在客户端是可以直接调用的,比如在浏览器中调用Get请求 http://localhost:7777/WebService/student/findAll/22响应JSON数据在浏览器界面
6:使用CXF_RS开发客户端(restful方式)
我们使用CXF_RS开发客户端会使用到一个叫CXF的WebClient的工具类(后面章节介绍),可以发送不同类型的请求
在编写客户端之前,我们需要把服务端的实例对象复制到客户端里
pom.xml坐标文件 客户端类代码问题:
<!--客户端加上此坐标可以转换为json数据--> <!--服务端加上此坐标可以解析json数据--> <!--下面这两个坐标不设置就会导致 是发送端无法转换json发送,是接收端无法把json转换为对象接收--> <!--设置CXF提供者坐标--> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-rs-extension-providers</artifactId> <version>3.4.3</version> </dependency> <!--JSON转换坐标,会集成到CXF的providers里--> <dependency> <groupId>org.codehaus.jettison</groupId> <artifactId>jettison</artifactId> <version>1.4.1</version> </dependency>
三:使用SoapUI工具监控请求及响应
file --> New SOAP Project 创建SOAP请求 file --> New REST Project 创建Rest请求(后面说)
四:WSDL说明书详细说明(重要)
如果你对 XML 不熟悉的请先研究一下 XML ==> 直达XML学习地址 学习一下 Schema 约束那一章
下面我就以如下的文件来详细分析一下 WSDL 说明书,这个文件是由我上面的 JAX-WS 案例生成的
示例wsdl说明书:http://localhost:8888/WebService/student?wsdl 示例wsdl类型说明书:http://localhost:8888/WebService/student?xsd=1wsdl文档说明书是由definitions标签来包裹,内部有 五大标签各司其职 分别为 service、binding、portType、message、types 这五大标签我将在下面一一介绍
1:WSDL报文之 definitions
<definitions xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://www.w3.org/ns/ws-policy" xmlns:wsp1_2="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://impl.webservice.xw.cn/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://impl.webservice.xw.cn/" name="StudentWebServiceImplService"> <!--内部标签省略.....`--> </definitions> 标签: definitions:根元素 每个wsdl文件包含一个根元素,内部定义一些属性 属性: xmlns:tns:引用 相当于Java里面的import包的反转路径 name:SEI定义名称 我们Java程序中的接口实现类,SEI定义规则是:服务接口类+Service后缀,Service系统自动追加 targetNamespace:命名空间 相当于Java里面的package,它刚好是和我们定义的的包名相反 其它属性:出现的其它属性不能改动,必须那样写,因为是整篇wsdl说明书的约束条件
2:WSDL报文之 types
定义Web服务里用到的,XMLSchema定义的数据类型以外的自定义数据类型,对于我们自定义的类(Student),会对应到一个<complexType>(复杂类型标签),其中用<element>元素指定每个参数的类型。
<types> <xsd:schema> <xsd:import namespace="http://impl.webservice.xw.cn/" schemaLocation="http://localhost:8888/WebService/student?xsd=1"/> </xsd:schema> </types> 标签:types 定义Web服务中用到的请求与响应的数据类型 标签:xsd:schema 约束标签,用来指定内部类型按照指定规范编写 标签:xsd:import 导入外部文件 属性: namespace:命名空间 schemaLocation:约束文件地址 如下是http://localhost:8888/WebService/student?xsd=1约束文件 <xs:schema xmlns:tns="http://impl.webservice.xw.cn/" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0" targetNamespace="http://impl.webservice.xw.cn/"> <!--定义countAllStudent方法的请求类型 指定的类型是countAllStudent--> <xs:element name="countAllStudent" type="tns:countAllStudent"/> <!--定义countAllStudentResponse方法的响应类型 指定的类型是countAllStudentResponse--> <xs:element name="countAllStudentResponse" type="tns:countAllStudentResponse"/> <!--定义findByName方法的请求类型 指定的类型是findByName--> <xs:element name="findByName" type="tns:findByName"/> <!--定义findByNameResponse方法的响应类型 指定的类型是findByNameResponse--> <xs:element name="findByNameResponse" type="tns:findByNameResponse"/> <!--定义一个复杂类型,但此类型为空(就是说countAllStudent方法为空参数)--> <xs:complexType name="countAllStudent"> <xs:sequence/> </xs:complexType> <!--定义一个复杂类型,返回的是一个序列(参数按照要求位置)--> <xs:complexType name="countAllStudentResponse"> <xs:sequence> <!--此处告诉我们是一个响应的return参数,此时的参数类型为int 并且至少出现0次--> <xs:element name="return" type="xs:int" minOccurs="0"/> </xs:sequence> </xs:complexType> <!--后面不会的请参考具体的xml学习--> <!--后面的省略........--> </xs:schema>
3:WSDL报文之 message
具体定义了在通信中使用的消息的数据结构,Message元素包含了一组Part元素,每个Part元素都是最终消息的一个组成部分,每个Part都会引用一个DataType(就是part里的element属性)来表示它的结构。
<message name="findByName"> <part name="parameters" element="tns:findByName"/> </message> <message name="findByNameResponse"> <part name="parameters" element="tns:findByNameResponse"/> </message> <message name="countAllStudent"> <part name="parameters" element="tns:countAllStudent"/> </message> <message name="countAllStudentResponse"> <part name="parameters" element="tns:countAllStudentResponse"/> </message> 标签:message 用来定义请求/响应消息的结构 属性: name:方法名称 标签:part 指定引用types中定义的标签片段 属性: name:此时说明都是参数 element:引用指定的类型,类型在types中定义 大白话: 我们编写的SEI实现类的某一个方法会对于的两个message,分别对象请求message和响应message 而不管请求还是响应message都会有参数的传输,比如请求的message是有个请求参数的,这个请求参数 的类型就是在此处说明,并引用types定义的具体复杂类型
4:WSDL报文之 portType
Operation是对服务中所支持的操作的抽象描述,一般单个Operation描述了一个访问入口的请求/响应消息对。
PortType具体定义了一种服务访问入口的类型,就是输入/输出消息的模式及其格式。一个PortType可以包含若干个Operation,而一个Operation则是指访问入口支持的一种类型的调用。在WSDL里面支持四种访问入口调用的模式如单请求、单响应、请求/响应、响应/请求。
在这里请求指的是从客户端到Web服务端,而响应指的是从Web服务端到客户端。PortType的定义中会引用消息定义部分的一个到两个消息,作为请求或响应消息的格式。
<portType name="StudentWebServiceImpl"> <operation name="findByName"> <input wsam:Action="http://impl.webservice.xw.cn/StudentWebServiceImpl/findByNameRequest" message="tns:findByName"/> <output wsam:Action="http://impl.webservice.xw.cn/StudentWebServiceImpl/findByNameResponse" message="tns:findByNameResponse"/> </operation> <operation name="countAllStudent"> <input wsam:Action="http://impl.webservice.xw.cn/StudentWebServiceImpl/countAllStudentRequest" message="tns:countAllStudent"/> <output wsam:Action="http://impl.webservice.xw.cn/StudentWebServiceImpl/countAllStudentResponse" message="tns:countAllStudentResponse"/> </operation> </portType> 标签:portType 用来定义服务器端的SEI接口 属性: name:定义我们的实现类名称 标签:operation 用来指定SEI中的处理请求的方法,一般分为请求和响应 属性: name:SEI实现类里的具体实现方法 标签:input 指定客户端请求过来的数据,它会引用我们定义的message标签来强行约束类型 属性: message:引用请求消息的约束 标签:output 指定服务端响应回去的数据,它会引用我们定义的message标签来强行约束类型 属性: message:引用响应消息的约束
5:WSDL报文之 binding
此标签包含了如何将抽象接口的元素(portType)转变为具体表示的细节,具体表示也就是指特定的数据格式和协议的结合;特定端口类型的具体协议和数据格式规范的绑定。JAX-RPC规范规定,SOAP绑定可以有rpc和document两种类型,分别表示远程过程调用和基于消息的方式。use属性可以是encoded或literal,对于前者要支持rpc的方式,对于后者要支持rpc和document的方式。
<binding name="StudentWebServiceImplPortBinding" type="tns:StudentWebServiceImpl"> <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/> <operation name="findByName"> <soap:operation soapAction=""/> <input> <soap:body use="literal"/> </input> <output> <soap:body use="literal"/> </output> </operation> <operation name="countAllStudent"> <soap:operation soapAction=""/> <input> <soap:body use="literal"/> </input> <output> <soap:body use="literal"/> </output> </operation> </binding> 标签:binding 用于定义服务器端的SEI接口实现类 属性: name:实现类名称 type:此时这里是引用portType指定标签 标签:soap:binding 绑定什么类型的数据用来请求响应 属性: type:绑定的数据是一个document(就是xml格式类型的请求响应) 标签:operation 用来指定SEI中的处理请求的方法,一般分为请求和响应 属性: name:SEI实现类里的具体实现方法 标签:input和output 指定客户端请求和服务端响应过来的数据类型 属性: use:定义类型literal(文本) 结合上面可以看出当前的SEI实现类只可以用document(xml)类型来交互,并且里面的方法是使用xml的文本方式交互
6:WSDL报文之 service
描述的是一个具体被部署的Web服务所提供的所有访问入口的部署细节,一个Service往往会包含多个服务访问入口,而每个访问入口都会使用一个Port元素来描述
<service name="StudentWebServiceImplService"> <port name="StudentWebServiceImplPort" binding="tns:StudentWebServiceImplPortBinding"> <soap:address location="http://localhost:8888/WebService/student"/> </port> </service> 标签:service 一个WebService的容器 属性: name:它用来指定客户端容器类 标签:port 用来指定一个服务器处理的请求入口(就是SEI的实现,理解为实现类) 属性: binding:引用具体的<binding/>标签 name:具体的实现类对象,正如 factory.getStudentWebServiceImplPort()获取实现类对象 标签:soap:address 用来说明当前WebService的请求地址 属性: soap:address.location:标明具体的WebService请求地址
五:WebService开发常用注解介绍
1:@WebService
此注解主要是标注当前是个WebService服务
@WebService serviceName: 对外发布的服务名,指定 WebService 的服务名称;缺省值为Java类的非限定名称+"Service" 修改:wsdl:service["name"] 修改:wsdl:definitions["name"] name: 设置端口类型名称,缺省值为Java接口或者类的非限定名称 修改:wsdl:portType["name"] portName: 设置端口类型名称,缺省值为端口类型名称(就是我们设置的name或者缺省)+"Port" 修改:wsdl:port["name"] targetNamespace: 指定WebService生成的WSDL和XML元素命名空间,缺省为 "http://"+当前接口的包名倒排 修改:wsdl:definitions["xmlns:tns"] 修改:wsdl:definitions["targetNamespace"] endpointInterface: 用于定义服务的抽象WebService的服务端点的限定名,如果指定了限定名,则会使用改服务端接口来确定抽象WSDL约束 wsdlLocation: 指定用于定义WebService的WSDL文档的Web地址。Web地址可以是相对路径或绝对路径 注: ①:实现类上可以不添加 @WebService ②:如果@WebService在SEI实现类上添加后可以指定endpointInterface属性来告知SEI接口限定类名
2:@WebMethod
此注解主要是标注WebService方法的具体名称
@WebMethod operationName: 指定SEI方法的具体名称,缺省值为Java方法名称 修改:wsdl:operation["name"] action: 定义操作的行为,缺省值为"" 修改:soap:operation["soapAction"] exclude: 指定是否从WebService中排除某一方法,缺省值为false 注: ①:此注解添仅支持添加在方法上,且当前方法的类上必须存在@WebService注解才可使用
②:修改operationName会导致客户端调用的方法名称改变
4:@Oneway
此注解必须写在带有@WebService的类方法上,它是声明此方法只有输入消息而没有输出消息的WebService单向操作
5:@WebParam
此注解主要标注参数至WebService消息部件和XML元素的映射,不指定WebService参数名称则默认xs:element["name"] = "args[0~*]"
@WebParam name: 交互方法的参数名称,如果操作是远程过程调用(RPC)类型并且未指定partName属性,那么这是用于表示参数的wsdl:part属性的名称 如果操作是文档类型或者参数映射至某个头,那么name是用于表示该参数的XML元素的局部名称。 如果操作是文档类型、参数类型为BARE并且方式为OUT或INOUT,那么必须指定此属性 targetNamespace: 指定返回值的XML名称空间。仅当操作类型为RPC或者操作是文档类型并且参数类型为BARE时才使用此参数 header: 指定头中是否附带结果。缺省值为false partName: 指定RPC或DOCUMENT/BARE操作的结果的部件名称。缺省值为@WebResult.name
6:@WebResult
此注解主要标注从返回值至WSDL部件或XML元素的映射
@WebResult name: 当返回值列是在WSDL文件中并且在连接上的消息中找到该返回值时,指定该返回值的名称。 对于RPC绑定,这是用于表示返回值的wsdl:part属性的名称。对于文档绑定,name参数是用于表示返回值的XML元素的局部名。 对于RPC和DOCUMENT/WRAPPED绑定,缺省值为return。对于DOCUMENT/BARE绑定,缺省值为方法名 + Response。 targetNamespace: 指定返回值的XML名称空间。仅当操作类型为RPC或者操作是文档类型并且参数类型为BARE时才使用此参数。 header: 指定头中是否附带结果。缺省值为false partName: 指定RPC或DOCUMENT/BARE操作的结果的部件名称。缺省值为@WebResult.name
7:@HandlerChain
注释用于使 Web Service 与外部定义的处理程序链相关联。只能通过对 SEI 或实现类使用 @HandlerChain 注释来配置服务器端的处理程序。
但是可以使用多种方法来配置客户端的处理程序。可以通过对生成的服务类或者 SEI 使用 @HandlerChain 注释来配置客户端的处理程序。此外,可以按程序在服务上注册您自己的 HandlerResolver 接口实现,或者按程序在绑定对象上设置处理程序链。
@HandlerChain file: 指定处理程序链文件所在的位置。文件位置可以是采用外部格式的绝对 java.net.URL,也可以是类文件中的相对路径 name: 指定配置文件中处理程序链的名称
8:@XmlRootElement
类级别的注解。将类映射为xml全局元素,也就是根元素
@XmlRootElement name: 类级别的注解。将类映射为xml全局元素,也就是根元素 namespace: namespace属性用于指定生成的元素所属的命名空间
9:@XmlSeeAlso
指示JAXB在绑定此类时也绑定其他类;
@XmlSeeAlso value: 类级别的注解。映射属性内部类型,value是class[]类型
@XmlRootElement(name = "Result") @XmlSeeAlso({Student.class}) public class Result<T> { private Integer code; //响应码 private String msg; //响应信息 //示例这个T可能是Student ,但也有可能会是别的类型,把可能出现的类型列举在@XmlSeeAlso private List<T> data; //响应数据 }
六:WebService开发RS方式类型特有注解
具体API官方文档 进入文档使用全文匹配搜索Ctrl+f 搜索 ' javax.ws.rs '
1:@Path
标识资源类或类方法将为其请求提供服务的URI路径。
@Path value: 设置请求路径名称,(和SpringMVC的@RequestMapping一个道理) 注意:资源路径是以RSETful风格的路径 GET方式: http://localhost/student/findById/23 @Path("/student/findById/{id}") POST方式: http://localhost/student/save @Path("/student/save")
2:@GET、@PUT、@POST、@DELETE
标注方法是用什么请求的HTTP才可以匹配到此方法,无属性
3:@Produces
定义资源类或MessageBodyWriter的方法可以生成的媒体类型;说白了就是告诉当前方法的响应MIME媒体类型
@Produces value: MIME类型名称 示例 @Produces(value = {"application/json;charset=utf-8"}) 返回JSON类型并且是UTF-8格式 @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) 可以返回XML类型以及JSON类型 MediaType枚举类定义了各种类型 类型举例: text/plain 文本类型 text/html HTML类型 application/json JSON类型 application/xml XML类型 image/png PNG类型
4:@Consumes
定义资源类或MessageBodyReader的方法可以接受的媒体类型;说白了就是告诉当前方法的请求MIME媒体类型
@Consumes value: MIME类型名称 使用上和@Produces一样,是个对应关系,一个请求和一个响应
5:@PathParam
将URI模板参数或包含模板参数的路径段的值绑定到资源方法参数、资源类字段或资源类Bean属性;说白了就是绑定RESTful风格的URL后面的参数到方法参数上
@PathParam value: 绑定的名称,注意要和URL里被{}括起来的名称一一对应 示例: @DELETE @Path("/delete/{id}") @Produces(value = {"application/json;charset=utf-8"}) void deleteById(@PathParam(value = "id") String id);
6:@MatrixParam
将URI的Matrix参数的值绑定到资源方法参数、资源类字段或资源类Bean属性。
@MatrixParam value: 获取Matrix参数,名称要和URL里的名称对应@MatrixParam具体使用及介绍
7:@QueryParam
将HTTP查询参数的值绑定到资源方法参数、资源类字段或资源类Bean属性。说白了就是绑定问号后的参数 ?x=x&z=z
@QueryParam value: 从URL中提取指定名称的参数;适用于?xxx=xxx&zzz=zzz@QueryParam注解使用介绍
8:@FormParam
将URI模板参数或包含模板参数的路径段的值绑定到资源方法参数、资源类字段或资源类Bean属性。说白了就是绑定POST提交的Form参数,其中Content-Type被假设为application/x-www-formurlencoded。
@FormParam value: 表单提交的键名称
具体操作和@QueryParam差不多,只是@QueryParam是直接绑定URL上,而@FormParam是绑定POST提交的表单上
9:@HeaderParam
将HTTP标头的值绑定到资源方法参数、资源类字段或资源类Bean属性。说白了就是获取请求的头信息
@HeaderParam value: 获取请求头信息,value填写获取的头名称(键)
10:@CookieParam
将HTTP Cookie的值绑定到资源方法参数、资源类字段或资源类Bean属性。说白了就是获取指定名称Cooke值
@CookieParam value: 获取Cookie信息,value填写获取的指定Cookie名称(键)
11:@DefaultValue
定义使用以下注释之一绑定的请求元数据的默认值:PathParam
, QueryParam
, MatrixParam
,CookieParam
, FormParam
, HeaderParam
@DefaultValue value: 设置指定参数默认值
http://localhost:7777/WebService/testB/st001 接口: @GET @Path("testC/{id}") @Produces({"text/plain;charset=utf-8"}) String testC(@PathParam("id") String id, @DefaultValue("安徽大学") @QueryParam("address") String address); 实现类: @Override public String testC(String id,String address) { System.out.println("打印id:" + id); System.out.println("打印address:" + address); return "成功执行此方法!!"; }
七:Spring整合CXF_WS(SOAP 重要)
1:CXF_WS开发服务端
pom.xml坐标文件编写 实体对象Student、Dog 编写SEI接口和SEI接口实现类(WebService服务类) spring-cxf.xml (CXF配置文件) applicationContext.xml (spring配置文件) web.xml (WEB文件配置)2:CXF_WS开发客户端
开发前根据wsdl说明书来使用wsimport.exe生成具体的客户端代码,这里不懂的请看第二章入门案例
pom.xml坐标文件 spring-cxf.xml (CXF配置文件) applicationContext.xml (spring配置文件) TestClient 测试文件八:Spring整合CXF_RS(RestFul 重要)
Rest是一种风格,而RestFul是一种符合Rest风格的一种架构,RestFul风格的URL是一个资源定位,通过GET、POST、PUT、DELETE来区分查增改删方式,具体的规范请参考其它具体文章
我们在使用CXF_RS时我们是不用像开发WS一样编写完服务端还有根据WSDL说明书生成客户端代码,使用RS方式我们只要编写服务端代码,而客户端代码我们是不用自己编写的,我们客户端调用服务端方法只需要一个URL请求即可完成调用
1:CXF_RS开发服务端
在开发CXF_RS服务端时不理解的可以参考第二章节的入门开发方式,这里只是一个整合
实体类Student、Dog、Result 服务接口及接口实现类 spring-cxf.xml配置类 applicationContext.xml主配置类 log4j.properties日志配置 web.xml配置 pom.xml坐标文件2:CXF_RS开发客户端
其实CXF_RS开发客户端容易,我们其实不需要生成任何的代码来协助客户端的编写,我们只要借助WebClient就可以在任意的框架下使用,使用CXF_RS开发客户端我们得保证我们的实体类与服务端的一样
TestClient代码 pom.xml文件九:SpringBoot整合CXF_WS和CXF_RS
1:SpringBoot整合CXF_WS开发服务端
注:如果是我们创建BUS方法的话,那么注入到方法是必须写方法名如springBus(),如果是直接注入就写属性名称(参考配置类)
实体对象Student、Dog SEI服务接口及SEI服务接口实现类 JaxWsConfig配置类 pom.xml坐标文件我们完成上面几步后,我们启动SpringBoot项目后可以通过访问?WSDL来查看我们发布的服务说明书,这时候我们客户端就可生成客户端代码了
关于客户端使用方式可以去参考我第二章我JAX_WS开发
2:SpringBoot整合CXF_RS开发服务端
Springboot整合CXF_RS开发服务端和整合CXF_WS的目录是一样的
实体类Student、Dog、Result 服务实现类及服务接口 JaxRsConfig配置类 pom.xml要导入的坐标十:WebService拦截器
1:WebService拦截器介绍
在前面的整合和入门案例中,关于CXF_WS/CXF_RS这两个技术中我都添加了系统的拦截器用来拦截日志的请求和响应并输出,其实拦截器就是用来拦截我们的请求和响应,用来拒绝非法访问,如访问前验证token啦,密码验证等等
系统拦截器: LoggingInInterceptor:系统请求入日志打印拦截器 LoggingOutInterceptor:系统响应出日志打印拦截器 自定义拦截器: 我们创建的每一个自定义拦截器都得继承AbstractPhaseInterceptor类 要注意的是,不管是系统的拦截器还是自定义拦截器,我们都要最终添加到端点发布的 如: //服务端入拦截器 List<Interceptor<? extends Message>> inInterceptors = endpoint.getInInterceptors(); inInterceptors.add(new LoggingInInterceptor());//设置请求拦截日志 //服务端出拦截器 List<Interceptor<? extends Message>> outInterceptors = endpoint.getOutInterceptors(); outInterceptors.add(new LoggingOutInterceptor());//设置响应拦截日志
2:SpringBoot整合CXF_WS并设置自定义拦截器(服务端)
本章我们说说SpringBoot整合CXF_WS,并设置了拦截器,请求头设置账号密码都正确才可以访问具体方法,我们复用上面的springboot整合CXF_WS的案例进一步添加功能
第一步我们就要创建一个自定义拦截器(入)加入容器了,用来校验请求来的账号密码是否匹配
第二步我们再创建一个自定义的拦截器(出)加入容器了,用来都操作成功后响应拦截器写回一些标签属性
InJaxWsInterceptopr入拦截器编写,用来验证请求过来的数据 OutJaxWsInterceptor出拦截器,用来对响应回去的数据加工第三步光定义了自定义拦截器还不够,我们要像系统拦截器一样添加到服务发布端点里
修改JaxWsConfig端点发布配置代码Phase类里面定义了特别多静态常量,常用的就是 Phase.PRE_REOTOCOL 代表请求协议和内容过来前拦截
说明:自定义拦截器抛出Fault代表拦截,什么都不抛出,正常把方法执行完代表允许放行
2:SpringBoot整合CXF_WS并设置自定义拦截器(客户端)
客户端代码大家只需要通过wsdl2java工具生成即可,下面直接上重点调用
导入需要用到的pom.xml坐标我们客户端每次发送请求都要携带安全验证账号密码头,所以我直接在客户端中设置出拦截器,用来每次创建指定的头
JaxWsInterceptor出拦截器,来每次设置请求头 调用服务端代码补充:WebService的热部署使用JRebel插件,在IDEA就可以搜索;
作者:蚂蚁小哥 出处:https://www.cnblogs.com/antLaddie/标签:术语,WebService,请求,WS,CXF,原理,服务端,客户端 来源: https://www.cnblogs.com/Leo_wl/p/15324036.html