`
li-yuan
  • 浏览: 66279 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

Web 服务3(入门教程)

阅读更多

1.6     JAX-WS 开发 Web 服务

JAX-WS 是用于简化使用 Java 构造 Web 服务和 Web 服务客户机的工作的技术。该技术提供了完整的 Web 服务堆栈,可减少开发和部署 Web 服务的任务。 JAX-WS 支持 WS-I 基础总则 1.1 ,后者可确保使用 JAX-WS 堆栈开发的 Web 服务能够供采用 WS-I 基础总则标准使用任意语言开发的任意客户机使用。 JAX-WS 还包括了 JAXB Java Architecture for XML Binding Java XML 绑定框架 ) SAAJ(SOAP with Attachments API for Java SOAP 附件 API)

JAXB 提供了一种非常方便的方法来将 XML 模式映射到 Java 代码的表示形式,从而支持数据绑定功能。 JAXB 消除了将 SOAP 消息中的 XML 模式消息转换为 Java 代码的工作,因而不必全面了解 XML SOAP 解析。 JAXB 规范定义 Java XML 模式之间的绑定。 SAAJ 提供了标准的方法来处理 SOAP 消息中包含的 XML 附件。

而且, JAX-WS 提供了用于将 POJO 类转换为 Web 服务的注释库,从而加速了 Web 服务的开发工作。另外,它还指定了从采用 Web 服务描述语言( Web Services Description Language WSDL )定义的服务到实现该服务的 Java 类之间的详细映射。采用 WSDL 定义的任意复杂类型都通过遵循 JAXB 规范定义的映射来映射为 Java 类。 JAX-WS 之前与 Java EE5 绑定。而 JAX-WS 2.0 规范是作为 JCP JSR 224 开发的。

让我们首先创建一个网上书店订单处理 Web 服务,用于接受订单信息、配送信息和订购书籍并最终生成确认订单号作为响应。订单处理服务的代码如下

package tutorial.service;

 

import javax.jws.WebMethod;

import javax.jws.WebService;

import javax.jws.soap.SOAPBinding;

 

@WebService(serviceName = "OrderProcess",

              portName = "OrderProcessPort",   

              targetNamespace = "http://tutorial/jaxws/orderprocess")

       

@SOAPBinding(style=SOAPBinding.Style.DOCUMENT,use=SOAPBinding.Use.LITERAL,

                     parameterStyle=SOAPBinding.ParameterStyle.WRAPPED)

 

public class OrderProcessService {

 

       @WebMethod

       public OrderBean processOrder(OrderBean orderBean) {

       System.out.println("客户端调用processOrder"

                            + orderBean.getCustomer());

       System.out.println("所定书籍数量"+orderBean.getOrderBooks().length);

          orderBean.setOrderId("2008123111");

          return orderBean;

       }


}

 

这是一个虚拟实现,将在控制台输出客户名和书籍数量,然后输出虚拟订单 2008123111

OrderBean 中包含订单信息,具体来说,其中包含对客户、订单项和配送地址对的内容。 OrderBean 代码如下:

package tutorial.service;

 

public class OrderBean {

 

       private String customer;

 

       private String shippingAddress;

 

       private String[] orderBooks;

 

       private String orderId;

 

       public String getCustomer() {

              return customer;

       }

 

       public void setCustomer(String customer) {

              this.customer = customer;

       }

 

       public String getOrderId() {

              return orderId;

       }

 

       public void setOrderId(String orderId) {

              this.orderId = orderId;

       }

 

       public String getShippingAddress() {

              return shippingAddress;

       }

 

       public void setShippingAddress(String shippingAddress) {

              this.shippingAddress = shippingAddress;

       }

 

       public String[] getOrderBooks() {

              return orderBooks;

       }

 

       public void setOrderBooks(String[] orderItems) {

              this.orderBooks = orderItems;

       }

 

}

 

开发 JAX-WS Web 服务的起点是一个使用 javax.jws.WebService Annotation 进行了注释的 Java 类。所使用的 JAX-WS 注释属于 Java 平台 Web 服务元数据( Web Services Metadata for the Java Platform )规范 (JSR-181) 的一部分。      OrderProcessService 类(带有 @javax.jws.WebService Annotation 的类)隐式地定义了服务端点接口( Service Endpoint Interface SEI ),用于声明客户机可以对服务调用的方法。除了使用 @WebMethod 注释且 exclude 元素设置为 true 的方法外,类中定义的所有公共方法都会映射到 WSDL 操作。 @WebMethod 注释是可选的,用于对 Web 服务操作进行自定义。除了 exclude 元素外, javax.jws.WebMethod 注释还提供 operation name action 元素,用于在 WSDL 文档中自定义操作名属性和 SOAP action 元素。这些属性是可选的;如果未定义,会从类名称派生缺省值。

Web 服务后,需要生成部署服务所需的所有构件,然后将 Web 服务打包为部署构件(通常为 WAR 文件),并将 WAR 文件部署到任何支持 JAX-WS 2.0 规范的兼容服务器上。通常生成的构件是提供基于服务接口将 Java 对象转换为 XML WSDL 文件和 XSD 模式的功能的类。

出于测试目的, Java 6 绑定了一个轻量级 Web 服务器,可以通过调用简单的 API 调用将 Web 服务发布到该服务器上。接下来我们将了解如何使用此方法测试 Web 服务。

发布服务

发布服务首先要生成构件,运行 wsgen 工具,以生成订单处理 Web 服务的 JAX-WS 可移植构件。此工具将读取 Web SEI 类,并生成 Web 服务部署和调用所需的所有构件。 wsgen 工具生成需要发布的 Web 服务的 WSDL 文件和 XSD 模式。

先编译 OrderProcessServie OrderBean ,然后把这个两个类加入到类路径中,然后执行如下命令:

wsgen tutorial.service.OrderProcessService -wsdl
 

wsgen 工具提供了大量的选项,例如,其中提供了 -wsdl 选项,用于生成服务的 WSDL XSD 模式。运行此命令后生成了 OrderProcess.wsdl OrderProcess_schema1.xsd 。为了使用 Java 6 提供的轻量级 Web 服务器,我们在 OrderProcessService main 方法增加如下代码:

public static void main(String[] args) {

       Endpoint.publish("http://localhost:8080/OrderProcessWeb/orderprocess",

                            new OrderProcessService());

}
 

只用运行 OrderProcessService 就将 OrderProcessService 发布成了 Web 服务。通过 Endpoint.publish() 方法,可以方便地发布和测试 JAX-WS Web 服务。 publish() 接受两个参数: Web 服务的位置和 JAX-WS Web 服务实现类。 publish() 方法在指定的 URL (本例中为本地主机,端口为 8080 )创建轻量级 Web 服务器,并将 Web 服务部署到该位置。此轻量级 Web 服务器在 Java 虚拟机( Java Virtual Machine JVM )中运行,可通过调用 endpoint.stop() 方法以有条件的方式终止。

   接下我们将了解如何从 WSDL 创建 Web 服务客户机。 JAX-WS 提供了名为 wsimport 的工具,用于从 WSDL 生成 JAX-WS 可移植构件。生成的可移植构件通常包括以下内容:

  •   服务端接口 (SEI)
  • 服务(需要实现的服务实现类)
  • 从模式类型生成的 JAXB 生成类
  • wsdl:fault 映射的异常类(如果有)

客户端使用生成的构件调用 Web 服务。 Web 服务客户机并不需要处理任何 SOAP 格式(如创建或解析 SOAP 消息)。这将由 JAX-WS 运行时予以处理,此运行时将使用生成的构件代码( JAXB 生成类)。 Web 服务将处理 Java 代码( JAXB 生成类),从而减少了开发 Web 服务客户机和对 Web 服务调用操作的工作。

先使用 wsimport 工具从 OrderProcess WSDL 生成 JAX-WS 构件。然后要创建 Web 服务客户端,后者使用生成的构件代码调用订单处理 Web 服务。要生成 JAX-WS 构件,先运行 OrderProcess ,然后执行下面的命令

wsimport -keep -p tutorial.client 
       http://localhost:8080/OrderProcessWeb/orderprocess?wsdl
 

-keep 选项指示保留生成的文件, -p 选项指定需要在其中生成构件的包名称。 http://localhost:8080/OrderProcessWeb/orderprocess?wsdl 指定 WSDL 文件的位置。以下构件是从 OrderProcessService WSDL 生成的:

  • JAXB 类( OrderBean ):通过读取 OrderProcessService WSDL 中定义的模式定义生成;
  •   RequestWrapper ResponseWrapper 类封装了 SOAP 请求和应答
  • 服务类 (OrderProcess) :客户机用于请求 Web 服务的类
  •   服务接口 (OrderProcessService) :包含着用于服务实现接口的类

接下来了解一下如何使用上面生成的构件创建 Web 服务客户端。客户端的代码如下:

package tutorial;

 

import java.net.MalformedURLException;

import java.net.URL;

import javax.xml.namespace.QName;

import tutorial.client.*;

 

public class OrderClient {

       final QName qName = new QName(

                     "http://tutorial/jaxws/orderprocess", "OrderProcess");

       public static void main(String[] args) {

              if (args.length != 1) {

                     System.out

                                   .println("请指定订单处理Web服务的URL");

                     System.exit(-1);

              }

              URL url = getWSDLURL(args[0]);

              OrderClient client = new OrderClient();

              client.processOrder(url);

       }

       private static URL getWSDLURL(String urlStr) {

              URL url = null;

              try {

                     url = new URL(urlStr);

              } catch (MalformedURLException e) {

                     e.printStackTrace();

                     throw new RuntimeException(e);

              }

              return url;

       }

       public void processOrder(URL url) {

 

              OrderProcess orderProcessingService = new OrderProcess(url, qName);

              OrderBean order = populateOrder();

              OrderProcessService port = orderProcessingService.getOrderProcessPort();

              OrderBean orderResponse = port.processOrder(order);

              System.out.println("订货单号为:" + orderResponse.getOrderId());

       }

       private OrderBean populateOrder() {

              OrderBean order = new OrderBean();

              order.setCustomer("张三");

              order.getOrderBooks().add("世界是平的");

              return order;

       }

}
 

上面列出的 Web 服务客户机代码执行以下任务:

  • 通过传入 OrderProcess Web 服务的 WSDL URL 和服务的 QName 创建 OrderProcess 类的实例。
  •   创建 OrderBean 的实例,并使用 populateOrder() 方法填充订单信息。
  • 对服务调用 getOrderProcessPort() ,以检索到服务的代理(也称为端口)。端口实现服务所定义的接口。
  •   调用端口的 processOrder 方法,并同时传入在上面的第二个列表项目中创建的 OrderBean 实例。
  • 从服务获得 OrderBean 响应并输出订单 ID

如上面的客户机代码中所示,并不会处理调用 Web 服务操作时使用的任何基于 SOAP XML 的格式;相反,需要处理的是输入和输出消息的 JAXB 生成类,并使用服务接口和服务类对象。存根负责从 JAXB 注释创建 SOAP 请求,并将 SOAP 响应转换回 Java 对象。

在本节中,我们了解了如何使用 JAX-WS 技术设计和开发 Web 服务。 JAX-WS 是一个非常不错的选择,因为其中提供了完整的 Web 服务堆栈,以简化 Web 服务的开发和部署。

本节中开发的订单处理 Web 服务使用文档样式的 Web 服务,可确保服务使用者和服务提供者使用 XML 文档进行通信。 XML 文档遵循定义良好的契约,而此类契约通常都是使用 XML 模式定义创建的。 XML 模式格式指定服务使用者能够调用和遵循的业务消息的契约。文档样式的 Web 服务应该是开发企业 Web 服务的首选方法。

 

分享到:
评论
3 楼 SINCE1978 2010-03-25  
什么不全?,你的SEI实现类和客户端代码是需要你自己编写的。这是根据ibm中文网上的教程简化改编的例子,都是全的。也能跑起来,谢谢博主。
只是奇怪为啥wsdl url没写后面的“?wsdl”虽然跑了个异常出来但是后面的都正常运行了。
2 楼 love1907 2010-03-23  
江西不全,有些类,莫名其妙的就贴出了使用,但是确没有定义
1 楼 SINCE1978 2010-03-23  
第一次运行OrderClient时输入wsdl url后面的“?wsd”l忘写了,写成了:
http://localhost:8080/OrderProcessWeb/orderprocess
应该是:
http://localhost:8080/OrderProcessWeb/orderprocess?wsdl

但是有点奇怪:
第一次wsdl url写错了还能调用webservice,服务端控制台也输出了,只是先输出了一个异常:
严重: Request doesnt have a Content-Type
com.sun.xml.internal.ws.server.UnsupportedMediaException
...
客户端调用processOrder张三
所定书籍数量1


客户端输出:
订货单号为:2008123111

相关推荐

Global site tag (gtag.js) - Google Analytics