web Service
--不是框架,更不是一种技术
而是一种跨平台、夸语言的规范
为了解决这一的需求场景
不同平台,不同语言所编写的应用之间如何互相调用?
通俗点,加入Java里有如下方法
public List<Cat> getCatsByUser(User user)
有一个C语言写的程序,它想去调用上面的getCatsByUser方法
Web Service集中解决
1.远程调用
2.跨平台调用
3.跨语言调用
Web Service在实际中的用途
1、同一个公司的新、旧系统的整合
Linux上的Java应用,去调用window
2、不同公司的业务整合
业务的整合就要求带来,不同公司的系统整合
不同公司的系统可能存在平台不同,语言不同的问题
3、内容聚合
一个应用需要提供,天气预报,股票行情,黄金行情,编程语言行情.....
这个内容聚合的应用,需要调用大量不同平台、不同语言编写的应用的方法。
CFX
Axis(Apache) --> Axis2(Apache)
XFire --> XFire + Celtrix = CXF(两个框架)
XFire (Web Service框架)
Celtrix (ESB框架)
SOA(面向服务的架构)
Service1 Service2 Service3 –所有组件都是“即插即用”
IBM提倡的SOA架构,希望以“组装电脑”的方式开发软件
1、各种提供服务的组件(Web Service)
2、企业服务总线(Enterprise Services Bus , ESB)
CXF号称是SOA框架
CFX(Apache)
CXF内置了一个Jetty Web服务器
/************************************
每个Web Service组件需要两个部分,接口和实现类
************************************/
使用CXF开发Web Service服务器端
1、开发一个Web Service业务接口
该接口要用@WebService修饰
2、开发一个Web Service实现类
实现类也需要@WebService修饰修饰
3、使用Endpoit类的静态方法发布Web Service
使用CXF开发Web Service客户端
1、调用CXF提供wsdl2java工具,根据WSDL文档生成相应的Java代码。
WSDL - Web Service Definition Language
任何语言实现了Web Service,都需要提供、并暴露wsdl文档
2、找到wsdl2java所生成的类,一个继承Service的类。
该类的实例可当成工厂来使用
3、调用Service子类的实例的getXxxPort方法,放回远程Web Service 代理
形参,返回值
1、当形参、返回值的类型是String、基本数据类型的是,CXF肯定可以轻松处理
2、当形参、返回值的类型是JavaBean复合类,List集合和数组时
CXF也可以很好的处理
3、还有一些像Map、非JavaBean式的复合类,CXF是处理不了的
/************************************************************
XML里两个属性: **
targetNamespace - 相当于Java语言里的package语句 **
xmlns - 相当于java语言的import **
xmlns:tx=”http://www.springframework.org/schema/tx” tx相当于别名 **
= **
其中maxOccurs是指最大出现几次 unbounded是无限大 **
其中minOccurs是指最小出现几次 **
其中type是内容 tns:cat 对应出类型 **
************************************************************/
Web Service的三个技术基础
1、WSDL Web Service Definition Language - Web Service定义语言
2、SOAP SimpleObject Access Protocol 简单对象访问协议
3、UDDI
一次Web Service的调用 -- 其实并不是方法调用,而是发送SOAP消息(即XML文档片段)
对于SayHi操作来说,
传入的消息
<sayHi>
<arg0>字符串</arg0>
</sayHi>
传出的消息
<sayHiResponse>
<return>字符串</return>
</sayHiResponse>
对于getCatsByUser操作来说,
传入的消息
<getCatsByUser>
<arg0>
<address>字符串</address>
<id>整数值</id>
<name>字符串</name>
<pass>字符串</pass>
</arg0>
</getCatsByUs
er>
传出的消息
<getCatsByUserResponse>
<return> -- 可出现0~N此
<color>字符串</color>
<id>整数值</id>
<name>字符串</name>
<return>
</getCatsByUserResponse>
对于getAllCats来说
传入消息
传出的消息
</getAllCatsResponse>
通俗来说,WSDL文档描述了Web Service如下3个方面
1、 WHAT:该Web Service包含了”什么”操作。
2、 HOW: 该Web Service操作一个”怎么”调用。
3、 WHERE:该Web Service的服务地址。
/************************
只要得到webService的WSDL文档 **
接下来程序就可以调用Web Service **
************************/
调用一次Web Service的本质
1、客户端把调用方法的参数,转换为XML文档片段(SOAP消息,input消息)
--该片段必须符合WSDL定义的格式
2、通过网络、吧XML文档片段传送给服务器
3、服务器接受到XML文档片段
4、服务器解析XML文档片段,提取其中的数据,并把数据转换调用Web Service所需要的参数
5、服务器端执行方法
6、吧执行方法得到的返回值再次转发生成XML文档片段(SOAP消息,output消息)
7、通过网络、吧XML文档片段传送给客户端
8、客户端接受到XML文档片段
9、把数据转换调用Web Service的返回值
冲上面调用的本质来看,要一个语言支持Web Service
唯一的要求是,改语言支持XML文档解析、生成、支持网络传输
collection类
在CXF开发中,需要系统无法自动处理的类型就需要
/*******************
注意:CXF3.0以上支持了Map格式*
*******************/
处理思路是提供一个转换器,改转换器负责吧CXF搞不懂的类型转化为搞的定的内心
1、使用@XmlJavaTypeAdapter修饰CXF无法处理的类型
使用Annotation时,通过value属性指定一个转换器
2、实现自己的转换器
实现转换器时,需要开发一个CXF搞的定的类型
/**********************************************TWO***************************************/
Web Service调用的本质
1、客户端吧调用的参数转换为XML文档片段(SOAP消息,input消息)
2、客户端通过网络把XML文档片段传给远程服务器
3、服务器接受XML文档片段
4、服务器解析XML文档片段,提取其中的数据,并把数据转换为调用所需的参数
5、服务器执行方法
6、得到方法的返回值,服务器吧方法的返回值转换为XML片段(SOAP消息,output消息)
7、远程服务器通过网络吧XML文档片段传给客户端
8、客户端接受XML文档片段
9、客户端解析XML文档片段,提取其中的数据,并把数据转换为返回值
Web Service的三个技术基础
- WSDL
WebService接口
1、Type(标准的Schema)
2、2N个message元素
3、portType,有N个operation子元素
Web Service实现类
1、binding元素 - N个更详细的operation
2、、Service - 知道Web Service的服务器地址
- SOAP
Header
Header是可选的,有程序猿控制
Body
Body元素是默认的,Body元素里可以有两种情况
- 当Web Service交互正确的时候,Body元素的内容由WSDL控制
- 当Web Service交互出错时,Body元素的内容将是Fault子元素
Web Service急需解决的问题,如何进行权限控制
解决思路是,服务器端要求input消息总是携带有用户名,密码信息
如果没有用户名和密码信息就拒绝调用
如果不用CXF等框架,SOAP消息的生成、解析都是由程序员来负责的,
无论是添加用户名、密码信息,还是提取用户名、密码信息都可以由程序员控制
如果CXF等框架,SOAP消息的生成,解析都是CXF等框架完成的
拦截器
为了让程序员访问,并修改CXF框架所生成的SOAP消息,CXF提供了拦截器。
服务器端添加拦截器
1、获取Endpoint的publish方法的返回值
2、调用该方法返回值的getInterceptor以及getOutInterceptor方法
来获取In,Out拦截器,接下来就可以添加到拦截器了。
客户端添加拦截器
1、调用ClientProxy的getClient方法,调用该方法
2、调用Client对象的getInInterceptors方法,getOutInterceptors方法来
获取In,Out拦截器列表,接下来就可以添加拦截器了
对于SayHi操作来说,
<?xml version="1.0" ?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:sayHi xmlns:ns2="http://ws.cxf.fkjava.org/">
<arg0>孙悟空</arg0>
</ns2:sayHi>
</S:Body>
</S:Envelope>
传出消息
自定义拦截器
需要实现Interceptor接口,实现上我们会继承