设计与开发 JAX-WS 2.0 Web 服务(1)

源自IBM

通过使用 Java™ API for XML Web Services (JAX-WS) 技术设计和开发 Web 服务,可以带来很多好处,能简化 Web 服务的开发和部署,并能加速 Web 服务的开发。通过此教程,可以了解如何开发将其功能作为 Web 服务公开的示例订单处理程序,从而进行所有这些工作以及其他任务。完成了此教程后,您将能够应用这些概念和新获得的知识,来使用 JAX-WS 技术为应用程序开发 Web 服务。

在本教程中,我们将设计和开发一个订单处理应用程序,并将其功能作为 Web 服务公开,以便各种使用者以独立于平台的方式提交订单信息。

要运行此教程中的示例,需要安装 Java Platform, Standard Edition (Java SE) 6.0
1JAX-WS 简介

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

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

而且,JAX-WS 提供了用于将传统 Java 对象(Plain Old Java ObjectPOJO)类转换为 Web 服务的 Annotation 库,从而加速了 Web 服务的开发工作。另外,它还指定了从采用 Web 服务描述语言(Web Services Description LanguageWSDL)定义的服务到实现该服务的 Java 类之间的详细映射。采用 WSDL 定义的任意复杂类型都通过遵循 JAXB 规范定义的映射来映射为 Java 类。JAX-WS 之前与 Java Platform, Enterprise Edition (Java EE) 5 绑定。而 JAX-WS 2.0 规范是作为 Java Community Process (JCP) 的 JSR 224 开发的。

2开发 Web 服务

契约优先方法与代码优先方法

进入 JAX-WS 时代的最好方法莫过于首先开发一个 Web 服务。可以采用以下两种方法之一开发 Web 服务:

· 契约优先:从 WSDL 契约着手,生成 Java 类来实现服务。

· 代码优先:从 Java 类着手,使用 Annotation 来生成 WSDL 文件和 Java 接口。

契约优先 WSDL 方法需要对用于定义消息格式的 WSDL 和 XML 模式定义(XML Schema DefinitionXSD)有良好的理解。如果您对 Web 服务相当陌生,最好从代码优先方法着手,本教程中将使用此方法开发 Web 服务。

代码优先 Web 服务开发

使用代码优先方法时,将从实现希望作为服务公开的功能的 Java 类或类入手。在已经提供了 Java 实现且需要将实现作为服务公开的情况下,代码优先方法尤为有用。

3开发订单处理 Web 服务

让我们首先创建一个订单处理 Web 服务,用于接受订单信息、配送信息和订购物品并最终生成确认 ID 作为响应。订单处理服务的代码如清单 中所示。这是一个虚拟实现,将在控制台输出客户 ID 和物品数量,然后输出虚拟订单 ID A1234

清单 1. 订单处理 Web 服务实现

package com.ibm.jaxws.tutorial.service;

import javax.jws.WebMethod;

import javax.jws.WebService;

import javax.jws.soap.SOAPBinding;

import com.ibm.jaxws.tutorial.service.bean.OrderBean;

//JWS annotation that specifies that the portType name of the 

//Web service is "OrderProcessPort," the service name 

//is "OrderProcess," and the targetNamespace used in the generated

//WSDL is "http://jawxs.ibm.tutorial/jaxws/orderprocess."

@WebService(serviceName = "OrderProcess",

        portName = "OrderProcessPort",  

        targetNamespace = "http://jawxs.ibm.tutorial/jaxws/orderprocess") 

//JWS annotation that specifies the mapping of the service onto the

// SOAP message protocol. In particular, it specifies that the SOAP messages 

//are document literal.

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

            parameterStyle=SOAPBinding.ParameterStyle.WRAPPED)

public class OrderProcessService {

    @WebMethod

    public OrderBean processOrder(OrderBean orderBean) {

        // Do processing...

        System.out.println("processOrder called for customer"

                + orderBean.getCustomer().getCustomerId());

        // Items ordered are

        if (orderBean.getOrderItems() != null) {

            System.out.println("Number of items is "

                    + orderBean.getOrderItems().length);

        }

        //Process order.

        //Set the order ID.

        orderBean.setOrderId("A1234");

        return orderBean;

    }

}

OrderBean 中包含订单信息,如清单 中所示。具体来说,其中包含对客户、订单项和配送地址对象的引用。
清单 2. 包含订单信息的 OrderBean 

package com.ibm.jaxws.tutorial.service.bean;                                                                             

public class OrderBean {

private Customer customer;

private Address shippingAddress;

    private OrderItem[] orderItems;

    private String orderId;

    public Customer getCustomer() {

        return customer;

    }

    public void setCustomer(Customer customer) {

        this.customer = customer;

}

public String getOrderId() {

        return orderId;

    }

    public void setOrderId(String orderId) {

        this.orderId = orderId;

    }

    public Address getShippingAddress() {

        return shippingAddress;

    }

    public void setShippingAddress(Address shippingAddress) {

        this.shippingAddress = shippingAddress;

    }

    public OrderItem[] getOrderItems() {

        return orderItems;

}

public void setOrderItems(OrderItem[] orderItems) {

        this.orderItems = orderItems;

    }

}

开发 JAX-WS Web 服务的起点是一个使用 javax.jws.WebService Annotation 进行了标注的 Java 类。所使用的 JAX-WS Annotation 属于 Web Services Metadata for the Java Platform 规范 (JSR-181) 的一部分。您可能已经注意到了,OrderProcessService 使用 WebService Annotation 进行了标注,而后者将类定义为了 Web 服务端点。

OrderProcessService 类(带有 @javax.jws.WebService Annotation 的类)隐式地定义了服务端点接口(Service Endpoint InterfaceSEI),用于声明客户机可以对服务调用的方法。除了使用 @WebMethod Annotation 标注且 exclude 元素设置为 true 的方法外,类中定义的所有公共方法都会映射到 WSDL 操作。@WebMethod Annotation 是可选的,用于对 Web 服务操作进行自定义。除了 exclude 元素外,javax.jws.WebMethod Annotation 还提供 operation name 和 action 元素,用于在 WSDL 文档中自定义操作的 name 属性和 SOAP action 元素。这些属性是可选的;如果未定义,会从类名称派生缺省值。

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

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

4生成 JAX-WS 构件

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

为了生成 JAX-WS 构件,首先需要编译服务和 Bean 源文件:

① 打开命令提示符,并进入到 c:\JAXWS-Tutorial目录(本教程中使用的源文件所在目录)

② 运行以下命令,以编译 Java 文件,并将类文件放入其各自文件夹中:
javac com\ibm\jaxws\tutorial\service\*.java com\ibm\jaxws\tutorial\service\bean\*.java

③ 运行以下命令,以生成 JAX-WS 构件:
wsgen -cp . com.ibm.jaxws.tutorial.service.OrderProcessService -wsdl

④ wsgen 工具提供了大量的选项,例如,其中提供了 -wsdl 选项,用于生成服务的 WSDL 和模式构件。运行此命令后,应该在 JAXWS-Tutorial 文件夹中看到生成的 OrderProcess.wsdlOrderProcess_schema1.xsd,而且会看到在 com\ibm\jaxws\tutorial\service\jaxws 文件夹中创建了 JAX-WS 构件。生成了构件后,运行以下 Web 服务发布器客户机,以发布订单处理 Web 服务。

⑤ 从 c:\JAXWS-Tutorial 文件夹运行以下命令,以编译 OrderWebServicePublisher
javac com\ibm\jaxws\tutorial\service\publish\OrderWebServicePublisher.java

⑥ 然后运行以下命令:
java com.ibm.jaxws.tutorial.service.publish.OrderWebServicePublisher

⑦ 运行 Java 程序后,应该看到以下消息: The Web service is published at http://localhost:8080/OrderProcessWeb/orderprocess. To stop running the Web service, terminate this Java process.

这会将订单 Web 服务发布到 http://localhost:8080/OrderProcessWeb/orderprocess。可以通过显示订单处理 Web 服务生成的 WSDL 来验证 Web 服务是否在运行:

⑧ 打开浏览器,并导航到 http://localhost:8080/OrderProcessWeb/orderprocess?wsdl

5分析 OrderWebServicePublisher

在分析 WSDL 和模式构件前,让我们分析一下 OrderWebServicePublisher 的代码。清单 提供了 OrderWebServicePublisher 客户机的源代码。
清单 3. 用于发布订单处理 Web 服务的代码

package com.ibm.jaxws.tutorial.service.publish;

import javax.xml.ws.Endpoint;

import com.ibm.jaxws.tutorial.service.OrderProcessService;

public class OrderWebServicePublisher {

    public static void main(String[] args) {

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

                new OrderProcessService());

}

}

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

6分析生成的 WSDL

要查看生成的订单处理 Web 服务 WSDL,在浏览器中键入以下 URL 位置: http://localhost:8080/OrderProcessWeb/orderprocess?wsdl.

让我们分析 WSDL 一些重要方面的内容,并了解如何基于 JAX-WS 元数据生成 WSDL 和模式构件,首先要分析的是生成的 XSD。此内容使用 xsd:import 标记导入到 WSDL 文件中(请参见清单 4);schemaLocation 指定 XSD 的位置。
清单 4. 包含订单处理模式定义的 WSDL 文件

<types>    

    <xsd:schema>

      <xsd:import namespace="http://jawxs.ibm.tutorial/jaxws/orderprocess" 

      schemaLocation="OrderProcess_schema1.xsd"/>

    </xsd:schema>

</types>

在浏览器中打开 schemaLocation (http://localhost:8080/OrderProcessWeb/orderprocess?xsd=1),以查看模式定义在浏览器中呈现的情况。让我们分析一下其中的情况:模式定义最开始是 targetNamspace 和 tns 声明,映射到在 OrderProcessService 的 @WebService Annotation 中定义的 targetNamespace http://jawxs.ibm.tutorial/jaxws/orderprocess。清单 给出了对应的代码。

你可能感兴趣的:(java,设计模式,Web,应用服务器,webservice)