1、Web service是什么?
通过使用 Web Services,您的应用程序可以向全世界发布信息,或提供某项功能。Web Services 脚本平台需支持 XML + HTTP。
①、基于Web服务,服务器端整出一些资源让客户端应用访问(获取数据)。②、一个跨语言、跨平台的规范(抽象)③、多个跨平台、跨语言应用通信整合的方案(实际)
Web services 有两种类型的应用
可重复使用的应用程序组件
Web services 可以把应用程序组件作为服务来提供,比如汇率转换、天气预报或者甚至是语言翻译等等。
连接现有的软件
通过为不同的应用程序提供一种链接其数据的途径,Web services有助于解决协同工作的问题。通过使用 Web services,您可以在不同的应用程序与平台之间来交换数据。
2、Web services 平台的几个概念。稍后会有相关详解
①、WSDL(Web Services Description Language) :web Service 的定义语言。
1、对应一种类型的文件.wsdl
2、定义了web service的服务器端与客户端应用交互传递请求和相应数据的格式和方式。
3、一个 web service 对应一个唯一的 wsdl文档。
②、SOAP(simple object access protocal):简易对象访问协议
1、一种简单的、基于HTTP和XML的协议,用于在WEB上交换结构化的数据。
2、soap消息:请求消息和响应消息
3、http+xml片段
③、SEI(Webservice EndPointInterface):web service的终端接口
1、Web Service 服务器用来处理请求的接口
④、CXF:Celtix +XFire:一个Apache的用于开发Webservice服务端和客户端的框架。
3、开发Web service
开发方式:①使用jdk开发(版本1.6以上) ②使用CXF框架开发(工作中)
组成:客户端、服务端
- 使用Jdk开发
1、开发服务端:
Webservice 编码 :@WebService(SEI 和SEI的实现类)、@WebMethod(SEI中所有的方法)
发布Webservice: EndPoint(终端,发布webservice)
/*
* SEI
*/
@WebService
public interface HelloWS {
@WebMethod
public String sayHello(String str1);
}
/* * SEI实现 */ @WebService public class HelloWSImpl implements HelloWS { @Override public String sayHello(String str1) { System.out.println("hello"+str1); return "hello"+str1; } }
/* * 发布web service * address:发布地址 http://ip地址:端口号/访问名 * implementor:SEI实现类实例 */ public class ServerTest { public static void main(String[] args){ String address="http://localhost:8989/20171017/hellows"; //Endpoint.publish(address, implementor) Endpoint.publish(address, new HelloWSImpl()); System.out.println("发布成功"); } }
2、开发客户端
①、使用myeclipse自带的 web service浏览器访问
-查看对应的wsdl文档:服务器端发布的address?wsdl(一般浏览器)
-请求 webservice并查看请求和响应消息(webservice浏览器)步骤如下:(服务器启动的状态下)
1、
2、
3、
4、
5、
一次Web Service请求的流程:①、客户端向服务器发送一个soap消息(http消息和xml片段)②、服务器端处理完请求之后向客户端返回一个soap消息。
②、创建客户端应用编码方式访问
借助jdk的wsimport.exe工具生成客户端代码。 方式:wsimport -keep url //url是.wsdl文件的路径。可以是网址路径http://localhost:8989/20171017/hellows?wsdl 也可以是.wsdl保存在本地目录下的路径F:workws_Client1hellows.wsdl。
借助生成的代码编写请求代码
如图所示:
切换到你客户端工程的SRC路径下执行以下命令。(我在环境变量当中添加了wsimport)。运行成功如下,刷新项目工程代码,可以看到。
public class ClientTest { public static void main(String[] args) { /** * <service name="HelloWSImplService"> * <port name="HelloWSImplPort" binding="tns:HelloWSImplPortBinding"> * <soap:address location="http://localhost:8989/20171017/hellows"/> * </port> * </service> */ HelloWSImplService service = new HelloWSImplService(); HelloWSImpl helloWS = service.getHelloWSImplPort(); System.out.println(helloWS.getClass()); System.out.println(helloWS.sayHello("wang")); } }
监听请求:使用MyEclipse的TCP/IP工具(端口转发)
1、将.wsdl文件保存在客户端本地 2、修改文档将端口号8989改为8080 3、根据本地.wsdl文档生成客户端代码 4、配置MyEclipse的TCP/IP,启动监听
点击start。运行客户端代码
- 使用CXF开发Web Service 只需要加入apache-cxf-3.0.13.zip/lib里的jar包即可,其他不需要改动。
4、解析.wsdl文档
WSDL 是一种 XML 文档
WSDL 文档是利用这些主要的元素来描述某个 web service 的:
元素 | 定义 |
---|---|
<portType> | web service 执行的操作 |
<message> | web service 使用的消息 |
<types> | web service 使用的数据类型 |
<binding> | web service 使用的通信协议 |
1 <?xml version="1.0" encoding="UTF-8"?> 2 3 <!-- Published by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.1.6 in JDK 6. --> 4 5 <!-- Generated by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.1.6 in JDK 6. --> 6 7 <definitions name="HelloWSImplService" targetNamespace="http://ws.com/" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://ws.com/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"> 8 9 10 <types> 11 12 13 <xsd:schema> 14 15 <xsd:import schemaLocation="http://localhost:8989/20171017/hellows?xsd=1" namespace="http://ws.com/"/> 16 17 </xsd:schema> 18 19 </types> 20 21 <!-- 请求消息格式<sayHello> --> 22 <message name="sayHello"> 23 24 <part name="parameters" element="tns:sayHello"/> 25 26 </message> 27 28 <!-- 响应消息格式<sayHelloResponse> --> 29 <message name="sayHelloResponse"> 30 31 <part name="parameters" element="tns:sayHelloResponse"/> 32 33 </message> 34 35 <!-- portType 定义服务器端的SEI --> 36 <portType name="HelloWSImpl"> 37 38 <!-- 用来指定SEI中处理请求的方法 --> 39 <operation name="sayHello"> 40 <!-- 指定客户端应用传来的数据 会引用上面请求<message>定义的格式-->
41 <input message="tns:sayHello"/> 42 <!-- 指定福区段应用传出的数据 会引用上面响应<message>定义的格式--> 43 <output message="tns:sayHelloResponse"/> 44 45 </operation> 46 47 </portType> 48 49 <!-- 用于定义SEI实现类 type:使用上面<portType>--> 50 <binding name="HelloWSImplPortBinding" type="tns:HelloWSImpl"> 51 <!-- 绑定数据是一个document(xml)--> 52 <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/> 53 54 <!-- 定义实现的方法 --> 55 <operation name="sayHello"> 56 57 <soap:operation soapAction=""/> 58 59 60 <input> 61 <!-- literal:文本数据--> 62 <soap:body use="literal"/> 63 64 </input> 65 66 67 <output> 68 69 <soap:body use="literal"/> 70 71 </output> 72 73 </operation> 74 75 </binding> 76 77 <!-- 一个Web service容器。name:用于指定客户端容器类 因此客户端会 HelloWSImplService service = new HelloWSImplService();--> 78 <service name="HelloWSImplService"> 79 80 <!-- 用来指定客户端处理请求的入口 :HelloWSImpl helloWS = service.getHelloWSImplPort(); --> 81 <port name="HelloWSImplPort" binding="tns:HelloWSImplPortBinding"> 82 <!-- web service 请求地址--> 83 <soap:address location="http://localhost:8989/20171017/hellows"/> 84 85 </port> 86 87 </service> 88 89 </definitions>
5、CXF拦截器的使用
為了能够动态的操作请求和响应返回数据,cxf设计了拦截器。
拦截器分类:按位置分:服务器拦截器、客户端拦截器
按消息方向分:入拦截器、出拦截器
按定义分:系统拦截器、自定义拦截器
拦截器API:Interceptor(拦截器接口)
AbstractPhaseInterceptor(自定义拦截器继承类)
例子:服务器端系统拦截器:
/* * 发布web service */ public class ServerTest { public static void main(String[] args) { String address = "http://localhost:8888/20171025cxf/hellows"; Endpoint publish = Endpoint.publish(address, new HelloWSImpl()); System.out.println(publish); EndpointImpl endpointImpl=(EndpointImpl) publish; List<Interceptor<? extends Message>> inInterceptors = endpointImpl.getInInterceptors();
系统日志入拦截器: inInterceptors.add(new LoggingInInterceptor()); List<Interceptor<? extends Message>> outInterceptors = endpointImpl.getOutInterceptors();
系统日志出拦截器 outInterceptors.add(new LoggingOutInterceptor()); System.out.println(endpointImpl); System.out.println("发布成功"); } }
客户端发送请求时:服务器端出现如下消息log
2017-10-26 11:38:51 org.apache.cxf.services.HelloWSImplService.HelloWSImplPort.HelloWS
信息: Inbound Message
----------------------------
ID: 1
Address: http://localhost:8888/20171025cxf/hellows?wsdl
Http-Method: GET
Content-Type:
Headers: {Accept=[*/*], Cache-Control=[no-cache], connection=[keep-alive], Content-Type=[null], Host=[localhost:8888], Pragma=[no-cache], User-Agent=[Apache CXF 3.0.13]}
--------------------------------------
2017-10-26 11:38:52 org.apache.cxf.services.HelloWSImplService.HelloWSImplPort.HelloWS
信息: Inbound Message
----------------------------
ID: 2
Address: http://localhost:8888/20171025cxf/hellows
Encoding: UTF-8
Http-Method: POST
Content-Type: text/xml; charset=UTF-8
Headers: {Accept=[*/*], Cache-Control=[no-cache], connection=[keep-alive], Content-Length=[182], content-type=[text/xml; charset=UTF-8], Host=[localhost:8888], Pragma=[no-cache], SOAPAction=[""], User-Agent=[Apache CXF 3.0.13]}
Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:sayHello xmlns:ns2="http://ws1.com/"><arg0>cxf</arg0></ns2:sayHello></soap:Body></soap:Envelope>
--------------------------------------
hellocxf
2017-10-26 11:38:52 org.apache.cxf.services.HelloWSImplService.HelloWSImplPort.HelloWS
信息: Outbound Message
---------------------------
ID: 2
Response-Code: 200
Encoding: UTF-8
Content-Type: text/xml
Headers: {}
Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:sayHelloResponse xmlns:ns2="http://ws1.com/"><return>hellocxf</return></ns2:sayHelloResponse></soap:Body></soap:Envelope>
--------------------------------------
public class Test { public static void main(String[] args) { HelloWSImplService helloWSImplService = new HelloWSImplService(); HelloWS helloWSImplPort = helloWSImplService.getHelloWSImplPort(); //发送请求的客户端对象 Client client = ClientProxy.getClient(helloWSImplPort); //客户端的日志的出拦截器的集合 List<Interceptor<? extends Message>> outInterceptors = client.getOutInterceptors(); outInterceptors.add(new LoggingOutInterceptor()); //客户端的日志的日拦截器的集合 List<Interceptor<? extends Message>> inInterceptors = client.getInInterceptors(); inInterceptors.add(new LoggingInInterceptor()); System.out.print(helloWSImplPort.sayHello("cxf")); } }
客户端配置拦截器后,请求服务,客户端出现如下log
2017-10-26 11:43:09 org.apache.cxf.wsdl.service.factory.ReflectionServiceFactoryBean buildServiceFromWSDL
信息: Creating Service {http://ws1.com/}HelloWSImplService from WSDL: http://localhost:8888/20171025cxf/hellows?wsdl
2017-10-26 11:43:10 org.apache.cxf.services.HelloWSImplService.HelloWSImplPort.HelloWS
信息: Outbound Message
---------------------------
ID: 1
Address: http://localhost:8888/20171025cxf/hellows
Encoding: UTF-8
Http-Method: POST
Content-Type: text/xml
Headers: {Accept=[*/*], SOAPAction=[""]}
Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:sayHello xmlns:ns2="http://ws1.com/"><arg0>cxf</arg0></ns2:sayHello></soap:Body></soap:Envelope>
--------------------------------------
2017-10-26 11:43:10 org.apache.cxf.services.HelloWSImplService.HelloWSImplPort.HelloWS
信息: Inbound Message
----------------------------
ID: 1
Response-Code: 200
Encoding: UTF-8
Content-Type: text/xml;charset=UTF-8
Headers: {Content-Length=[207], content-type=[text/xml;charset=UTF-8], Server=[Jetty(8.1.19.v20160209)]}
Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:sayHelloResponse xmlns:ns2="http://ws1.com/"><return>hellocxf</return></ns2:sayHelloResponse></soap:Body></soap:Envelope>
--------------------------------------
hellocxf
自定义拦截器的使用
参照ApacheCXFWebServiceDevelopment书138-144页
6、SOAP
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:sayHello xmlns:ns2="http://ws1.com/"><arg0>cxf</arg0></ns2:sayHello></soap:Body></soap:Envelope>
一条 SOAP 消息就是一个普通的 XML 文档,包含下列元素:
- 必需的 Envelope 元素,可把此 XML 文档标识为一条 SOAP 消息。
- 可选的 Header 元素,包含头部信息。如果 Header 元素被提供,则它必须是 Envelope 元素的第一个子元素。
- 必需的 Body 元素,包含所有的调用和响应信息
- 可选的 Fault 元素,提供有关在处理此消息所发生错误的信息。如果已提供了 Fault 元素,则它必须是 Body 元素的子元素。在一条 SOAP 消息中,Fault 元素只能出现一次。