利用JAX-WS开发Web服务
Web服务是一种经由HTTP与其他软件进行通信的软件。Java最激动人心的一个特性是用于XML Web服务的Java API(JAX-WS)。JAX-WS是一组Java类和包,他可以创建对Web服务发出请求的客户端,以及接受这些请求的服务。
JAX-WS支持使用简单对象访问协议(SimpleObject Access Protocol,SOAP)和表述性状态转移(Representational State Transfer,REST)实现的Web服务。JAX-WS大大简化了支持这些协议的任务。程序员只需要创建Java对象,并调用方法来使用Web服务即可,其他事宜在幕后进行处理。
1、定义服务端点接口
创建JAX-WS服务的第一步是创建服务端点接口(Service EndpointInterface),这是一个Java接口,它定义了客户端在使用Web服务时能够调用的方法。
在接口定义方法时,跟在方法后面的是分号而不是将语句块括起来的“{}”字符。接口中没有定义方法的行为,而是由实施了该接口的类来处理。
通常情况下,在被称为JAX-WS服务的方法前面添加一个额外的修饰词:@WebMethod用来注解。
注解(annotation)是用来简化java代码的,是一种巧妙的注释(comment)形式,可以被Java解释器、编译器和编程工具所理解。注解可以定义不属于程序部分的程序信息,使得当程序在编译或运行时,这些程序信息能够触发行为。
最常见的注释是@Override,它便是一个方法覆盖了超类的方法,例如:
@Override
public voidpaintComponent(Graphics comp){}
@WebMethod注解表示一个方法可以作为Web服务调用。下面是一个Web服务的代码:
import javax.jws.WebMethod; import javax.jws.*; import javax.jws.soap.*; importjavax.jws.soap.SOAPBinding.*; @WebService @SOAPBinding(style =Style.RPC) public interfaceSquareRootServer { @WebMethod double getSqureRoot(double input); @WebMethod String getTime(); }
2、创建服务实现Bean
实现了服务器端点接口的Java类被称为服务实现Bean(Service ImplementationBean)。在JAX-WS的学习过程中,遇到一些新奇的术语是不可避免的。
下面是SquareRootServerImpl.java的源码:
import java.util.Date; import javax.jws.WebService; @WebService(endpointInterface= "com.java24hours.ws.SqureRootServer") public classSqureRootServerImpl implements SquareRootServer{ @Override public double getSqureRoot(double input) { return Math.sqrt(input); } @Override public String getTime() { Date now = new Date(); return now.toString(); } }
可以看到SquareRootServerImpl类实现了SquareRootServer接口,这表示你要创建的类必须包含接口中的所有方法,而且每个方法都有适当的参数。
类中唯一比较新鲜的地方是后面的注解,它出现在类语句之前:
@WebService(endpointInterface= "com.java24hours.ws.SqureRootServer")
该注解表示,类是名为com.java24hours.ws.SquareRootServer的服务端点接口的服务实现Bean。必须使用完整的类名,其中包括其包的名字。
注意注解后面跟的不是分号,这与语句不同。
创建了以上两个类之后,即可准备启用该服务,以便其他软件来调用。
3、发布Web服务
JAX-WS Web服务可以使用诸如BEA WebLogic、GlassFish、Jboss和Jetty这样的Java应用服务器来部署。如果在支持这些服务器的开发环境中创建了SquareRootServerWeb服务,此时就可以准备启用Web服务。
SquareRootServerPublisher应用程序只需要两个步骤就可以处理该任务:
>载入实现了Web服务的类;
>将该对象发布到Internet。
Javax.xml.ws包中的EndPoint类有一个类方法publish(String , Object),它可以部署Web服务。该方法的一个参数是可以访问Web服务的网络地址,对该项目而言,该网络地址是 http://127.0.0.1:5335/service。该网络地址以主机名SingerFive打头,这被称为本地主机,因为该注记是你创建并运行Java程序的本地计算机。
网络地址的第二部分是本地主机的端口号,Web服务在该端口号等待连接。这里使用的端口号是5335,因为该端口号不太可能被计算机上其他Internet感知程序使用。
地址的最后一部分”/service”是路径。每一个Web服务必须有一个唯一的路径。如果在你的计算机上运行其他Web服务,则他们的路径不能与SquareRootServer相同。
为了部署Web服务,在com.java24hours.ws包中创建一个名为SquareRootServerPublisher的Java空文件,然后输入如下代码:
public static void main(String[] args)
{
SquareRootServerImpl serverImpl = newSquareRootServerImpl();
Endpoint.publish("http://127.0.0.1:5335/service", serverImpl);
}
运行该程序时,它将在计算机上的5335端口等待连接。只要程序支持SOAP或基于REST的Web服务,则无论它是使用Java语言还是其他语言编写的,都可以调用其中的Web服务的方法。只要你的Web服务位于Internet中,任何连接到Internet的软件都可以调用其方法。
4、使用Web服务描述语言文件
在启用该Web服务之前,你可以使用任务的Web浏览器来测试SquareRootServerPublisher应用程序的可用性。
打开浏览器输入网址 http://127.0.0.1:5335/service?wsdl,你将看到浏览器显示程序清单文件如下,该文件由刚才创建的应用程序提供。
<?xml version="1.0" encoding="UTF-8" ?> - <!-- Published by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.2.4-b01. --> - <!-- Generated by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.2.4-b01. --> - <definitions xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://www.w3.org/ns/ws-policy" xmlns:wsp1_2="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://ws.java24hours.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://ws.java24hours.com/" name="SquareRootServerImplService"> <types /> - <message name="getSqureRoot"> <part name="arg0" type="xsd:double" /> </message> - <message name="getSqureRootResponse"> <part name="return" type="xsd:double" /> </message> <message name="getTime" /> - <message name="getTimeResponse"> <part name="return" type="xsd:string" /> </message> - <portType name="SquareRootServer"> - <operation name="getSqureRoot"> <input wsam:Action="http://ws.java24hours.com/SquareRootServer/getSqureRootRequest" message="tns:getSqureRoot" /> <output wsam:Action="http://ws.java24hours.com/SquareRootServer/getSqureRootResponse" message="tns:getSqureRootResponse" /> </operation> - <operation name="getTime"> <input wsam:Action="http://ws.java24hours.com/SquareRootServer/getTimeRequest" message="tns:getTime" /> <output wsam:Action="http://ws.java24hours.com/SquareRootServer/getTimeResponse" message="tns:getTimeResponse" /> </operation> </portType> - <binding name="SquareRootServerImplPortBinding" type="tns:SquareRootServer"> <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="rpc" /> - <operation name="getSqureRoot"> <soap:operation soapAction="" /> - <input> <soap:body use="literal" namespace="http://ws.java24hours.com/" /> </input> - <output> <soap:body use="literal" namespace="http://ws.java24hours.com/" /> </output> </operation> - <operation name="getTime"> <soap:operation soapAction="" /> - <input> <soap:body use="literal" namespace="http://ws.java24hours.com/" /> </input> - <output> <soap:body use="literal" namespace="http://ws.java24hours.com/" /> </output> </operation> </binding> - <service name="SquareRootServerImplService"> - <port name="SquareRootServerImplPort" binding="tns:SquareRootServerImplPortBinding"> <soap:address location="http://127.0.0.1:5335/service" /> </port> </service> </definitions> 关闭提示 关闭 确 认 取 消
该文件是一个使用Web服务描述语言(Web Serveice Description Language , WSDL)编写的服务合约,WSDL是一个XML方言,它可以清楚地说民Web服务的运行方式,一遍服务器和客户端能够充分使用它。
在创建JAX-WS服务和客户端来访问Web服务时,没有必要必须理解WSDL。当然,最好还是看一下该文件的内容,以对基于SOAP和REST的Web服务的运行方式有一个理解。
WSDL之所以被称为服务合约,是因为他规定了访问Web服务的方式、可以与服务交换的信息,以及所传输信息的数据类型。
WSDL合约的第13~22行定义了Web服务的方法、这些方法的参数,以及作为响应返回的数据。查看这些代码行,看是否能够找到getSquareRoot()方法所在的位置。该方法接受一个double型参数,并返回一个double值。
5、创建Web服务客户端
下面我们将创建SquareRootClient应用程序,它可以调用你前面创建的Web服务的方法。当然该服务必须处于运行状态,以便客户端与其连接。
由于像JAX-WS库这样的Web服务技术都支持SOAP、REST、HTTP和XML等标准,因此不一定非要使用Java程序来连接该Web服务。
JAX-WS库在javax.xml.ws包中提供了Service类,这是一个可以创建调用Web服务的对象的工厂(factory)。
类方法Service.create(URL, QName)创建了工厂,其参数URL和Qname分别来自java.net和java.xml.namespace。
URL必须是Web服务的WSDL合约地址:
URL url = new URL(“http://127.0.0.1:5335/service?wsdl”);
Qname是一个限定名称,之二十一个与Web服务提供者关联起来的XML标识符。限定名称包含命名空间URI和本地的标识符。
命名空间URI和URL相似,但是不一定非要作为网络地址来使用。由于我们创建的Web服务的包名称是com.java24hours.ws,在Java中,该名称一般与Internet主机名关联起来,用于该Web服务的命名空间时URI是 http://ws.java24hours.com。
该Web服务的本地标识符是服务实现Bean的名字,而后面添加有Service单词。下面是一个创建限定名称的语句:
QName qname = new Qname( http://ws.java24hours.com/ , “SquareRootServiceImplService”);
使用URL和限定名称则可以创建Web服务客户端工厂:
Service service =Service.create(url , qname);
该工厂有getPort(Class)方法,这个方法创建了指定类的独享。为了对作为方法参数使用的Java类进行识别,可以使用名为class的类变量。例如:
SquareRootServer srs =service.getPort(SquareRootServer.class);
使用SquareRootServer.class作为参数来调用getProt()方法时,将导致工厂创建一个SquareRootServer对象。该对象存储在src变量中。
可以在Java的其他对象中调用SquareRootServer对象的方法:
System.out.println(srs.getTime());
System.out.println(srs.getSqaureRoot(625D));
JAX-WS库将这些方法调用作为SOAP消息打包,然后通过Internet发送到Web服务,然后进行方法调用。
当服务响应这些调用时,它将响应打包为SOAP消息,然后通过Internet发送回去,之后再被转换为Java数据类型。
创建一个名为SquareRootClient的Java文件:
public classSquareRootClient { public static void main(String[] args)throws MalformedURLException { URL url = newURL("http://127.0.0.1:5335/service?wsdl"); QName qName = newQName("http://ws.java24hours.com/","SquareRootServerImplService"); Service service = Service.create(url,qName); SquareRootServer srs =service.getPort(SquareRootServer.class); System.out.println(srs.getTime()); System.out.println(srs.getSqureRoot(625D)); } }
运行该客户端应用程序时,如果SquareRootPublisher应用程序也已经处于运行状态,会看到下图所示输出结果:
6、总结
在Java中,有一类API用作基于XML的RPC(JAX-RPX),JAX-RPC是一种允许Java对象经由Internet向另外一个对象进行远程过程调用(RPC)的技术。而JAX-WS包和类的集合则继承了该API。
以上讲解了使用JAX-WS来创建和使用Web服务的4个步骤:为服务创建一个借口(服务端点接口)、实现该服务(服务实现Bean)、在Internet上发布服务,以及创建客户端访问该服务。