实战:基于JAX-WS实现Web服务
本节演示如何基于JAX-WS规范来实现Web服务。
JAX-WS概述
在JAX-WS中,Web服务操作调用由基于XML的协议(如SOAP)表示。SOAP规范定义了信封结构、编码规则和表示Web服务调用和响应的约定。这些调用和响应以SOAP消息(XML文件)的形式在HTTP上传输。
虽然SOAP消息很复杂,但是JAX-WS API对应用程序开发人员隐藏了这种复杂性。在服务器端,开发人员通过使用Java编写的接口定义方法来指定Web服务操作。开发人员还对实现这些方法的一个或多个类进行编码。客户端程序也很容易编写,创建一个代理(表示服务的本地对象),然后简单地调用代理上的方法。使用JAX-WS,开发人员不会生成或解析SOAP消息。它是JAX-WS运行时系统,负责将API调用和响应与SOAP消息进行相互转换。
使用JAX-WS时,客户端和Web服务有一个很大的优势:Java的平台无关性。此外,JAX-WS没有限制:JAX-WS客户端可以访问不在Java平台上运行的Web服务,反之亦然。这种灵活性是可能的,因为JAX-WS使用W3C定义的技术:HTTP、SOAP和WSDL。WSDL指定XML格式,用于将服务描述为对消息进行操作的一组端点。
图6-7演示了JAX-WS技术如何管理Web服务和客户端之间的通信。
图6-7 JAX-WS管理Web服务和客户端之间的通信
开发JAX-WS Web服务的起点是一个用javax.jws.WebService注释的Java类。@WebService注释将类定义为Web服务端点。
服务终结点接口或服务终结点实现(SEI)分别是Java接口或类,它声明客户端可以在服务器上调用的方法。构建JAX-WS端点时,不需要接口。Web服务实现类隐式地定义了一个SEI。
可以通过在实现类中的@WebService注释中添加endpointInterface元素来指定显式接口。然后,你必须提供一个接口,该接口定义端点实现类中可用的公共方法。
创建Web服务器和客户端的基本步骤
创建Web服务器和客户端的基本步骤如下。
·编码实现类。
·编译实现类。
·将文件打包成WAR文件。
·部署WAR文件。
·编码客户端类。
·使用wsimportMaven目标来生成和编译连接到服务器所需的Web服务构件。
·编译客户端类。
·运行客户端。
以下各小节将更详细地描述这些步骤。
JAX-WS终端要求
JAX-WS端点必须遵循这些要求。·实现类必须用javax.jws.WebService或
javax.jws.WebServiceProvider注释。
·实现类可以通过@WebService注解的endpointInterface元素显式引用SEI,但不需要这样做。如果@WebService中未指定endpointInterface,则隐式地为实现类定义SEI。
·实现类的业务方法必须是公共的,并且不能声明为static或final。
·暴露给Web服务客户端的业务方法必须用javax.jws.WebMethod进行注释。
·暴露给Web服务客户端的业务方法必须具有与JAXB兼容的参数和返回类型。请参阅JAX-WS支持的类型中的JAXB默认数据类型绑定列表。
·实现类不能声明为final,也不能是抽象的。
·实现类必须具有默认公共构造方法。
·实现类不能定义finalize方法。
·实现类可以使用
javax.annotation.PostConstruct或
javax.annotation.PreDestroy对其方法的注解,以进行生命周期事件回调。
·@PostConstruct方法在实现类开始响应Web服务客户端之前由Web容器调用。
·在将终结点从操作中移除之前,Web容器会调用@PreDestroy方法。
创建基于JAX-WS的服务器
创建Endpoint接口,代码如下。
package com.waylau.java.ws;
import javax.jws.WebService;
@WebServicepublic interface HelloService {
String getHelloworld();
}
需要注意的是,接口需要加@WebService注解。
创建Endpoint实现,代码如下。
package com.waylau.java.ws;
import javax.jws.WebMethod;
import javax.jws.WebService;
@WebService(endpointInterface = "com.waylau.java.ws.HelloService")
public class HelloServiceImpl implements HelloService {
@WebMethod
public String getHelloworld() {
return "Hello world!";
}
}
上述代码,@WebService注解中的endpointInterface需要指定接口的位置。
创建Endpoint发布器,代码如下。
package com.waylau.java.ws;
import javax.xml.ws.Endpoint;
public class HelloPublisher {
public static void main(String[] args) {
Endpoint.publish("http://localhost:9999/ws/hello",
new HelloServiceImpl());
}
}
Endpoint.publish方法用于方便发布一个Web服务器,而无须部署到Web容器中。
创建基于JAX-WS的客户端
客户端代码如下。
package com.waylau.java.ws;
import java.net.URL;
import javax.xml.namespace.QName;import javax.xml.ws.Service;
public class HelloClient {
public static void main(String[] args) throws Exception {
URL url = new URL("http://localhost:9999/ws/hello?wsdl");
QName qname = new QName("http://ws.java.waylau.com/",
"HelloServiceImplService");
Service service = Service.create(url, qname);
HelloService hello = service.getPort(HelloService.class);
System.out.println(hello.getHelloworld());
}
}
Service承担Web服务客户端的职责,可以快速访问Web服务。
运行
运行服务器,可以在
http://localhost:9999/ws/hello?wsdl地址下看到图6-8所示的描述文档。
图6-8 描述文档
运行客户端可以看到图6-9所示的输出。
图6-9 客户端输出
本节示例,可以在java-ws项目下找到。
本章小结
本章介绍了什么是面向服务的架构,以及实现面向服务的架构技术,包括XML-RPC、SOAP、Microsoft.NET Remoting、Java等。其中,Web服务又可以分为“大”Web服务、RESTful Web服务。
在本章也演示了如何通过Java技术来实现Web服务。