JAVA 的
的的
的 WebService 支持
支持支持
支持
李海峰
李海峰李海峰
李海峰(
((
(QQ:61673110)
))
)-Andrew830314@163.com
SOA(Service-Oriented Architecture)面向服务架构是一种思想,它将应用程序的不同功能单元
通过中立的契约(独立于硬件平台、操作系统和编程语言)联系起来,使得各种形式的功能
单元更好的集成。目前来说,WebService 是 SOA 的一种较好的实现方式,WebService 采用
HTTP 作为传输协议,SOAP(Simple Object Access Protocol)作为传输消息的格式。但
WebService 并不是完全符合 SOA 的概念,因为 SOAP 协议是 WebService 的特有协议,并
未符合 SOA 的传输协议透明化的要求。SOAP 是一种应用协议,早期应用于 RPC 的实现,
传输协议可以依赖于 HTTP、SMTP 等。
SOA 的产生共经历了如下过程:
通常采用 SOA 的系统叫做服务总线(BUS),结构如下图所示:
------------------------------------------------------------------------------------
JAVA 中的
中的中的
中的 Web 服务规范
服务规范服务规范
服务规范:
::
:
JAVA 中共有三种 WebService 规范,分别是 JAXM&SAAJ、JAX-WS(JAX-RPC)、JAX-RS。
下面来分别简要的介绍一下这三个规范。
(1.)JAX-WS:
::
:
JAX-WS(Java API For XML-WebService),JDK1.6 自带的版本为 JAX-WS2.1,其底层支
持为 JAXB。早期的基于 SOAP 的 JAVA 的 Web 服务规范 JAX-RPC(Java API For
XML-Remote Procedure Call)目前已经被 JAX-WS 规范取代,JAX-WS 是 JAX-RPC 的演进
版本,但 JAX-WS 并不完全向后兼容 JAX-RPC,二者最大的区别就是 RPC/encoded 样式的
WSDL,JAX-WS 已经不提供这种支持。JAX-RPC 的 API 从 JAVA EE5 开始已经移除,如
果你使用 J2EE1.4,其 API 位于 javax.xml.rpc.*包。
JAX-WS(JSR 224)规范的 API 位于 javax.xml.ws.*包,其中大部分都是注解,提供 API 操
作 Web 服务(通常在客户端使用的较多,由于客户端可以借助 SDK 生成,因此这个包中的
API 我们较少会直接使用)。
WS-MetaData(JSR 181)是 JAX-WS 的依赖规范,其 API 位于 javax.jws.*包,使用注解配
置公开的 Web 服务的相关信息和配置 SOAP 消息的相关信息。
(2.)JAXM&SAAJ:
::
:
JAXM(JAVA API For XML Message)主要定义了包含了发送和接收消息所需的 API,相当
于 Web 服务的服务器端,其 API 位于 javax.messaging.*包,它是 JAVA EE 的可选包,因此
你需要单独下载。
SAAJ(SOAP With Attachment API For Java,JSR 67)是与 JAXM 搭配使用的 API,为构建
SOAP 包和解析 SOAP 包提供了重要的支持,支持附件传输,它在服务器端、客户端都需要
使用。这里还要提到的是 SAAJ 规范,其 API 位于 javax.xml.soap.*包。
JAXM&SAAJ 与 JAX-WS都是基于 SOAP的 Web 服务,相比之下 JAXM&SAAJ 暴漏了 SOAP
更多的底层细节,编码比较麻烦,而 JAX-WS 更加抽象,隐藏了更多的细节,更加面向对
象,实现起来你基本上不需要关心 SOAP 的任何细节。那么如果你想控制 SOAP 消息的更
多细节,可以使用 JAXM&SAAJ,目前版本为 1.3。
(3.)JAX-RS:
::
:
JAX-RS 是 JAVA 针对 REST(Representation State Transfer)风格制定的一套 Web 服务规范,
由于推出的较晚,该规范(JSR 311,目前 JAX-RS 的版本为 1.0)并未随 JDK1.6 一起发行,
你需要到 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。你要注意的是 Apache CXF
2.2 的发行包中的 jar 你如果直接全部放到 lib 目录,那么你必须使用 JDK1.6,否则会报
JAX-WS 版本不一致的问题。对于 JAXM&SAAJ 规范我们采用 JDK 中自带的默认实现。
------------------------------------------------------------------------------------
1.JAVA
的
的的
的
WebService
规范
规范规范
规范
JAX-WS
:
::
:
Web 服务从前面的图中不难看出自然分为 Server、Client 两部分,Server 公开 Web 服务,
Client 调用 Web 服务,JAX-WS 的服务端、客户端双方传输数据使用的 SOAP 消息格式封
装数据,在后面我们会看到其实 SOAP 信封内包装的就是一段 XML 代码。
I.服务端示例
服务端示例服务端示例
服务端示例:
::
:
我们先看一个服务器端示例:
(1.)公开 Web 服务的接口 IHelloService:
package net.ilkj.soap.server;
import javax.jws.WebService;
@WebService
public interface IHelloService {
Customer selectMaxAgeStudent(Customer c1, Customer c2);
Customer selectMaxLongNameStudent(Customer c1, Customer c2);
}
我们看到这个接口很简单,仅仅是使用类级别注解@WebService 就标注了这个接口的方法
将公开为 Web 服务,使用了这个注解的接口的所有方法都将公开为 Web 服务的操作,如果
你想屏蔽某个方法,可以使用方法注解@Method 的 exclude=true。我们也通常把公开为 Web
服务的接口叫做 SEI(Service EndPoint Interface)服务端点接口。
(2.)实现类 HelloServiceImpl:
package net.ilkj.soap.server;
public class HelloServiceImpl implements IHelloService {
@Override
public Customer selectMaxAgeStudent(Customer c1, Customer c2) {
if (c1.getBirthday().getTime() > c2.getBirthday().getTime())
return c2;
else
return c1;
}
@Override
public Customer selectMaxLongNameStudent(Customer c1, Customer c2)
{
if (c1.getName().length() > c2.getName().length())
return c1;
else
return c2;
}
}
这个实现类没有任何特殊之处,但是如果你的实现类还实现了其他的接口,那么你需要在实
现类上使用@WebService 注解的 endpointInterface 属性指定那个接口是 SEI(全类名)。
(3.)Customer 类:
package net.ilkj.soap.server;
import java.util.Date;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "Customer")
public class Customer {
private long id;
private String name;
private Date birthday;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
}
这个类是公开为 Web 服务的接口中的参数类型和返回值,因此你需要使用 JAXB 注解告诉
CXF如何在 XML 和 Java Object 之间处理,因为前面说过 SOAP 消息格式包装的是一段 XML
代码,那么无论是服务器端还是客户端在接收到 SOAP 消息时都需要将 XML 转化为 Java
Object,在发送 SOAP 消息时需要将 Java Object 转化为 XML。
(4.)发布 Web 服务:
package net.ilkj.soap.server;
import javax.xml.ws.Endpoint;
public class SoapServer {
public static void main(String[] args) {
Endpoint.publish("http://127.0.0.1:8080/helloService",
new HelloServiceImpl());
}
}
注意我们发布 Web 服务使用的是 javax.xml.ws.*包中的 EndPoint 的静态方法 publish()。
(5.)查看 WSDL:
我们访问 http://127.0.0.1:8080/helloService?wsdl 地址,您会看到很长的 XML 文件(由于浏
览器的问题,如果你看到的是空白页面,请查看源代码),这就是 WSDL(WebService Definition
Language),对于你要访问的 Web 服务,只要在其地址后加上,就可以在浏览器中查看用于
描述 Web 服务的 WSDL,这也是一种 XML,Web 服务能够被各种编程语言书写的程序访
问就是通过 WSDL 这种通用的契约来完成的。
如果你已经看到 WSDL,那么表示我们的 Web 服务发布成功了。你可能会差异,我们没有
借助 Tomcat 这样的 Web 服务器,直接运行一个 main 方法是怎么发布的 Web 服务呢?其实
CXF 内置了 Jetty(Servlet 容器),因此你不需要将你的程序部署到 Tomcat 等 Web 服务器
也可以正常发布 Web 服务。
------------------------------------------------------------------------------------
II.分析
分析分析
分析 WSDL 的构成
的构成的构成
的构成:
::
:
下面我们来解释一下你所看到的 WSDL 的结构,你可以对照你所生成 WSDL(文件太长,
Word 里实在放不下)。
(1.)<wsdl:definitions …
这个是 WSDL 的根元素,我们要关心的是三个属性,name 属性值为公开的 Web 服务的接
口的实现类+Service(上例中为
name="HelloServiceImplService"
,不同的 JAX-WS
实现名字是不一样的 );targetNamespace 指定目标名称空间,targetNamespace 的值被后面
的 xmlns:tns 属 性 作 为 值 , 默 认 是 使 用 接 口 实 现 类 的 包 名 的 反 缀
(
targetNamespace="http://server.soap.ilkj.net/" …
xmlns:tns="http://server.soap.ilkj.net/"
),
你可以使用@WebService 注解的 targetNamespace 属性指定你想要的名称空间。
(2.)<wsdl:types …
这个元素会通过<xs:element … 声明几个复杂数据类型的元素。
一般首先你看到的是 Web 服务中的方法参数、返回值所涉及的所有复杂(complex)类型的
元素定义<xs:element …,其中 name 属性值是这个复杂类型的 JAXB 注解的 name 属性值,
type 属性是 tns:+JAXB 注解的 name 属性值的全小写形式(上例中的方法参数、返回值只涉
及一个复杂类型 Customer,Customer 的@XmlRootElement 注解的 name 属性值为 Customer,
因此你会看到
<xs:element name="Customer" type="tns:customer" />)。
再向下你会看到 XXX 元素和 XXXResponse 元素,其中 XXX 是方法名称(你可以使用
@WebMethod 的 operationName 属性值指定 XXX 的值),XXX 是对方法参数的封装,
XXXResponse 是对返回值的封装,上例中你会看到
- 1
- 2
- 3
- 4
- 5
- 6
前往页