例如:天气预报、淘宝、手机号归属地、火车线路查询、银行转账业务……
Webservice即web服务,是一种跨编程语言和跨操作平台的远程调用技术。
分别是JAX-WS(JAX-RPC)、JAXM&SAAJ、JAXRS。
- JAX-WS(Java API For XML-WebService):
其底层支持为JAXB。JAX-WS(JSR 224)规范的API 位于javax.xml.ws.*包,其中大部分都是注解,提供API 操作Web 服务(通常在客户端使用的较多,由于客户端可以借助SDK 生成,因此这个包中的API 我们较少会直接使用) - JAXM&SAAJ:
JAXM(JAVA API For XML Message)主要定义了包含了发送和接收消息所需的API,相当于Web 服务的服务器端。
SAAJ(SOAP With Attachment API For Java,JSR 67)是与JAXM 搭配使用的API,为构建SOAP 包和解析SOAP 包提供了重要的支持,支持附件传输,它在服务器端、客户端都需要使用。 - JAXM&SAAJ 与JAX-WS的对比:
都是基于SOAP 的Web 服务,相比之下JAXM&SAAJ暴漏了SOAP更多的底层细节,编码比较麻烦,而JAX-WS 更加抽象,隐藏了更多的细节,更加面向对象,实现起来你基本上不需要关心SOAP 的任何细节。那么如果你想控制SOAP 消息的更多细节,可以使用JAXM&SAAJ - JAX-RS:
JAX-RS 是JAVA 针对REST(RepresentationState Transfer)风格制定的一套Web 服务规范。
使用:
需要到JCP 上单独下载JAX-RS 规范的接口,其API 位于javax.ws.rs.*包。这里的JAX-WS 和JAX-RS 规范我们采用Apache CXF 作为实现,CXF 是Objectweb Celtix和Codehaus XFire 合并而成。CXF 的核心是org.apache.cxf.Bus(总线),类似于Spring 的ApplicationContext,Bus 由BusFactory 创建,默认是SpringBusFactory 类,可见默认CXF是依赖于Spring 的,Bus 都有一个ID,默认的BUS 的ID 是cxf。
JAX-WS 版本不一致的问题。对于JAXM&SAAJ 规范我们采用JDK 中自带的默认实现
可适用于应用程序集成、软件重用、跨防火墙通信等需求。不同的业务要求不同。
(1) 跨防火墙通信
(2) 应用系统集成
(3) 软件和数据重用
简单来说,如果一个功能,需要被多个系统使用,即可以使用webservice开发一个服务端接口,供不同的客户端应用。
主要应用在企业内部系统之间的接口调用、面向公网的webservice服务。
- 异构平台的互通性 理论上:Web Service
最大的优势是提供了异构平台的无缝街接技术手段。由于不同的=用户使用不同的硬件平台,不同的操作平台,不同的操作系统,不同的软件,不同的协议通信,这就产生了互相通信的需求。
Web Service 使任何两个应用程序,只要能读写XML,那么就能互相通信 - 软件复用 例如:手机淘宝可以复用已有淘宝的业务逻辑
通过组合已有模块来搭建应用程序,大幅度提高软件的生产效率和质量。用户只要获得了描述Web
Service的WSDL文件,可以直接生成客户端代理,通过代理访问WebService。 - 成本低、可读性强、应用范围广 Web Service 可用基于 XML 的 SOAP 来表示数据和调用请求。 并且通过 HTTP
协议传输XML 格式的数据。 - 迅捷的软件发行方式 每个web Service称为一个生产者.不同的生产者可以相互协同合作完成整个应用
- 重点: 客户端与服务端可能是用不同的语言开发的,但是,通过webservice提供服务接口,客户端与服务端之前可以传递对象。
由于soap是基于xml传输,本身使用xml传输会传输一些无关内容从而影响效率,随着soap协议的完善,soap协议增加了许多内容,这样就导致了使用soap去完成简单的数据传输而携带的信息更多效率再受影响
webService三要素:soap、wsdl、uddi SOAP协议是什么- 全名:简单对象访问协议,是一种轻量的、简单的、基于XML的协议,是被设计成在Web上交换结构化的和固化的信息
- 是基于XML的简易协议,可使应用程序在HTTP之上进行信息交换
一条SOAP消息就是一个普通的XML文档,包含下列元素
构建模块:
- Envelope元素(必有),可把此XML文档表示为一条SOAP消息
- Header元素(可选),包含头部信息
- Body元素(必有),包含所有的调用和响应信息
- Fault元素(可选),提供有关在处理此消息所发生错误的信息
是 SOAP 消息的根元素,可把 XML 文档定义为 SOAP 消息,并且它可把封装定义为 SOAP 封装
Header元素包含头部信息,包含有关 SOAP 消息的应用程序专用信息(比如认证、支付等)。如果 Header 元素被提供,则它必须是 Envelope 元素的第一个子元素。
注释:所有 Header 元素的直接子元素必须是合格的命名空间。
Body元素可包含打算传送到消息最终端点的实际 SOAP 消息。
Fault元素用于存留 SOAP 消息的错误和状态信息。
如果已提供了 Fault 元素,则它必须是 Body 元素的子元素。在一条 SOAP 消息中,Fault 元素只能出现一次。
WSDL 指网络服务描述语言 (Web Services Description Language)。
WSDL 是一种使用 XML 编写的文档。这种文档可描述某个 Web service。它可规定服务的位置,以及此服务提供的操作(或方法)。
- 通过wsdl说明书,可以描述webservice服务端对外发布的服务。
- 是一个基于xml文件,通过xml语言描述整个服务。
- 其中描述了:对外发布的服务名称(类)、接口方法名称(方法)、接口参数(方法参数)、服务返回的数据类型(方法返回值)
| 元素 | 定义 |
|---|---|
| web service 执行的操作 | |
| web service 使用的消息 | |
| web service 使用的数据类型 | |
| web service 使用的通信协议 |
WSDL 文档可包含其它的元素,比如 extension 元素,以及一个 service 元素,此元素可把若干个 web services 的定义组合在一个单一的 WSDL 文档中。
WSDL 端口
它可描述一个 web service、可被执行的操作,以及相关的消息。
可以把 元素比作传统编程语言中的一个函数库(或一个模块、或一个类)。
每个消息均由一个或多个部件组成。可以把这些部件比作传统编程语言中一个函数调用的参数。
使用XML Schema语法来定义数据类型。
UUID
UDDI是统一描述、发现和集成(Universal Description, Discovery, and Integration)的缩写。
UDDI 是一种目录服务,通过它,企业可注册并搜索 Web services。
它是一个基于 XML 的跨平台的描述规范,可以使世界范围内的企业在互联网上发布自己所提供的服务。
- UDDI 指通用的描述、发现以及整合(Universal Description, Discovery and Integration)。
- UDDI 是一种用于存储有关 web services 的信息的目录
- UDDI 是一种由 WSDL 描述的网络服务接口目录。
- UDDI 经由 SOAP 进行通迅。
- UDDI 被构建于 Microsoft .NET 平台之中。
UDDI 使用 W3C 和 IETF* 的因特网标准,比如 XML、HTTP 和 DNS 协议。
UDDI 使用 WSDL 来描述到达 web services 的界面
此外,通过采用 SOAP,还可以实现跨平台的编程特性,大家知道,SOAP 是 XML 的协议通信规范,可在 W3C 的网站找到相关的信息。
*注释:IETF - Internet Engineering Task Force
UDDI 的好处任何规模的行业或企业都能得益于 UDDI。
在 UDDI 之前,还不存在一种 Internet 标准,可以供企业为它们的企业和伙伴提供有关其产品和服务的信息。也不存在一种方法,来集成到彼此的系统和进程中。
UDDI 规范帮助我们解决的问题:
- 使得在成百万当前在线的企业中发现正确的企业成为可能
- 定义一旦首选的企业被发现后如何启动商业
- 扩展新客户并增加对目前客户的访问
- 扩展销售并延伸市场范围
- 满足用户驱动的需要,为在全球 Internet 经济中快速合作的促进来清除障碍
假如行业发布了一个用于航班比率检测和预订的 UDDI 标准,航空公司就可以把它们的服务注册到一个 UDDI 目录中。然后旅行社就能够搜索这个 UDDI 目录以找到航空公司预订界面。当此界面被找到后,旅行社就能够立即与此服务进行通信,这样由于它使用了一套定义良好的预订界面。
ApacheCXF 框架介绍Apache CXF = Celtix + XFire
CXF 继承了 Celtix 和XFire 两大开源项目的精华,提供了对 JAX-WS全面的支持,并且提供了多种 Binding 、DataBinding、Transport 以及各种 Format 的支持,并且可以根据实际项目的需要,采用代码优先(Code First)或者 WSDL 优先(WSDL First)来轻松地实现 Web Services 的发布和使用。
CXF 大大简化了 Services 的创建,同时它继承了 XFire 传统,一样可以天然地和 Spring 进行无缝集成。
CXF 包含了大量的功能特性,但是主要集中在以下几个方面:
- 支持 Web Services 标准:CXF 支持多种 Web Services 标准,包含
SOAP、BasicProfile、WS-Addressing、WS-Policy、WS-ReliableMessaging 和
WS-Security。 - Frontends:CXF 支持多种“Frontend”编程模型,CXF 实现了 JAX-WS API (遵循JAX-WS 2.0TCK 版本),它也包含一个“simple frontend”允许客户端和 EndPoint 的创建,而不需要 Annotation注解。CXF 既支持 WSDL 优先开发,也支持从 Java 的代码优先开发模式。
- 容易使用: CXF 设计得更加直观与容易使用。有大量简单的 API 用来快速地构建代码优先的 Services,各种 Maven
的插件也使集成更加容易,支持 JAX-WS API ,支持Spring 2.0 更加简化的 XML 配置方式,等等。 - 支持二进制和遗留协议:CXF 的设计是一种可插拨的架构,既可以支持 XML ,也可以支持非 XML 的类型绑定,比如:JSON 和CORBA。
- 创建一个maven项目
- 添加CXF依赖
org.apache.cxf cxf‐rt‐frontend‐jaxws 3.0.1 org.apache.cxf cxf‐rt‐transports‐http‐jetty 3.0.1 org.slf4j slf4j‐log4j12 1.7.12 junit junit 4.10 test
-
编写服务接口
-
编写服务接口实现
-
发布服务
-
服务发布成功
-
访问wsdl说明书(从下往上读)
- 创建项目
- 添加依赖(同服务端)
- 编写服务接口
- 远程访问服务端
- 远程访问成功
基于restful风格的webservice,请求使用的是http协议,可以传递xml/json数据
服务端的创建- 创建一个maven项目
- 添加依赖
org.apache.cxf cxf‐rt‐frontend‐jaxrs 3.0.1 org.apache.cxf cxf‐rt‐transports‐http‐jetty 3.0.1 org.slf4j slf4j‐log4j12 1.7.12 北京市昌平区建材城西路金燕龙办公楼一层 电话:400-618-9090 org.apache.cxf cxf‐rt‐rs‐client 3.0.1 org.apache.cxf cxf‐rt‐rs‐extension‐providers 3.0.1 org.codehaus.jettison jettison 1.3.7 junit junit 4.10 test
- 创建服务接口、接口实现、实体类的编写
①编写实体类:
//此处省略get、set
@XmlRootElement(name = "Car")
public class Car {
private Integer id;
private String carName;
private Double price;
}
@XmlRootElement(name = "User")
public class User {
private Integer id;
private String username;
private String city;
private List cars = new ArrayList();
}
②编写服务接口:
@Path("/userService")
@Produces("*/*")
public interface UserService {
// 表示处理的请求类型,post对应的是insert新增操作
@POST
// 访问当前服务接口的方法对应的路径
@Path("/user")
// 服务器支持的请求的数据格式类型
@Consumes({ "application/xml", "application/json" })
public void saveUser(User user);
// 同上,put对应的是update修改操作
@PUT
@Path("/user")
@Consumes({ "application/xml", "application/json" })
public void updateUser(User user);
@GET
@Path("/user")
@Produces({ "application/xml", "application/json" })
public List findAllUsers();
// get对应的是查询操作
@GET
@Path("/user/{id}")
@Consumes("application/xml")
// 服务器支持的返回的数据格式类型
@Produces({ "application/xml", "application/json" })
public User finUserById(@PathParam("id") Integer id);
// 删除操作
@DELETE
@Path("/user/{id}")
@Consumes({"application/xml", "application/json"})
public void deleteUser(@PathParam("id") Integer id);
}
③接口实现:
public class UserServiceImpl implements UserService {
public void saveUser(User user) {
System.out.println("save user:" + user);
}
public void updateUser(User user) {
System.out.println("update user:" + user);
}
public List findAllUsers() {
List users = new ArrayList();
User user1 = new User();
user1.setId(1);
user1.setUsername("小明");
user1.setCity("北京");
List carList1 = new ArrayList();
Car car1 = new Car();
car1.setId(101);
car1.setCarName("保时捷");
car1.setPrice(1000000d);
carList1.add(car1);
Car car2 = new Car();
car2.setId(102);
car2.setCarName("宝马");
car2.setPrice(400000d);
carList1.add(car2);
user1.setCars(carList1);
users.add(user1);
User user2 = new User();
user2.setId(2);
user2.setUsername("小丽");
user2.setCity("上海");
users.add(user2);
return users;
}
public User finUserById(Integer id) {
if (id == 1) {
User user1 = new User();
user1.setId(1);
user1.setUsername("小明");
user1.setCity("北京");
return user1;
}
return null;
}
public void deleteUser(Integer id) {
System.out.println("delete user id :" + id);
}
}
④服务实现:
public class Server {
public static void main(String[] args) {
// 创建发布服务的工厂
JAXRSServerFactoryBean factoryBean = new JAXRSServerFactoryBean();
// 设置服务地址
factoryBean.setAddress("http://localhost:8001/rs");
// 设置服务类
factoryBean.setServiceBean(new UserServiceImpl());
// 添加日志输入输出拦截器
factoryBean.getInInterceptors().add(new LoggingInInterceptor());
factoryBean.getOutInterceptors().add(new LoggingOutInterceptor());
// 创建服务
factoryBean.create();
System.out.println("发布服务成功,端口号8001");
}
}
测试,发布服务:
- 创建项目
- 添加依赖
- 客户端实现:
public class Client {
@Test
public void testOne(){
User user = new User();
user.setCity("LuoYang");
user.setUsername("zhangsan");
user.setId(100);
// 通过WebClient对象远程调用服务端
WebClient.create("http://localhost:8001/rs/userService/user").type(MediaType.APPLICATION_JSON).post(user);
}
@Test
public void testTwo(){
User user = WebClient.create("http://localhost:8001/rs/userService/user/1").accept(MediaType.APPLICATION_JSON).get(User.class);
System.out.println(user);
}
}
- 测试服务:



