Web 服务元数据简介

    技术2022-05-11  22

    您可以通过编辑一份 Java 文件 — Java Web 服务文件来创建 Web 服务,这不是很奇妙吗?理想的情况是,您还可以自动地从这份文件生成 WSDL,或者从给定的 WSDL 文档生成 Java Web 服务文件的框架。虽然 J2EE 1.4 有助于把可移植性带给运行在 J2EE 运行环境中的 Web 服务应用程序,但是令人头疼的是必须编写两个部署描述符(webservices.xml 和 jax-rpc-mapping.xml)、生成 WSDL 并保持 WSDL 和服务实现 bean 同步。    JSR 181 (用于 Java 平台的 Web 服务元数据) 试图通过在 J2SE 5.0 中使用标注功能来降低这种复杂性。在本文中,我们将研究 JSR 181 中提出的一些功能,以及它对 J2EE 中 Web 服务编程模型带来的冲击。 背景简述   Web 服务元数据(Web Service Meta-data,WSM) 主要是把 Java 中新增的元数据功能应用到 Java Web 服务中。在深入讨论 JSR 181 中具体的 WSM 之前,让我们花上几分钟时间来确保我们已经掌握了 J2EE Web 服务和 Java 中元数据功能的基础知识。欲了解更多信息请参阅参考资料部分。 JAX-RPC   JAX-RPC 代表基于 XML 的远程过程调用的 Java API(Java API for XML-Based Remote Procedure Calls)。简单来说,它仅仅是一种机制,用于执行使用基于 XML 协议的旧 RMI 风格的 RPC,相对于 RMI 中专用于 Java 的协议。Web 服务可以通过服务端点接口(Service Endpoint Interface)映射到 Java,然后作为一种 servlet 实现。客户端编程模型使 Web 服务标注看起来像一次普通的 RPC 调用。为JAX-RPC 实现人员提供 Java XML/WSDL 映射可以使这项工作无缝地进行。JSR 109 构建在 JAX-RPC 之上,并且在生成符合 J2EE 标准的 Web 服务时 JSR 181 处理器必须实现 JAX-RPC 的全部语义。 J2EE Web 服务   在JSR 109 (实现企业 Web 服务)中,J2EE 平台的 Web 服务开发工作被标准化成 J2EE 1.4 平台的一部分。这个 JSR 在很大程度上依赖于 JAX-RPC 规范,并标准化了驻留在 J2EE 运行环境中的 Web 服务的公布方法,这样应用程序就可以在所有符合 J2EE 1.4 规范的应用程序服务器之间进行移植,并且可以由任何 Web 服务客户端 (在 J2EE 环境或非 J2EE 环境中运行)访问。同时,Enterprise JavaBeans (EJB) 2.1 采用了来自 JSR 109 的相应建议,把 Web 服务变成 EJB 世界中的一级公民。   简而言之,JSR 109 是这样一个规范:以一种可移植和互操作的方式为 J2EE 构建和访问 Web 服务。它指定了以下项目: 客户端编程模型:客户端如何访问 Web 服务,就好像 Web 服务是一个普通的远程对象一样。   服务器编程模型:Web 服务如何作为无状态会话 bean 或 JAX-RPC 形式的 servlet 实现。   部署模型:使用部署描述符来定义可以在所有符合 J2EE 规范的应用程序服务器之间移植的 Web 服务。   在 J2EE Web 服务世界里,JSR 181 WSM 文件的最终命运就是转换成 JSR 109 的制品。 Java 元数据功能   J2SE 5.0 引入了一种新的程序标注功能。利用这个功能,可以定义定制标注和标注字段、方法、class 和其它程序元素。这些标注通常不会直接影响程序的语义,但是可以使用工具查看这些标注,以生成额外的构造器(例如部署描述符)或者执行预期的运行行为。可以通过源代码解析(例如,用编译器或 IDE 工具)或者在运行时使用扩展的反射 API 查看标注。标注可以被配置成仅在源代码层、编译的 class 层、或者运行时可用。在 JSR 181 Early Draft中提出的所有标注都有一个 RetentionPolicy of RUNTIME。这样会在某种程度上增加内存中 class 的占用空间,但是却使 Container Provider 和 JSR 181 Processor Providers 的实现更加轻松。 概览   JSR 181 由 BEA Systems 领导,主要基于 Web 服务标注开发工具,这个工具在在 WebLogic Platform 8.1 中提供。这个平台为 Web 服务引入了基于 Javadoc 的标注,在这里,标注被嵌入在 Javadoc 的 class 和 method 注释里。但是,JSR 181 将采用新的基于 J2SE 5.0 标准标注机制。   正如在 JSR 181 早些的草案中所提议的,Java Web 服务仅仅是带有某些标注的普通 Java 对象(Plain Old Java object,POJO)。为了便于引用,我们把这样标注过的文件称为 JWS 文件。标注被用来描述 Web 服务名称、Web 服务界面中公布的所有 method、参数、参数类型、绑定以及其它信息。实际上,与 JSR 109 不同,JWS 文件不需要实现服务端点界面;界面可以基于标注生成。   在 JSR 181 中的另外一个重要概念就是处理器。JSR 181 处理器基本就是一个工具,它把经过标注的 JWS 文件和 Web 服务文件(例如,WSDL 和符合 J2EE 1.4 规范文件如部署描述符)桥接起来。简单来说,它是能够从 JWS 文件生成 WSDL 或者从 WSDL 生成 JWS 文件的工具,它还可以生成完全符合 J2EE 1.4 规范的企业应用程序档案(EAR)文件,生成的 EAR 文件可以立即部署到托管 Web 服务的 J2EE 1.4 容器里。   需要提出的重要一点是:JSR 181 没有定义托管 Web 服务的运行环境或容器。它只是提供了一个处理 JWS 文件的模型,和到 J2EE 1.4 运行期间的环境的映射。 逐步深入   现在是时候讨论 JSR 181 具体细节了。我们先从剖析 JWS 文件入手,然后研究处理或生成 JWS 文件的可行性方法。沿着这条思路,我们将了解 JSR 181 处理器的功能,并理解它与 J2EE 运行环境的关联。 Java Web 服务文件   符合 JSR 181 规范的 Java Web 服务文件是普通的 Java 文件(扩展名为 .java),其中包含一些 JSR 181 标准的标注(也可以有自定义标签)。JWS 文件可以用 J2SE 5.0 编译器编译,JSR 181 处理器能够从源文件(或编译过的文件)读取标注,并生成一套 J2EE Web 服务文件。处理器从 JWS 文件的标注中读取 Web 服务配置信息。例如:@WebService 标注和它的属性被用来指定 Web 服务的名称、服务名称、WSDL 文件的位置等等。以下示例演示了用 JSR 181 标注编写的一个简单的 Web 服务。 import javax.jws.WebService; import javax.jws.WebMethod; @WebService public class HelloWorldService {   @WebMethod   public String helloWorld() {    return "Hello World!";   } }   在定义标注方面,专家组已经采纳了按异常配置(configuration by exception)技术。多数标注都有直观的默认值,所以不需要指定它们;这是可以推理得到的最普遍的信息。例如,如果 @WebService 标注没有指定 name 这个标注成员,就是用默认值来作为 JWS 文件的简单名称(不规范 class 名称)。由于通过 JSR 175 引入的 Java 语言元数据工具还不支持这些“基于规则的默认值”,所以需要 JSR 181 处理器来执行它们。 开发模型   规范允许使用两种模式进行开发:从 WSDL 开始和从 Java 开始。如果您已经有了 WSDL,那么 JSR 181 处理器就会生成 JWS 框架文件,文件中没有 method 和适当的标注。这样,开发人员可以使用 method 实现来填充。但是,流行的模型可能是:生成需要被公布为 Web 服务的 Java 文件。在这种情况下,开发人员只需要对 Java 文件进行适当的标注。处理器可以生成 WSDL、模式以及其它必要的支持文件。 处理器模型   JSR 181 没有指定 Web 服务的运行环境,但是它指定了 JWS 文件处理器的功能。基本理念是使用带有 Java 标注的 Java 语言编写 Web 服务,并且任何符合规范的处理器都可以处理这些标注,并生成适用于目标运行时环境的 Web 服务。不管将来要运行在什么目标环境中,Web 服务的行为方式都应当相同。   几种处理器模型如下:   处理器采用命令行工具的形式,来执行 Java 到 WSDL 和 WSDL 到 Java 的映射工作,并可以报告不兼容问题 — 类似于执行同一任务的 Axis 命令行工具。   处理器可以把 Web 服务直接部署在 J2EE 1.4 容器里,还可以生成标准的 J2EE 1.4 EAR文件。   处理器可以和 IDE 紧密集成,轻点鼠标即可完成上述任务。   处理器可以和 servlet 容器或 EJB 容器紧密耦合,来运行 JWS 文件中生成的 Web 服务。这对于 Java Web 服务的迭代开发来说非常有用。 在规范里对其中一个模型(生成 J2EE 1.4 EAR 文件)进行了详细描述。下图(来自规范)描述了处理器可以输出什么。我们稍后将详细讨论这个模型。 图1.针对J2EE 1.4 运行时环境的 JSR 181   处理器采用形式有多种可能,并没有限制,但是 JSR 181 处理器至少需要支持从 WSDL 开始和从 Java 开始这两种开发模型,并在出现不一致的情况时报告错误。 错误检测   如上所述,当存在不一致时 JSR 181 处理器必须报告错误。例如,如果有人采用从 WSDL 开始模型来生成框架 JWS 文件,然后修改了 method 名称或方法参数名称,那么 JWS 文件和相应的 WSDL 就失去了同步性。处理器必须检查标注是否与其它标注一致。例如,如果为 method 指定 @WebResult 标注,而其返回值是 void,这就是非法的。命令行处理器可以在控制台上输出警告(类似编译器的警告)。如果处理器和 IDE 集成,那么这些错误也可以在编辑器里显示。 标注   现在让我们把注意力转到可以在 JWS 文件里使用的一些重要标注。大多数推荐的标注都定义在 javax.jws 包里,但是不包括用来指定 SOAP 绑定的标注,这些标注在 javax.jws.soap 包里。   Web 服务:@WebService 标注用来在 JWS 文件里对 class 进行标注,表明这个 class 实现了 Web 服务。可以使用 name 标注成员来指定 Web 服务的名称(wsdl:portType),用 serviceName 成员来指定 wsdl:service。同样,可以使用 wsdlLocation 标注成员来指定 JWS 映射到的 WSDL 文件。   服务端点:JSR 181 处理器会提取所有用 @WebMethod 标注进行标注的 method,用它们生成服务端点界面。如果 Web 服务使用 SOAP 绑定,您还可以通过 action 标注成员指定 SOAPAction header。   参数:JWS 文件中的 method 参数可以用 @WebParam 和 @WebResult 标注进行标记,它们对应着 WSDL 中的 wsdl:part 元素,分别代表参数和返回值。在 method 上标记的 @OneWay 标注代表这个方法没有输出,而且可以异步执行。它的副作用就是,@OneWay method 不能发布经过检测的异常,而且显然也不能有任何 OUT/INOUT 参数。正如前面介绍过的,这类规则必须由 JSR 191 处理器来执行。   SOAP 绑定:JSR 181 Early Draft 只对 JWS 文件提供了标准的 SOAP 绑定。当然,也可以通过定制标注来支持其它绑定。根据第一个草案,其意图似乎只是暂时支持SOAP。可以在class 层上指定 @SOAPBinding 标注,从而把这个标注应用于所有 method,或者在 method 层指定,这样就可以使具体的 method 忽略 class 层的标注。它的标注成员 style、use和parameterStyle 可以用来定制到 wsdl:binding 的映射。 安全性:JSR 181 提出了一种通过 @SecurityRoles 和 @SecurityIdentity 标注来指定安全性语义的机制。您可以指定允许哪个角色执行某个具体的 method,以及指定调用线程在运行时采用哪种标识。显然,安全性是 J2EE 平台应当考虑的问题,这个标注最终选择的语法有可能被当作 J2EE 1.5 JSR 的一部分。JSR 220 (EJB 3.0) 已经提出了一种与意图相似的模型,但是语法不同。   以下是这些标注的几个完整示例: import javax.jws.*; import javax.jws.soap.*; @WebService( name="SimpleExampleWebService",            targetNamespace=            "http://example.org/wsm/10/2004/SimpleExampleService") @SOAPBinding(style=SOAPBinding.Style.RPC,             use=SOAPBinding.Use.LITERAL) public class SimpleExampleService {    @WebMethod(action="urn:sayHello")    @WebResult(name="greetings")    public String sayHello(           @WebParam(name="username")           String username) {        return "Hello "+username+"!!!";    }     @WebMethod(action="urn:sayHelloDocument")    @OneWay    @SOAPBinding(style=SOAPBinding.Style.DOCUMENT,                 use=SOAPBinding.Use.LITERAL)    public String sayHelloDocument(                  @WebParam(name="username")                  String username) {       System.out.println(username+" said hello!!!");    } } 在处理的时候,上述的Java Web 服务文件能够生成与下面的 WSDL(他们是由原型处理器生成的,可能不完全准确)相似的结果: <?xml version="1.0" encoding="utf-8"?> <definitions xmlns="http://schemas.xmlsoap.org/wsdl/"         xmlns:tns="http://example.org/wsm/10/2004/SimpleES"         xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"         targetNamespace="http://example.org/wsm/10/2004/SimpleES"         xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <types>    <xsd:schema         targetNamespace="http://example.org/wsm/10/2004/SimpleES">      <xsd:element name="sayHello">        <xsd:complexType>          <xsd:sequence>            <xsd:element name="username" type="xsd:string"         minOccurs="0"/>          </xsd:sequence>        </xsd:complexType>      </xsd:element>      <xsd:element name="greetings">        <xsd:complexType>          <xsd:sequence>            <xsd:element name="greetings" type="xsd:string"          minOccurs="0"/>          </xsd:sequence>        </xsd:complexType>      </xsd:element>      <xsd:element name="sayHelloDocument">        <xsd:complexType>          <xsd:sequence>            <xsd:element name="username" type="xsd:string"          minOccurs="0"/>          </xsd:sequence>        </xsd:complexType>      </xsd:element>    </xsd:schema> </types>    <message name="sayHello">    <part name="username" element="tns:sayHello"/> </message> <message name="greetings">    <part name="username" element="tns:greetings"/> </message> <message name="sayHelloDocument">    <part name="username" element="tns:sayHelloDocument"/> </message>   <portType name="SimpleExampleService">    <operation name="sayHello">      <input message="tns:sayHello"/>      <output message="tns:greetings"/>    </operation>    <operation name="sayHelloDocument">      <input message="tns:sayHelloDocument"/>    </operation> </portType> <binding name="SimpleExampleServiceSoapHttp"          type="tns:SimpleExampleService">    <soap:binding transport="http://schemas.xmlsoap.org/soap/http"          style="rpc"/>    <operation name="sayHello">      <soap:operation soapAction="urn:sayHello" style="rpc"/>        <input>          <soap:body use="literal"          namespace="http://example.org/wsm/10/2004/SimpleES"/>        </input>        <output>          <soap:body use="literal"          namespace="http://example.org/wsm/10/2004/SimpleES"/>        </output>    </operation>    <operation name="sayHelloDocument">      <soap:operation soapAction="urn:sayHelloDocument"          style="document"/>        <input>          <soap:body use="literal"/>        </input>    </operation> </binding> <service name="SimpleExampleWebService">    <port name="SimpleExampleServiceSoapHttp"          binding="tns:SimpleExampleServiceSoapHttp">      <soap:address />    </port> </service> </definitions> 映射到 J2EE 运行环境   如前所述,JSR 181 处理器必须支持从 WSDL 开始和从 Java 开始这两种开发模型,并报告任何不一致问题。从宏观角度来看,这是需求的最小集合。但是,由于这个 JSR 的目标平台是 J2EE,而且 J2EE 也是 Java Web 服务最流行、最广泛的运行环境,所以这个规范非常自然地提议了一些到 J2EE 环境的映射。Early Draft 提议了一个把 JWS 文件映射到 J2EE 1.4 运行环境的模型,但是没有强制要求支持这种映射。   图 1 显示了这个模型。在这里,处理器基于 JSR 109 和 JAX-RPC 1.1 生成 J2EE。其理念是面向 J2EE 1.4 容器的JSR 181 处理器能够在 WSDL 文件和模式之外生成额外的文件。如果服务端点界面作为会话 bean 实现,那么这些额外的文件就有可能是会话 bean 的实现 class、Home 和 Remote 界面、ejb-jar.xml文件以及webservices.xml 和 jax-rpc-mapping.xml文件。 图 1 中的实现 class(Implementation Classes )要么是会话 bean 组件,要么是 JAX-RPC 式的 web 组件(servlet 和它的部署描述符)。还可能是 JSR 181 处理器被构建在容器中,并在访问或部署 Web 服务时生成这些文件。 图 2.针对 J2EE 的 JSR 181 处理器—可能的架构   上面的方法融合了两种模型 — 面向 J2SE 的处理器和面向 J2EE 的处理器。面向 J2EE 的处理器还可以作为使用 JSR 181 处理器的插件 API 生成的插件来构建,如图所示。面向J2SE 的处理器则需要提供 Java 到 WSDL 和 WSDL 到 Java 的转换工具,以及校验器(Validator)来确保 JWS 文件和相应的 WSDL 文件保持同步。为了能在 J2EE 环境里部署这个 JWS,必须生成会话 bean 和它的组件。这些可以使用 EAR Generator Tool生成。例如,EAR Generator Tool 可以使用 XMLBeans 生成部署描述符,以及使用代码生成工具(例如 Velocity)生成 Java class 和界面。这个工具的输出就是一个 EAR 文件,它可以立即部署到任何 J2EE 1.4 容器中。 WSM 实现和应用程序   这一领域已经开展了大量的活动。JSR 181 规范小组将会一直提供参考实现,预计在 JSR 181 正式通过之后,所有主要的供应商就会很快推出他们自己的商业实现。围绕 JSR 181 实现有好几个开放源代码战略;其中最著名的就是 Beehive 和 Pollinate。 Beehive    pache Beehive 是一个应用程序框架,它使用了元数据驱动的编程模型,通过基于标准的、业经验证的、广泛使用的设计模型来编写 J2EE 应用程序。Beehive 应用程序框架的主要组件有:Java 页面流,Java Web 服务,Java 控件,以及 XMLBeans (它本身就是一个独立的 Apache 项目)。Java Web 服务组件是采用 JSR 181 的理想方案。Beehive 社区已经启动了基于 JSR 181 之上的实现,但是仍然处在初期;这正是您加入并提供帮助的绝好时机。 Pollinate    Pollinate,是在 Eclipse 之下开发的一个计划,它将提供一个基于 Eclipse 的、内部采用 Beehive 的 IDE;换句话说,它是一个 Beehive 的开发环境。像 Beehive 一样,Pollinate也远远不只是 Web 服务元数据这么简单,但是 WSM 会是它的核心部分。 结束语   随着 Web 服务发展,规范变得越来越复杂,Web 服务设计和开发工具供应商正在努力让开发人员远离底层的复杂性。他们的尝试虽然富于创新性,但却是非标准的,因此也就严重威胁着这类应用程序的可移植性。JSR 181 是通过 Java 社区对这些创新中的一个( BEA System 提交的 Web 元数据)进行的一项值得称赞的标准化尝试。这个 JSR 的提案不仅让Web 服务更加简单、易于理解,而且还通过易于学习的编程模型(而且很好地支持迭代开发),使得 Web 服务更加容易开发 。   本文的观点仅代表作者本人的观点,与其雇主没有任何关系。 其他读物 JSR 181 Page JSR 109 Page JAX-RPC Introductory article on Java Annotations Apache Axis Apache Beehive Beehive on Dev2Dev 原文出处 http://dev2dev.bea.com/technologies/webservices/articles/Anil_WServices.jsp v 

    最新回复(0)