读书人

Java Web 服务: Axis2 中的 JAXB 跟 J

发布时间: 2012-10-20 14:12:48 作者: rapoo

Java Web 服务: Axis2 中的 JAXB 和 JAX-WS
Apache Axis2 支持各种数据绑定技术,包括官方 Java? 标准 JAXB 2.x。Axis2 还支持针对 Web 服务配置的 Java 标准 JAX-WS 2.x,作为其自有的配置技术的替代选择。Dennis Sosnoski 将继续他的 Java Web 服务 系列,向您演示如何将这两种 Java 标准用于 Axis2,并讨论 Axis2 对这些标准的当前支持存在哪些限制。
早期的 Apache Axis 建立在第一个面向 Web 服务的 Java 标准 JAX-RPC 的基础之上。事实证明,这并不是一个很好的方法,因为 JAX-RPC 限制了 Axis 代码的内部设计,而且造成了性能问题并缺乏灵活性。JAX-RPC 还对 Web 服务开发的方向作出了假设,而这在后来被证明是错误的。

在开始 Axis2 开发工作时,已经着手研究 JAX-RPC 的替代选择,因此,Axis2 在设计时已经考虑到了足够的灵活性,使其能够在基础框架之上实现对替代 Web 服务标准的支持。最新的 Axis2 版本同时实现了对 JAXB 2.x Java XML 数据绑定标准和替代了 JAX-RP 的 JAX-WS 2.x Java Web 服务标准的支持。本文将展示如何将 JAXB 和 JAX-WS 用于 Axis2 并找出 Axis2 对这些标准的当前支持中存在的一些限制。

Axis2 中的 JAXB

Axis2 实现了对 JAXB 2.x 的支持,将它作为数据绑定替代选择的其中之一,您可以在使用 WSDL2Java 从 Web Services Description Language (WSDL) 服务定义中生成代码时进行选择。(参见 “Java Web Services: Axis2 Data Binding” 获得有关其他主要替代选择的讨论)。和大多数其他替代选择一样,使用 JAXB 2.x 从 WSDL 中生成的代码创建了一组链接(linkage)类和一组数据模型类。这些链接类,包括一个客户端 stub 和一个服务器端消息接收器,充当应用程序代码和 Axis2 之间的接口。数据模型类表示实际的消息数据。

JAXB 2.x 使用数据模型类中的注释来控制数据与 XML 之间的转换方式。注释方法允许您在无需修改源代码或重新编译类的情况下在运行时使用不同的 JAXB 实现。由 JAXB 实现负责从数据模型类访问注释信息并在执行 XML 转换时应用这些注释。

代码下载(参见 下载)提供了一个演示在 Axis2 中使用 JAXB 的示例应用程序,位于 jaxb 目录中。这个应用程序是本系列前一篇文章中的简单的库管理服务的另一个版本(包括 “Axis2 Data Binding” 中的数据绑定比较)。WSDL 服务定义定义了四个操作:

getBook 用来检索由 International Standard Book Number (ISBN) 标识的某本特定图书的细节信息
getBooksByType 用来检索某一特定类型的所有图书的细节信息
getTypes 用于查找可用的图书类型
addBook 用于将新书添加到库中
清单 1 显示的是经过大量编辑的 WSDL,只包含了与 getBook 操作有关的部分:

清单 1. 库服务 WSDL


Axis2 的 JAXB 支持应该进行扩展,以生成未封装的操作方法(为了方便编程,封装到消息中的值被转换为方法参数 — 再一次建议您参考 “Java Web 服务:Axis2 Data Binding”,获得有关封装接口和未封装接口的讨论。但是使用 WSDL2Java 工具的未封装支持,不管在当前的 Axis2 代码中,还是最近几个发行版中,都不适合这个例子。至少在目前,封装操作方法是惟一可以将 JAXB 用于 Axis2 代码生成的方法(但请立刻参考一下 JAX-WS 讨论 了解另一种替代方法)。对于封装操作接口,每个服务方法都对操作使用一个与输入消息匹配的单一对象参数,并为操作返回一个与输出消息匹配的对象。

附带的代码提供了服务和测试客户机的实际实现,开始处理由运行的 WSDL2Java 生成的类。与本系列早期文章的样例代码相同,下载部分包括用于通过 Apache Ant 构建样例的 build.properties 和 build.xml 文件(位于 jaxb 目录)。您首先需要编辑 build.properties 文件,以将路径设置为您的 Axis2 安装(并修改其他设置,如果系统需要的话)。随后可以在一个打开到 jaxb 目录的控制台中输入 ant 以运行 WSDL2Java,编译附带的和生成的代码,并为服务器部署构建 AAR 文件。要进行尝试,首先将生成的 AAR 文件部署到您的 Axis2 服务器安装并在控制台中输入 ant run。

客户端 JAXB 使用

测试客户机使用作为命令行参数传递进来的服务端点参数创建了一个服务 stub 实例,然后依次执行 5 个服务调用:

获得有关某本书的细节。
获得库中的图书类型。
向库添加一本新书(如果该书已经存在的话,此操作将失败,当客户机在未重启服务器的情况下运行超过一次时,也会出现同样的错误)。
如果上一步骤成功,那么尝试使用相同 ISBN 添加另一本书(这个操作应当永远都是失败的)。
获得有关某一特定类型的所有图书的信息。
清单 2 展示了完整的测试客户机代码。可以看到用于每个操作的封装器对象中的服务接口的封装特性,比如调用 getTypes 操作所需的 GetTypes 对象(即使没有为该操作提供输入数据)和由调用返回的 GetTypesResponse 对象。

清单 2. JAXB 测试客户机代码


如果将 清单 2 与 “Java Web Services: Axis2 Data Binding” 中的客户机代码示例加以比较,会发现它非常类似于 JiBX 和 Axis Data Binding (ADB) 封装例子,主要区别在于 JAXB 封装器类使用 Java 5 类型列表(typed lists)而不是数组(JiBX 数据绑定支持的另一个替换选择,但是不受 ADB 支持)。

服务器端使用

库服务的服务器端代码包含两个类,其中一个实际实现库处理,另一个可适应 Axis2 所期望的服务接口。实际的实现代码对于不同的数据绑定几乎都是相同的,只需要根据生成的数据模型表示做一些微小的修改。清单 3 展示了更加有趣的服务接口类。和在客户端一样,封装的接口要求应用程序代码从收到的封装器对象中提取数据,并构造将要发送的封装器对象。

清单 3. JAXB 服务器代码
 

JAX-WS 客户端处理通常要求在运行时访问服务 WSDL,并且使用 WSDL 来初始化服务器链接。如果您已经获知目标服务的 WSDL 始终可以在运行时直接从服务器获得,并且该服务器将始终位于同一地址,那么您可以将 WSDL URL 提供给 WsImport,并让它将 URL 硬编码到生成的代码中。对于大多数严肃的工作,最好使用 WSDL 的本地副本,然后,如果目标服务地址不同于 WSDL 中的地址,那么在运行时重写该地址。附带的构建文件采用了这种方法,而 清单 6 中粗体所示的代码部分演示了如何在不修改 WSDL 的情况下在运行时修改服务地址。

服务器端 JAX-WS 使用

服务器端代码的 JAX-WS 版本如 清单 7 所示。实现类的 @WebService 注释(粗体显示)将实现代码与某个特定 Web 服务接口关联起来。实现类的这个注释允许您从生成的服务接口(清单 5)的相应注释中重写设置。在本例中,注释将设置服务和端口名,并给出 WSDL 服务定义的位置(显然 Axis2 希望该位置与类路径的根相关,或是一个绝对 URL)。

清单 7. JAX-WS 服务器代码
 
@javax.jws.WebService(endpointInterface="com.sosnoski.ws.library.jaxws.Library",portName="library", targetNamespace="http://ws.sosnoski.com/library/wsdl",wsdlLocation="com/sosnoski/ws/library/jaxws/library.wsdl", serviceName="JaxwsLibrary")public class JaxwsLibraryImpl implements Library{    private final BookServer m_server;        public JaxwsLibraryImpl() {        m_server = new BookServer();    }        public boolean addBook(String type, String isbn, List<String> author, String title)        throws AddDuplicateFault {        BookInformation prior = m_server.getBook(isbn);        if (prior == null) {            BookInformation book = new BookInformation();            book.getAuthor().addAll(author);            book.setIsbn(isbn);            book.setTitle(title);            book.setType(type);            return m_server.addBook(book);        } else {            AddDuplicate ad = new AddDuplicate();            ad.setBook(prior);            AddDuplicateFault e =                new AddDuplicateFault("Book already present with matching ISBN", ad);            throw e;        }    }    public BookInformation getBook(String isbn) {        return m_server.getBook(isbn);    }    public List<BookInformation> getBooksByType(String type) {        return m_server.getBooksByType(type);    }    public List<TypeInformation> getTypes() {        return m_server.getTypes();    }}

清单 7 中的其余代码仅仅是 清单 3 所示的(封装)JAXB 示例的未封装版本。

Axis2 中的 JAX-WS 问题

Axis2 在基础 JAX-WS 处理方面表现得非常好,但它的确也存在一些限制。最严重的一点就是当您在 Axis2 中使用 JAX-WS 时,缺乏对 WS-Security 或其他 Web 服务扩展技术的支持(但是围绕 Axis2 构建的应用服务器可能使用自己的方式实现配置和使用 WS-Security)。这对于企业应用程序来说是一个服务器限制,并且,除了一个稍微简单些的配置方法外,不存在任何起到补偿作用的优势,似乎没有足够的理由说服人们马上在 Axis2 中使用 JAX-WS。

结束语

在本文中,您了解了将 JAXB 2.x 和 JAX-WS 2.x Java 标准用于 Axis2 的基础知识。Axis2 中的 JAXB 支持存在某些限制,但是,至少对那些不需要定制的简单模式来说,它为 Axis2 中支持的其他数据绑定方法提供了一种有用的替代选择。JAX-WS 支持的限制更多,目前只对那些不需要 WS-Security 或其他任何增值功能的简单服务有用。

本系列目前为止一直关注 Apache Axis2 框架。有关 JAXB 和 JAX-WS 的介绍为研究其他一些同样支持这些标准的开源 Java Web 服务框架提供了一个良好的起点。在下个月中,本专栏将研究由 Sun 开发的 Metro Web Services 框架以及 JAXB 和 JAX-WS 参考实现。我们将更深入地研究 JAX-WS 的使用和特性。

读书人网 >Web前端

热点推荐