Apache CXF 开发指南

Red Hat Fuse 7.11

使用 Apache CXF Web 服务开发应用程序

摘要

使用 Apache CXF 开发 Web 服务指南.

使开源包含更多

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。我们从这四个术语开始:master、slave、黑名单和白名单。由于此项工作十分艰巨,这些更改将在即将推出的几个发行版本中逐步实施。详情请查看我们的 CTO Chris Wright 信息

部分 I. 编写 WSDL 合同

本节介绍如何使用 WSDL 定义 Web 服务接口。

第 1 章 介绍 WSDL 合同

摘要

WSDL 文档使用 Web 服务描述语言和多个可能扩展来定义服务。文档具有逻辑部分和组件。合同的抽象部分在实施中立的数据类型和消息中定义服务。文档的声明部分定义了实施服务的端点如何与外界交互。

设计服务的建议方法是先在 WSDL 和 XML 架构中定义服务,然后再编写任何代码。手动编辑 WSDL 文档时,必须确保文档有效且正确。要这样做,您必须对 WSDL 有一定的了解。您可以在 W3C 网站 www.w3.org 找到标准。

1.1. WSDL 文档的结构

概述

WSDL 文件最简单的是根 定义 元素中包含的元素集合。这些元素描述服务以及如何实施该服务的端点。

WSDL 文档有两个不同的部分:

  • 在实施中立地定义该服务 的逻辑部分
  • 定义实施该服务的端点如何在网络中公开的 部分

逻辑部分

WSDL 文档的逻辑部分包含 类型消息portType 元素。它描述了服务的接口以及该服务交换的消息。在 type 元素中,XML Schema 用于定义组成消息的数据的结构。有多个 消息 元素用于定义服务所使用的消息的结构。portType 元素包含一个或多个 操作 元素,用于定义由服务公开的操作发送的消息。

Concrete 部分

WSDL 文档的结合部分包含 绑定 和服务 元素。它描述了实施该服务的端点如何连接到外部世界。绑定 元素描述了如何 将消息 元素描述的数据单元映射到一个 Concrete 中,如 SOAP。服务 元素包含一个或多个 端口 元素,它们定义实施该服务的端点。

1.2. WSDL 元素

WSDL 文档由以下元素组成:

  • 定义 - WSDL 文档的根元素。此元素的属性指定 WSDL 文档的名称、文档的目标命名空间以及 WSDL 文档中引用的命名空间的简写定义。
  • 类型 - 形成服务所用消息的构建块的 XML 架构定义。有关定义数据类型的详情,请参考 第 2 章 定义逻辑数据单元
  • Message - 调用服务操作期间交换的消息描述。这些元素定义组成服务的操作参数。有关定义信息的详情,请参考 第 3 章 定义服务使用的逻辑消息
  • portType - 描述服务逻辑接口 的操作 元素的集合。有关定义端口类型的详情,请参考 第 4 章 定义逻辑接口
  • 操作 - 服务执行的操作的描述。操作由调用操作时在两个端点之间传递的消息定义。有关定义操作的详情请参考 “操作”一节
  • 绑定 - 端点的数据格式规格。binding 元素定义抽象消息如何映射到端点使用的数据格式。此元素是指定参数顺序和返回值等具体位置。
  • 服务 - 相关端口 元素 的集合。这些元素是组织端点定义的软件仓库。
  • 端口 - 由绑定和物理地址定义的端点。这些元素将所有抽象定义整合在一起,以及定义传输详细信息,并定义服务所公开的物理端点。

1.3. 设计合同

要为服务设计 WSDL 合同,您必须执行以下步骤:

  1. 定义服务使用的数据类型。
  2. 定义您的服务使用的消息。
  3. 定义服务的接口。
  4. 定义每个接口使用的消息和线路上的数据的转换之间的绑定。
  5. 定义每个服务的传输详情。

第 2 章 定义逻辑数据单元

摘要

在使用 XML 架构的 WSDL 合同复杂数据类型中描述服务时,将定义为逻辑单元。

2.1. 逻辑数据单元简介

在定义服务时,您必须考虑的第一个操作是如何将用作公开操作参数的数据将被表示。与使用固定数据结构的编程语言编写的应用程序不同,服务必须以逻辑单元中定义其数据,这些应用程序可由任意数量的应用程序使用。这涉及两个步骤:

  1. 将数据拆分为逻辑单元,这些单元可映射到服务物理实施所使用的数据类型中
  2. 将逻辑单元合并到端点之间传递的消息中来执行操作

本章讨论第一步。第 3 章 定义服务使用的逻辑消息 讨论第二步。

2.2. 将数据映射到逻辑数据单元

概述

用于实施服务的接口定义了表示操作参数作为 XML 文档的数据。如果要为已实现的服务定义接口,您必须将实施操作的数据类型转换为消息中可组合的 XML 元素。如果您要从头开始,您必须确定从中构建消息的构建块,以便它们从实施的角度有意义。

可用于定义服务数据单元的类型系统

根据 WSDL 规范,您可以使用您选择的任何类型的系统在 WSDL 合同中定义数据类型。但是,W3C 规格指出 XML 架构是 WSDL 文档的首选规范类型系统。因此,XML Schema 是 Apache CXF 中的内部类型系统。

XML 架构作为类型系统

XML 架构用于定义 XML 文档的结构方式。这可以通过定义组成文档的元素来实现。这些元素可以使用原生 XML 架构类型,如 xsd:int,或者可以使用用户定义的类型。用户定义的类型是使用 XML 元素的组合构建,或者通过限制现有类型来定义它们。通过组合类型定义和元素定义,您可以创建包含复杂数据的内置 XML 文档。

在 WSDL XML Schema 中使用时,定义包含与服务交互数据的 XML 文档的结构。在定义服务使用的数据单元时,您可以将它们定义为类型,以指定消息部分的结构。您还可以将数据单元定义为组成消息部分的元素。

创建数据单元的注意事项

在实施服务时,您可能需要只创建映射到您要使用的类型的逻辑数据单元。虽然此方法可以正常工作,并密切遵循构建 RPC 风格应用程序的模型,但最好构建一种面向服务的架构。

Web 服务互操作性组织的 WS-I 基本配置集提供了多个用于定义数据单元的指南,并可通过 http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html#WSDLTYPES 访问。另外,W3C 还提供了以下准则,使用 XML 架构来代表 WSDL 文档中的数据类型:

  • 使用元素而不是属性。
  • 不要使用特定于协议的类型作为基础类型。

2.3. 在合同中添加数据单元

概述

根据您选择创建 WSDL 合同的方式,创建新的数据定义需要不同的知识。Apache CXF GUI 工具提供了多个有助于描述使用 XML 架构的数据类型。其他 XML 编辑器提供了不同级别的帮助。无论您选择的编辑器如何,最好了解生成的合同应该是什么样的。

流程

定义 WSDL 合同中使用的数据涉及以下步骤:

  1. 确定合同中描述的接口中使用的所有数据单元。
  2. 在您的合同中创建 类型 元素。
  3. 创建一个 schema 元素,如 例 2.1 “WSDL 合同的架构条目”,作为 type 元素的子级。

    targetNamespace 属性指定定义新数据类型的命名空间。最佳实践也是定义提供目标命名空间访问权限的命名空间。不应更改剩余的条目。

    例 2.1. WSDL 合同的架构条目

    <schema targetNamespace="http://schemas.iona.com/bank.idl"
            xmlns="http://www.w3.org/2001/XMLSchema"
            xmlns:xsd1="http://schemas.iona.com/bank.idl"
            xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
  4. 对于作为元素集合的每个复杂类型,使用 complexType 元素定义数据类型。请参阅 第 2.5.1 节 “定义数据结构”
  5. 对于每个数组,使用 complexType 元素定义数据类型。请参阅 第 2.5.2 节 “定义数组”
  6. 对于从简单类型派生的每种复杂类型,请使用 simpleType 元素定义数据类型。请参阅 第 2.5.4 节 “根据限制定义类型”
  7. 对于每个枚举的类型,使用 simpleType 元素定义数据类型。请参阅 第 2.5.5 节 “定义枚举的类型”
  8. 对于每个元素,使用 element 元素 进行定义。请参阅 第 2.6 节 “定义元素”

2.4. XML 架构简单类型

概述

如果消息部分是简单类型,则不需要为其创建类型定义。但是,合同中定义的接口使用的复杂类型是利用简单类型来定义的。

输入简单类型

XML 架构简单类型主要放置在您的合同类型部分使用的 元素 元素中。它们也用于限制元素和扩展 元素 的基本 属性。

使用 xsd 前缀始终输入简单类型。例如,要指定某个元素类型为 int,您可以在其 type 属性中输入 xsd:int,如 例 2.2 “使用简单类型定义元素” 所示。

例 2.2. 使用简单类型定义元素

<element name="simpleInt" type="xsd:int" />

支持的 XSD 简单类型

Apache CXF 支持以下 XML 架构简单类型:

  • XSD:string
  • xsd:normalizedString
  • XSD:int
  • xsd:unsignedInt
  • XSD:long
  • xsd:unsignedLong
  • xsd:short
  • xsd:unsignedShort
  • XSD:浮点值
  • XSD:double
  • XSD:布尔值
  • XSD:字节
  • xsd:unsignedByte
  • XSD:整数
  • xsd:positiveInteger
  • xsd:negativeInteger
  • xsd:nonPositiveInteger
  • xsd:nonNegativeInteger
  • XSD:decimal
  • xsd:dateTime
  • XSD:time
  • XSD:date
  • xsd:QName
  • XSD:base64Binary
  • xsd:hexBinary
  • xsd:ID
  • XSD:token
  • XSD:language
  • xsd:Name
  • xsd:NCName
  • xsd:NMTOKEN
  • xsd:anySimpleType
  • xsd:anyURI
  • xsd:gYear
  • XSD:gMonth
  • XSD:gDay
  • xsd:gYearMonth
  • XSD:gMonthDay

2.5. 定义复杂数据类型

摘要

XML 架构提供了灵活的强大机制,用于从其简单数据类型构建复杂数据结构。您可以通过创建由元素和属性组成的序列来创建数据结构。您还可以扩展您定义的类型,以创建更复杂的类型。

除了构建复杂数据结构外,您还可以描述专用类型,如枚举类型、具有特定范围的值的数据类型,或者通过扩展或限制原语类型需要遵守特定模式的数据类型。

2.5.1. 定义数据结构

概述

在 XML 架构中,作为数据字段集合的数据单元是使用 complexType 元素来定义的。指定复杂类型需要三部分信息:

  1. 定义的类型的名称在 complexType 元素的 name 属性中指定。
  2. complexType 的第一个子元素描述了当 structure 字段在线路上时的行为。请参阅 “复杂的类型 varieties”一节
  3. 定义结构的每个字段都在作为 complexType 元素的 Getndchildren 的元素中定义。请参阅 “定义结构的部分”一节

例如,在 XML 架构中作为带有两个元素的复杂类型来定义 例 2.3 “简单结构” 中的结构。

例 2.3. 简单结构

struct personalInfo
{
  string name;
  int age;
};

例 2.4 “复杂类型” 显示 例 2.3 “简单结构” 中显示的结构的可能 XML 架构映射,在 例 2.4 “复杂类型” 中定义的结构会生成包含两个元素: nameage 的消息。

.

例 2.4. 复杂类型

<complexType name="personalInfo">
  <sequence>
    <element name="name" type="xsd:string" />
    <element name="age" type="xsd:int" />
  </sequence>
</complexType>

复杂的类型 varieties

XML 架构有三种方法来描述复杂类型的字段在以 XML 文档表示并用线路传递时的方式。complexType 元素的第一个子元素决定使用哪些复杂类型。表 2.1 “复杂的类型描述符元素” 显示用于定义复杂类型行为的元素。

表 2.1. 复杂的类型描述符元素

元素复杂的类型行为

序列

所有复杂类型的字段都可以存在,且它们必须按类型定义中指定的顺序。

all

所有复杂的类型字段都可以存在,但可以按任何顺序排列。

choice

只有结构中的其中一个元素可以放在消息中。

如果使用 选择 元素定义结构,如 例 2.5 “简单复杂的选择类型” 所示,它将生成一个包含 name 元素或 age 元素的消息。

例 2.5. 简单复杂的选择类型

<complexType name="personalInfo">
  <choice>
    <element name="name" type="xsd:string"/>
    <element name="age" type="xsd:int"/>
  </choice>
</complexType>

定义结构的部分

您可以使用 元素元素 定义组成结构的数据字段。每个 complexType 元素都应该至少包含一个 元素complexType 元素 中的每个元素代表定义的数据结构中的一个字段。

要完全描述数据结构中的字段,元素 元素有两个所需的属性:

  • name 属性指定 data 字段的名称,它在定义的复杂类型中必须是唯一的。
  • type 属性指定字段中存储的数据类型。类型可以是 XML 架构简单类型之一,也可以是在合同中定义的任何指定复杂类型。

除了名称和类型外,元素元素 还有两个常用的可选属性: minOcurrsmaxOccurs 这些属性根据字段在结构中发生的次数进行绑定。默认情况下,每个字段仅在复杂类型中执行一次。使用这些属性,您可以更改字段必须或可以在结构中显示的次数。例如,您可以定义一个字段 previousJobs,它必须至少发生三次,且不超过七次,如 例 2.6 “具有发生限制的简单复杂类型” 所示。

例 2.6. 具有发生限制的简单复杂类型

<complexType name="personalInfo">
  <all>
    <element name="name" type="xsd:string"/>
    <element name="age" type="xsd:int"/>
    <element name="previousJobs" type="xsd:string:
             minOccurs="3" maxOccurs="7"/>
  </all>
</complexType>

您还可以通过将 minOccurs 设置为 0,使用 minOccurs 来指定 age 字段是可选的,如 例 2.7 “简单的复杂类型,将 minOccurs 设为零” 所示。在这种情况下,可以省略这些 年龄,数据仍将有效。

例 2.7. 简单的复杂类型,将 minOccurs 设为零

<complexType name="personalInfo">
  <choice>
    <element name="name" type="xsd:string"/>
    <element name="age" type="xsd:int" minOccurs="0"/>
  </choice>
</complexType>

定义属性

在 XML 文档中,属性包含在元素的标签中。例如,在下面的代码中的 complexType 元素中,name 是属性。要为复杂类型指定属性,您可以在 complexType 元素定义中定义 属性 元素。属性 元素只能在 所有序列 或选择元素 后显示。为每个复杂类型的属性指定一个 属性 元素。任何 属性 元素都必须是 complexType 元素的直接子项。

例 2.8. 具有属性的复杂类型

<complexType name="personalInfo">
  <all>
    <element name="name" type="xsd:string"/>
    <element name="previousJobs" type="xsd:string"
             minOccurs="3" maxOccurs="7"/>
  </all>
  <attribute name="age" type="xsd:int" use="required" />
</complexType>

在前面的代码中,attribute 元素指定 personalInfo 复杂类型具有 age 属性。attribute 元素具有这些属性:

  • Name - 指定用于标识属性的字符串的必需属性。
  • Type - 指定存储在字段中的数据类型。这个类型可以是 XML 架构简单类型之一。
  • 使用 - 指定具有此属性时是否需要复杂类型的可选属性。有效值 是必需的可选。默认值是 属性是可选的。

attribute 元素中,您可以指定可选的 default 属性,它允许您指定属性的默认值。

2.5.2. 定义数组

概述

Apache CXF 支持在合同中定义数组。首先定义一个复杂的类型,它 maxOccurs 属性的值大于一。第二个是使用 SOAP 阵列。SOAP 阵列提供添加功能,比如轻松地定义多维数组和传输稀疏填充阵列的功能。

复杂的类型数组

复杂的类型数组是序列复杂类型的特殊情况。您只需使用单个元素定义复杂类型,并为 maxOccurs 属性指定值。例如,要定义一系列调整浮动点号,您需要使用类似 例 2.9 “复杂的类型数组” 中显示的复杂类型。

例 2.9. 复杂的类型数组

<complexType name="personalInfo">
  <element name="averages" type="xsd:float" maxOccurs="20"/>
</complexType>

您还可以为 minOccurs 属性指定值。

SOAP 阵列

SOAP 阵列通过除 SOAP-ENC:Array 基本类型使用 wsdl:arrayType 元素来定义。这个语法显示在 例 2.10 “使用 wsdl:arrayType 派生的 SOAP 阵列语法” 中。确保 definition 元素声明 xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"

例 2.10. 使用 wsdl:arrayType 派生的 SOAP 阵列语法

<complexType name="TypeName">
  <complexContent>
    <restriction base="SOAP-ENC:Array">
      <attribute ref="SOAP-ENC:arrayType"
                 wsdl:arrayType="ElementType<ArrayBounds>"/>
    </restriction>
  </complexContent>
</complexType>

使用这个语法,TypeName 指定新定义的数组类型的名称。ElementType 指定阵列中元素的类型。ArrayBounds 指定阵列中的维度数。要指定单一维度数组使用 []; 指定双维数组,使用 [][][,]

例如: SOAP Array, SOAPStrings(如 例 2.11 “SOAP 阵列的定义” 所示)定义一个字符串的一个连续数组。wsdl:arrayType 属性指定数组元素的类型 xsd:string,以及维度的数量( [] 表示一个维度)。

例 2.11. SOAP 阵列的定义

<complexType name="SOAPStrings">
  <complexContent>
    <restriction base="SOAP-ENC:Array">
      <attribute ref="SOAP-ENC:arrayType"
                 wsdl:arrayType="xsd:string[]"/>
    </restriction>
  </complexContent>
</complexType>

您还可以使用简单元素描述 SOAP Array,如 SOAP 1.1 规范中所述。这个语法显示在 例 2.12 “使用元素派生的 SOAP 阵列的语法” 中。

例 2.12. 使用元素派生的 SOAP 阵列的语法

<complexType name="TypeName">
  <complexContent>
    <restriction base="SOAP-ENC:Array">
      <sequence>
        <element name="ElementName" type="ElementType"
                 maxOccurs="unbounded"/>
      </sequence>
    </restriction>
  </complexContent>
</complexType>

使用这种语法时,元素的 maxOccurs 属性必须始终设为 unbound

2.5.3. 按扩展定义类型

与大多数主要的编码语言一样,XML Schema 也允许您创建数据类型来继承其某些元素的数据类型。这称为按照扩展来定义类型。例如,您可以创建一个名为 alienInfo 的新类型,它通过添加一个名为 planet 的新元素来扩展 例 2.4 “复杂类型” 中定义的 个人Info 结构。

由 扩展定义的类型有四个部分:

  1. 类型的名称由 complexType 元素的 name 属性定义。
  2. 复杂的Content 元素指定新类型将具有多个元素。

    注意

    如果您只向复杂类型添加新属性,您可以使用 simpleContent 元素。

  3. 从派生新类型的类型(称为 基础 类型)在 extension 元素的 base 属性中指定。
  4. 新类型的元素和属性在 extension 元素中定义,它们与用于常规复杂的类型相同。

例如: alienInfo 定义,如 例 2.13 “由扩展定义的类型” 所示。

例 2.13. 由扩展定义的类型

<complexType name="alienInfo">
  <complexContent>
    <extension base="xsd1:personalInfo">
      <sequence>
        <element name="planet" type="xsd:string"/>
      </sequence>
    </extension>
  </complexContent>
</complexType>

2.5.4. 根据限制定义类型

概述

XML 架构允许您通过限制 XML 架构简单类型的可能值来创建新类型。例如,您可以定义一个简单类型 SSN,它是仅包含 9 个字符的字符串。通过限制简单类型来定义的新类型,可使用 simpleType 元素来定义。

按限制划分类型的定义需要三个操作:

  1. 新类型的名称通过 simpleType 元素的 name 属性指定。
  2. 从中派生新类型的简单类型(称为 基础类型 )在 limits 元素中指定。请参阅 “指定基础类型”一节
  3. 规则(称为 facets )定义基础类型所施加的限制是作为 限制 元素的子项的子项。请参阅 “定义限制”一节

指定基础类型

基础类型是受限制来定义新类型的类型。它通过 limit 元素 来指定限制 元素是 simpleType 元素的唯一子项,并且具有一个指定 基础 类型的属性(base)。基本类型可以是任何 XML 架构简单类型。

例如,通过限制 xsd:int 的值来定义新类型,您可以使用类似 例 2.14 “使用 int 作为基础类型” 中显示的定义。

例 2.14. 使用 int 作为基础类型

<simpleType name="restrictedInt">
  <restriction base="xsd:int">
    ...
  </restriction>
</simpleType>

定义限制

定义对基本类型实施的限制的规则称为 facets。facets 是带有一条属性( value )的元素,它定义了如何强制实施 facet。可用的难题及其 有效值 设置取决于基本类型。例如,xsd:string 支持六方面面,其中包括:

  • length
  • minLength
  • maxLength
  • pattern
  • whitespace
  • 枚举

每个 facet 元素都是 限制 元素的子元素。

示例

例 2.15 “SSN 简单类型描述” 显示了一个简单类型 SSN 的示例,它代表了一个社交安全号。生成的 type 是 xxx-xx-xxxx 形式的字符串。<SSN>032-43-9876<SSN> 是此类型的元素的有效值,但 <SSN>032439876</SSN> 不可用。

例 2.15. SSN 简单类型描述

<simpleType name="SSN">
  <restriction base="xsd:string">
    <pattern value="\d{3}-\d{2}-\d{4}"/>
  </restriction>
</simpleType>

2.5.5. 定义枚举的类型

概述

XML 架构中的枚举类型是根据限制的特殊定义情况。它们通过使用 枚举 面貌(受所有 XML 架构制语支持)加以说明。与大多数现代编程语言中枚举的类型一样,这种类型的变量只能具有其中一个指定值。

在 XML 架构中定义枚举

定义枚举的语法显示在 例 2.16 “枚举的语法” 中。

例 2.16. 枚举的语法

<simpleType name="EnumName">
  <restriction base="EnumType">
    <enumeration value="Case1Value"/>
    <enumeration value="Case2Value"/>
    ...
    <enumeration value="CaseNValue"/>
  </restriction>
</simpleType>

EnumName 指定枚举类型的名称。EnumType 指定问题单值的类型。CaseNValue,其中 N 是任意一个或更大值,它指定枚举的每个具体案例的值。枚举的类型可以包含任意数量的问题单值,但由于从简单类型派生出,因此一次只有一个问题单值有效。

示例

例如,如果一个带有由 enumeration widgetSize 定义的元素的 XML 文档,如果它包括了 < widgetSize >big</widgetSize>,则它无效,但如果包含 <widgetSize>big,mungo</widgetSize>。例 2.17 “widgetSize enumeration”

例 2.17. widgetSize enumeration

<simpleType name="widgetSize">
  <restriction base="xsd:string">
    <enumeration value="big"/>
    <enumeration value="large"/>
    <enumeration value="mungo"/>
  </restriction>
</simpleType>

2.6. 定义元素

XML 架构中的元素代表从架构生成的 XML 文档中的一个元素实例。最基本的 元素由单个元素组成。与用于定义复杂类型的成员的 element 相似,它们有三个属性:

  • Name - 指定元素名称(在 XML 文档中出现)的必需属性。
  • type - 指定元素的类型。类型可以是任何 XML 架构原语类型,也可以是合同中定义的任何指定复杂类型。如果 type 具有内个定义,则可以省略此属性。
  • nillable - 指定是否可以完全从文档中省略元素。如果 nillable 被设置为 true,则元素可以从使用 schema 生成的任何文档中省略。

元素也可以具有 内行 类型定义。in-line 类型通过 complexType 元素或 simpleType 元素来指定。指定数据类型是否复杂或简单后,您可以使用每种数据类型可用的工具定义任何类型的数据。不建议使用行类型定义,因为它们没有重复使用。

第 3 章 定义服务使用的逻辑消息

摘要

服务由消息在调用操作时进行交换。在 WSDL 合同中,这些消息通过 消息 元素进行定义。消息由一个或多个利用 部分 元素定义的部分组成。

概述

服务的操作通过指定调用操作时交换的逻辑信息来定义。这些逻辑消息定义通过网络传输的数据作为 XML 文档。它们包含作为方法调用的一部分的所有参数。 使用您的合同中的 message 元素定义逻辑消息。每个逻辑消息由 部分 元素中定义的一个或多个部分组成。

虽然您的消息可以将每个参数列为单独的部分,但建议的做法是只使用一个部分来封装操作所需的数据。

消息和参数列表

服务公开的每个操作只能有一个输入消息和一个输出消息。输入消息定义在调用操作时服务接收的所有信息。输出消息定义在操作完成后服务返回的所有数据。故障消息定义服务在发生错误时返回的数据。

另外,每个操作都可以具有任意数量的故障消息。故障消息定义服务遇到错误时返回的数据。这些消息通常只有一个部分,以供消费者了解错误。

用于与旧系统集成的消息设计

如果要将现有应用程序定义为服务,您必须确保实施操作方法使用的每个参数都在消息中表示。您还必须确保操作输出消息中包含返回值。

定义您的消息的一种方法是 RPC 样式。在使用 RPC 样式时,您可以在方法的参数列表中为每个参数定义一个消息。每种消息部分均基于合同 类型 元素中定义的类型。您的输入消息包含方法中每个输入参数的部分。您的输出消息会包括每个输出参数的一个部分,以及代表返回值的部分(如果需要)。如果参数既是输入参数和输出参数,它将被列为输入消息和输出消息的一部分。

当启用使用 Tibco 或 CORBA 等传输的旧系统时,RPC 样式消息定义很有用。这些系统围绕了程序和方法设计。因此,使用类似参数列表的消息可方便建模,用于调用的操作。RPC 样式也使得服务与它所公开的应用之间形成一个干净的映射。

SOAP 服务的消息设计

而 RPC 样式对现有系统建模非常有用,而该服务的社区很广泛地使用嵌套文档风格。在嵌套文档风格中,每个消息都有一个部分。该消息的部分引用合同 类型 元素中定义的打包程序元素。wrapper 元素具有以下特征:

  • 它是包含一系列元素的复杂类型。更多信息请参阅 第 2.5 节 “定义复杂数据类型”
  • 如果它是一个用于输入信息的打包程序:

    • 它为每个方法的输入参数都有一个元素。
    • 其名称与与其关联的操作的名称相同。
  • 如果它是一个输出信息的打包程序:

    • 它为每个方法的输出参数和一个元素,每个方法的 inout 参数中有一个元素。
    • 第一个元素表示方法的返回参数。
    • 其名称将通过将响应 附加到 与打包程序关联的操作的名称。

消息命名

合同中的每个消息都必须在其命名空间中具有唯一的名称。建议您使用以下命名规则:

  • 消息只应用于一个操作。
  • 输入消息名是通过在操作名称中添加 Request 来形成的。
  • 输出消息的名称是通过在操作名称中添加 Response 来形成的。
  • 错误消息名称应该代表故障的原因。

消息部分

消息部分是逻辑消息的正式数据单元。每一部分使用 part 元素来定义,由 name 属性标识,另一个是 type 属性或指定其数据类型的 element 属性。数据类型属性列在 表 3.1 “部分数据类型属性” 中。

表 3.1. 部分数据类型属性

属性描述

element="elem_name"

部分的数据类型由名为 elem_name 的元素定义。

type="type_name"

部分的数据类型由名为 type_name 的类型定义。

允许消息重复使用部分名称。例如,如果方法有参数 foo,它通过引用或是一个 in/out 传递,它可以是请求消息和响应信息的一部分,如 例 3.1 “重复使用的部分” 所示。

例 3.1. 重复使用的部分

<message name="fooRequest">
  <part name="foo" type="xsd:int"/>
<message>
<message name="fooReply">
  <part name="foo" type="xsd:int"/>
<message>

示例

例如,假设您有一个存储个人信息的服务器,并提供了一个基于员工的 ID 编号返回员工数据的方法。查找数据的签名方法与 例 3.2 “personalInfo 查找方法” 类似。

例 3.2. personalInfo 查找方法

personalInfo lookup(long empId)

这个方法签名可以映射到 例 3.3 “RPC WSDL 消息定义” 中显示的 RPC 风格的 WSDL 片段。

例 3.3. RPC WSDL 消息定义

<message name="personalLookupRequest">
  <part name="empId" type="xsd:int"/>
<message/>
<message name="personalLookupResponse>
  <part name="return" element="xsd1:personalInfo"/>
<message/>

它还可以映射到 例 3.4 “嵌套文档 WSDL 消息定义” 中显示的嵌套文档风格的 WSDL 片段。

例 3.4. 嵌套文档 WSDL 消息定义

<wsdl:types>
  <xsd:schema ... >
  ...
  <element name="personalLookup">
    <complexType>
      <sequence>
        <element name="empID" type="xsd:int" />
      </sequence>
    </complexType>
  </element>
  <element name="personalLookupResponse">
    <complexType>
      <sequence>
        <element name="return" type="personalInfo" />
      </sequence>
    </complexType>
  </element>
  </schema>
</types>
<wsdl:message name="personalLookupRequest">
  <wsdl:part name="empId" element="xsd1:personalLookup"/>
<message/>
<wsdl:message name="personalLookupResponse">
  <wsdl:part name="return" element="xsd1:personalLookupResponse"/>
<message/>

第 4 章 定义逻辑接口

摘要

逻辑服务接口通过 portType 元素进行定义。

概述

逻辑服务接口通过 WSDL portType 元素进行定义。portType 元素是抽象操作定义的集合。每个操作都由用于完成操作所代表的输入、输出和错误消息来定义。当生成代码来实施 portType 元素中定义的服务接口时,每个操作都会转换成一个方法,其中包含由合同中指定的参数、输出和错误消息。

Process

要在 WSDL 合同中定义逻辑接口,您必须执行以下操作:

  1. 创建一个 portType 元素,以包含接口定义,并为它指定唯一名称。请参阅 “端口类型”一节
  2. 为接口中定义的每个操作创建一个操作元素。请参阅 “操作”一节
  3. 对于每个操作,请指定用于代表操作参数列表、返回类型和异常的消息。请参阅 “操作消息”一节

端口类型

WSDL portType 元素是逻辑接口定义中的根元素。虽然许多 Web 服务实施直接将 portType 元素映射到生成的实现对象,但逻辑接口定义没有指定由实施的服务提供的确切功能。例如,名为 ticketSystem 的逻辑接口可导致一个实现,可以销售 concert ticket 或挂起问题单的问题。

portType 元素是 WSDL 文档的单元,映射到绑定中,以定义端点用来公开定义的服务所使用的物理数据。

WSDL 文档中的每个 portType 元素必须具有唯一的名称,使用 name 属性来指定,由一系列操作组成,它们在 操作 元素中描述。WSDL 文档可以描述任意数量的端口类型。

操作

使用 WSDL 操作元素定义的逻辑 操作,定义两个端点之间的交互。例如,对检查帐户余量的请求和跨小部件的订购都可以定义为操作。

portType 元素中定义的每个操作必须具有唯一的名称,使用 name 属性指定。定义操作需要 name 属性。

操作消息

逻辑操作由代表端点之间沟通的逻辑消息的一组元素组成,以执行该操作。表 4.1 “操作消息元素” 中列出了可描述操作的元素。

表 4.1. 操作消息元素

元素描述

输入

指定在发出请求时客户端端点发送到服务供应商的消息。此消息的部分内容对应于操作的输入参数。

output

指定服务提供商在响应请求时发送到客户端端点的消息。此消息的部分内容对应于服务提供商可更改的任何操作参数,例如通过引用传递的值。这包括操作的返回值。

fault

指定用于在端点之间通信错误条件的消息。

需要具有至少一个 输入 或一个 输出元素的操作。操作可以同时具有 输入和输出 元素,但每个元素只能有一个。操作不需要有任何 故障 元素,但在需要时也可具有任意数量的 故障 元素。

元素在 表 4.2 “输入和输出元素的属性” 中列出的两个属性。

表 4.2. 输入和输出元素的属性

属性描述

name

标识消息,以便在将操作映射到组件数据格式时引用它。名称必须在包含的端口类型内唯一。

message

指定描述正在发送或接收的数据的抽象信息。message 属性的值必须与 WSDL 文档中定义的其中一个抽象消息的 name 属性对应。

不需要为所有 输入和输出 元素指定 name 属性,而 WSDL 会根据包含操作的名称提供默认命名方案。如果操作中只使用一个元素,则元素名称默认为操作的名称。如果使用 输入和输出 元素,则元素名称将分别默认为带有 RequestResponse 附加到名称的操作的名称。

返回值

因为 operation 元素是操作期间传递的数据的一个抽象定义,所以 WSDL 不会提供为操作指定的返回值。如果方法返回一个值,它将映射到 output 元素,作为该消息的最后一个部分。

示例

例如,您可能有一个与 例 4.1 “personalInfo 查找接口” 中显示的接口类似。

例 4.1. personalInfo 查找接口

interface personalInfoLookup
{
  personalInfo lookup(in int empID)
  raises(idNotFound);
}

这个接口可以映射到 例 4.2 “personalInfo 查找端口类型” 中的端口类型。

例 4.2. personalInfo 查找端口类型

<message name="personalLookupRequest">
  <part name="empId" element="xsd1:personalLookup"/>
<message/>
<message name="personalLookupResponse">
  <part name="return" element="xsd1:personalLookupResponse"/>
<message/>
<message name="idNotFoundException">
  <part name="exception" element="xsd1:idNotFound"/>
<message/>
<portType name="personalInfoLookup">
  <operation name="lookup">
    <input name="empID" message="tns:personalLookupRequest"/>
    <output name="return" message="tns:personalLookupResponse"/>
    <fault name="exception" message="tns:idNotFoundException"/>
  </operation>
</portType>

部分 II. Web 服务绑定

本节介绍如何将 Apache CXF 绑定添加到 WSDL 文档。

第 5 章 了解 WSDL 中的绑定

摘要

绑定将用于定义服务的逻辑消息映射到端点可传输和接收的冲突格式。

概述

绑定在服务用于聚合的数据格式的逻辑消息之间提供桥接,该格式端点在物理世界中使用。它们描述了逻辑消息如何映射到端点在线路上使用的有效负载格式。在绑定中,指定了参数顺序、分散数据类型和返回值等详情。例如,消息的部分可以被重新排序,以反映 RPC 调用所需的顺序。根据绑定类型,您还可以识别哪些消息部分(若有)代表方法的返回类型。

端口类型和绑定

端口类型和绑定直接相关。端口类型是在两个逻辑服务之间一组交互的抽象定义。绑定(绑定) 是指在物理世界中实例化用于实施逻辑服务的消息的定义。然后,每个绑定都与一组网络详情相关联,该详细信息是结束一个端点的定义,这些端点公开由端口类型定义的逻辑服务。

为确保端点仅定义单个服务,WSDL 要求绑定只能表示单一端口类型。例如,如果您具有与两个端口类型的合同,则无法编写将这两个绑定映射到统一数据格式。您需要两个绑定。

但是,WSDL 允许将端口类型映射到多个绑定。例如,如果您的合同具有单一端口类型,您可以将它映射到两个或更多个绑定中。每个绑定都可以更改消息的部分映射方式,或者为消息指定完全不同的有效负载格式。

WSDL 元素

使用 WSDL 绑定元素在合同中定义绑定。binding 元素由属性组成,如,其名称为提供 PortType 的引用的绑定和类型指定唯一名称。 此属性的值用于将绑定与端点关联,如 第 4 章 定义逻辑接口 中所述。

实际映射在 binding 元素的子项中定义。这些元素根据您决定使用的有效负载格式类型而有所不同。以下部分阐述了不同的有效负载格式以及用于指定其映射的元素。

添加到合同中

Apache CXF 提供可为预定义服务生成绑定的命令行工具。

该工具将为您添加正确的元素到您的合同中。但是,建议您了解不同类型的绑定的工作原理。

您还可以使用任何文本编辑器将绑定添加到合同中。手动编辑合同时,您需要确保合同有效。

支持的绑定

Apache CXF 支持以下绑定:

  • SOAP 1.1
  • SOAP 1.2
  • CORBA
  • pure XML

第 6 章 使用 SOAP 1.1 消息

摘要

Apache CXF 提供了一个工具来生成 SOAP 1.1 绑定,它不使用任何 SOAP 标头。但是,您可以使用任何文本或 XML 编辑器将 SOAP 标头添加到您的绑定中。

6.1. 添加 SOAP 1.1 Binding

使用 wsdl2soap

要使用 wsdl2soap 生成 SOAP 1.1 绑定: wsdl2soap-iport-type-name-bbinding-name-doutput-directory-ooutput-file-nsoap-body-namespace-style(document/rpc)-use(literal/encoded)-v-verbose-quietwsdlurl

注意

要使用 wsdl2soap,您将需要下载 Apache CXF 分发版本。

该命令具有以下选项:

选项解释

-i port-type-name

指定生成绑定的 portType 元素。

wsdlurl

包含 portType 元素定义的 WSDL 文件的路径和名称。

该工具具有以下可选参数:

选项解释

-b binding-name

指定生成的 SOAP 绑定的名称。

-d output-directory

指定放置生成的 WSDL 文件的目录。

-O output-file

指定生成的 WSDL 文件的名称。

-n soap-body-namespace

当 风格为 RPC 时,指定 SOAP 正文命名空间。

-style (document/rpc)

指定 SOAP 绑定中使用的编码风格(document 或 RPC)。默认为文档。

-use (literal/encoded)

指定在 SOAP 绑定中使用的绑定使用(编码或字面处理)。默认为字面上的。

-v

显示工具的版本号。

-verbose

在代码生成过程中显示注释。

-quiet

在代码生成过程中禁止评论。

需要 -i port-type-namewsdlurl 参数。如果指定了 -style rpc 参数,则还需要 -n soap-body-namspace 参数。所有其他参数都是可选的,可以按任何顺序列出。

重要

wsdl2soap 不支持生成 文档/编码的 SOAP 绑定。

示例

如果您的系统有一个接口,它会使用订购并提供单一操作来处理与 例 6.1 “排序系统接口” 中显示的 WSDL 片段中定义的订购。

例 6.1. 排序系统接口

<?xml version="1.0" encoding="UTF-8"?>
<definitions name="widgetOrderForm.wsdl"
    targetNamespace="http://widgetVendor.com/widgetOrderForm"
    xmlns="http://schemas.xmlsoap.org/wsdl/"
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
    xmlns:tns="http://widgetVendor.com/widgetOrderForm"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:xsd1="http://widgetVendor.com/types/widgetTypes"
    xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">

<message name="widgetOrder">
  <part name="numOrdered" type="xsd:int"/>
</message>
<message name="widgetOrderBill">
  <part name="price" type="xsd:float"/>
</message>
<message name="badSize">
  <part name="numInventory" type="xsd:int"/>
</message>

<portType name="orderWidgets">
  <operation name="placeWidgetOrder">
    <input message="tns:widgetOrder" name="order"/>
    <output message="tns:widgetOrderBill" name="bill"/>
    <fault message="tns:badSize" name="sizeFault"/>
  </operation>
</portType>
...
</definitions>

orderWidget 生成的 SOAP 绑定显示在 例 6.2 “用于 orderWidgets的 SOAP 1.1 Binding” 中。

例 6.2. 用于 orderWidgets的 SOAP 1.1 Binding

<binding name="orderWidgetsBinding" type="tns:orderWidgets">
  <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <operation name="placeWidgetOrder">
      <soap:operation soapAction="" style="document"/>
      <input name="order">
        <soap:body use="literal"/>
      </input>
      <output name="bill">
        <soap:body use="literal"/>
      </output>
      <fault name="sizeFault">
        <soap:body use="literal"/>
      </fault>
  </operation>
</binding>

此绑定指定消息使用 document/literal 消息样式发送。

6.2. 在 SOAP 1.1 绑定中添加 SOAP 标头

概述

SOAP 标头通过在默认的 SOAP 1.1 绑定中添加 soap:header 元素来定义。soap:header 元素是 输入输出和错误 元素的可选子元素。SOAP 标头成为父消息的一部分。SOAP 标头通过指定消息和消息部分来定义。每个 SOAP 标头只能有一个消息部分,但您可以根据需要插入多个 SOAP 标头。

语法

定义 SOAP 标头的语法显示在 例 6.3 “SOAP 标头语法” 中。soap:headermessage 属性是插入标头的部分所在消息的限定名称。part 属性是插入到 SOAP 标头中的消息部分的名称。由于 SOAP 标头始终为文档风格,因此必须使用元素定义插入到 SOAP 标头中的 WSDL 消息部分。消息部分 属性共同描述要插入到 SOAP 标头中的数据。

例 6.3. SOAP 标头语法

<binding name="headwig">
  <soap:binding style="document"
                transport="http://schemas.xmlsoap.org/soap/http"/>
    <operation name="weave">
      <soap:operation soapAction="" style="document"/>
      <input name="grain">
        <soap:body ... />
        <soap:header message="QName" part="partName"/>
      </input>
...
</binding>

除了强制 消息和 部分属性, soap:header 也支持 命名空间使用,以及 encodingStyle 属性。这些属性对于 soap:header 的作用相同,因为它们为 soap:body

在正文和标头间分割消息

插入到 SOAP 标头的消息部分可以是合同中任何有效的消息部分。它也可以是父消息的一部分,这些消息用作 SOAP 正文。由于您不太可能在同一消息中发送信息两次,因此 SOAP 绑定提供了指定插入到 SOAP 正文中的消息部分的方法。

soap:body 元素具有一个可选的属性(part),它取一个以空格分隔的部分名称列表。当定义各个部分时,只有列出的消息部分才会插入到 SOAP 正文中。然后您可以将剩余的部分插入 SOAP 标头。

注意

当您使用父消息的部分定义 SOAP 标头时,Apache CXF 会自动填写您的 SOAP 标头。

示例

例 6.4 “带有 SOAP 头的 SOAP 1.1 绑定” 显示 例 6.1 “排序系统接口” 中显示的 orderWidgets 服务的修改版本。此版本已被修改,每个顺序都有一个 xsd:base64binary 值,放置在请求的 SOAP 标头中。SOAP 标头定义为来自 widgetKey 消息的 keyVal 部分。在这种情况下,您需要把 SOAP 标头添加到应用程序逻辑中,因为它不是输入或输出消息的一部分。

例 6.4. 带有 SOAP 头的 SOAP 1.1 绑定

<?xml version="1.0" encoding="UTF-8"?>
<definitions name="widgetOrderForm.wsdl"
    targetNamespace="http://widgetVendor.com/widgetOrderForm"
    xmlns="http://schemas.xmlsoap.org/wsdl/"
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
    xmlns:tns="http://widgetVendor.com/widgetOrderForm"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:xsd1="http://widgetVendor.com/types/widgetTypes"
    xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">

<types>
  <schema targetNamespace="http://widgetVendor.com/types/widgetTypes"
           xmlns="http://www.w3.org/2001/XMLSchema"
           xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
    <element name="keyElem" type="xsd:base64Binary"/>
  </schema>
</types>

<message name="widgetOrder">
  <part name="numOrdered" type="xsd:int"/>
</message>
<message name="widgetOrderBill">
  <part name="price" type="xsd:float"/>
</message>
<message name="badSize">
  <part name="numInventory" type="xsd:int"/>
</message>
<message name="widgetKey">
  <part name="keyVal" element="xsd1:keyElem"/>
</message>

<portType name="orderWidgets">
  <operation name="placeWidgetOrder">
    <input message="tns:widgetOrder" name="order"/>
    <output message="tns:widgetOrderBill" name="bill"/>
    <fault message="tns:badSize" name="sizeFault"/>
  </operation>
</portType>

<binding name="orderWidgetsBinding" type="tns:orderWidgets">
  <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <operation name="placeWidgetOrder">
      <soap:operation soapAction="" style="document"/>
      <input name="order">
        <soap:body use="literal"/>
        <soap:header message="tns:widgetKey" part="keyVal"/>
      </input>
      <output name="bill">
        <soap:body use="literal"/>
        <soap:header message="tns:widgetKey" part="keyVal"/>
      </output>
      <fault name="sizeFault">
        <soap:body use="literal"/>
      </fault>
  </operation>
</binding>
...
</definitions>

您还可以修改 例 6.4 “带有 SOAP 头的 SOAP 1.1 绑定”,以便标头值是输入和输出信息的一部分。

第 7 章 使用 SOAP 1.2 信息

摘要

Apache CXF 提供生成 SOAP 1.2 绑定的工具,它不使用任何 SOAP 标头。您可以使用任何文本或 XML 编辑器将 SOAP 标头添加到您的绑定中。

7.1. 将 SOAP 1.2 绑定添加到 WSDL 文档

使用 wsdl2soap

注意

要使用 wsdl2soap,您将需要下载 Apache CXF 分发版本。

要使用 wsdl2soap 生成 SOAP 1.2 绑定,请使用以下命令: wsdl2soap-iport-type-name-bbinding-name- SOAp12-doutput-directory-nsoap-body-namespace-style(document/rpc)-use(literal/encoded)-quietwdlurl 工具有以下所需参数:

选项解释

-i port-type-name

指定生成绑定的 portType 元素。

-soap12

指定生成的绑定使用 SOAP 1.2。

wsdlurl

包含 portType 元素定义的 WSDL 文件的路径和名称。

该工具具有以下可选参数:

选项解释

-b binding-name

指定生成的 SOAP 绑定的名称。

-soap12

指定生成的绑定将使用 SOAP 1.2。

-d output-directory

指定放置生成的 WSDL 文件的目录。

-O output-file

指定生成的 WSDL 文件的名称。

-n soap-body-namespace

当 风格为 RPC 时,指定 SOAP 正文命名空间。

-style (document/rpc)

指定 SOAP 绑定中使用的编码风格(document 或 RPC)。默认为文档。

-use (literal/encoded)

指定在 SOAP 绑定中使用的绑定使用(编码或字面处理)。默认为字面上的。

-v

显示工具的版本号。

-verbose

在代码生成过程中显示注释。

-quiet

在代码生成过程中禁止评论。

需要 -i port-type-namewsdlurl 参数。如果指定了 -style rpc 参数,则还需要 -n soap-body-namspace 参数。所有其他参数都是可选的,可以按任何顺序列出。

重要

wsdl2soap 不支持生成 文档/编码的 SOAP 1.2 绑定。

示例

如果您的系统有一个接口,它会使用订购并提供单一操作来处理与 例 7.1 “排序系统接口” 中显示的 WSDL 片段中定义的订购。

例 7.1. 排序系统接口

<?xml version="1.0" encoding="UTF-8"?>
<definitions name="widgetOrderForm.wsdl"
    targetNamespace="http://widgetVendor.com/widgetOrderForm"
    xmlns="http://schemas.xmlsoap.org/wsdl/"
    xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
    xmlns:tns="http://widgetVendor.com/widgetOrderForm"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:xsd1="http://widgetVendor.com/types/widgetTypes"
    xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">

<message name="widgetOrder">
  <part name="numOrdered" type="xsd:int"/>
</message>
<message name="widgetOrderBill">
  <part name="price" type="xsd:float"/>
</message>
<message name="badSize">
  <part name="numInventory" type="xsd:int"/>
</message>

<portType name="orderWidgets">
  <operation name="placeWidgetOrder">
    <input message="tns:widgetOrder" name="order"/>
    <output message="tns:widgetOrderBill" name="bill"/>
    <fault message="tns:badSize" name="sizeFault"/>
  </operation>
</portType>
...
</definitions>

为 orderWidget 生成的 SOAP 绑定显示在 例 7.2 “用于 orderWidgets 的 SOAP 1.2 绑定” 中。

例 7.2. 用于 orderWidgets 的 SOAP 1.2 绑定

<binding name="orderWidgetsBinding" type="tns:orderWidgets">
  <soap12:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <operation name="placeWidgetOrder">
      <soap12:operation soapAction="" style="document"/>
      <input name="order">
        <soap12:body use="literal"/>
      </input>
      <output name="bill">
        <wsoap12:body use="literal"/>
      </output>
      <fault name="sizeFault">
        <soap12:body use="literal"/>
      </fault>
  </operation>
</binding>

此绑定指定消息使用 document/literal 消息样式发送。

7.2. 在 SOAP 1.2 消息中添加标头

概述

SOAP 邮件标题通过在 SOAP 1.2 信息中添加 soap12:header 元素来定义。soap12:header 元素是绑定的、outputfault 元素的可选子项。SOAP 标头成为父消息的一部分。SOAP 标头通过指定消息和消息部分来定义。每个 SOAP 标头只能有一个消息部分,但您可以根据需要插入多个标头。

语法

定义 SOAP 标头的语法显示在 例 7.3 “SOAP 标头语法” 中。

例 7.3. SOAP 标头语法

<binding name="headwig">
  <soap12:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <operation name="weave">
      <soap12:operation soapAction="" style="documment"/>
      <input name="grain">
        <soap12:body ... />
        <soap12:header message="QName" part="partName"
                       use="literal|encoded"
                        encodingStyle="encodingURI"
                        namespace="namespaceURI" />
      </input>
...
</binding>

表 7.1 “soap12:header Attributes” 描述了 soap12:header 元素的属性。

表 7.1. soap12:header Attributes

属性描述

message

指定将要插入到标头中的消息的合格属性。

part

指定插入到 SOAP 标头中的消息部分的名称所需的属性。

使用

指定消息部分是否使用编码规则进行编码。如果设置为 编码 消息部分,则使用由 encodingStyle 属性的值指定的编码规则进行编码。如果设置为 字面,则消息部分由所引用的 schema 类型定义。

encodingStyle

指定用于构建消息的编码规则。

namespace

使用 use="encoded" 定义分配给标头元素序列化的命名空间。

在正文和标头间分割消息

插入到 SOAP 标头的消息部分可以是合同中任何有效的消息部分。它也可以是父消息的一部分,这些消息用作 SOAP 正文。由于您不太可能在同一消息中发送信息两次,因此 SOAP 1.2 绑定提供了指定插入到 SOAP 正文中的消息部分的方法。

soap12:body 元素具有一个可选的属性(part),它取一个以空格分隔的部分名称列表。当定义各个部分时,只有列出的消息部分插入到 SOAP 1.2 消息的正文中。然后您可以将剩余的部分插入消息的标头中。

注意

当您使用父消息的部分定义 SOAP 标头时,Apache CXF 会自动填写您的 SOAP 标头。

示例

例 7.4 “使用 SOAP Header 的 SOAP 1.2 绑定” 显示 例 7.1 “排序系统接口” 中显示的 orderWidgets 服务的修改版本。此版本会被修改,以便每个顺序都放置在请求的标头中的 xsd:base64binary 值。标头定义为来自 widgetKey 消息的 keyVal 部分。在这种情况下,您需要添加应用程序逻辑来创建标头,因为它不是输入或输出消息的一部分。

例 7.4. 使用 SOAP Header 的 SOAP 1.2 绑定

<?xml version="1.0" encoding="UTF-8"?>
<definitions name="widgetOrderForm.wsdl"
    targetNamespace="http://widgetVendor.com/widgetOrderForm"
    xmlns="http://schemas.xmlsoap.org/wsdl/"
    xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
    xmlns:tns="http://widgetVendor.com/widgetOrderForm"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:xsd1="http://widgetVendor.com/types/widgetTypes"
    xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">

<types>
  <schema targetNamespace="http://widgetVendor.com/types/widgetTypes"
           xmlns="http://www.w3.org/2001/XMLSchema"
           xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
    <element name="keyElem" type="xsd:base64Binary"/>
  </schema>
</types>

<message name="widgetOrder">
  <part name="numOrdered" type="xsd:int"/>
</message>
<message name="widgetOrderBill">
  <part name="price" type="xsd:float"/>
</message>
<message name="badSize">
  <part name="numInventory" type="xsd:int"/>
</message>
<message name="widgetKey">
  <part name="keyVal" element="xsd1:keyElem"/>
</message>

<portType name="orderWidgets">
  <operation name="placeWidgetOrder">
    <input message="tns:widgetOrder" name="order"/>
    <output message="tns:widgetOrderBill" name="bill"/>
    <fault message="tns:badSize" name="sizeFault"/>
  </operation>
</portType>

<binding name="orderWidgetsBinding" type="tns:orderWidgets">
  <soap12:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <operation name="placeWidgetOrder">
      <soap12:operation soapAction="" style="document"/>
      <input name="order">
        <soap12:body use="literal"/>
        <soap12:header message="tns:widgetKey" part="keyVal"/>
      </input>
      <output name="bill">
        <soap12:body use="literal"/>
        <soap12:header message="tns:widgetKey" part="keyVal"/>
      </output>
      <fault name="sizeFault">
        <soap12:body use="literal"/>
      </fault>
  </operation>
</binding>
...
</definitions>

您可以修改 例 7.4 “使用 SOAP Header 的 SOAP 1.2 绑定” 以便标头值是输入和输出信息的一部分,如 例 7.5 “带有 SOAP 标头的 orderWidgets 的 SOAP 1.2 绑定” 所示。在这种情况下 keyVal 是输入和输出消息的一部分。在 soap12:body 元素中,part 属性指定该 keyVal 不应插入到正文中。但是,它将插入到标头中。

例 7.5. 带有 SOAP 标头的 orderWidgets 的 SOAP 1.2 绑定

<?xml version="1.0" encoding="UTF-8"?>
<definitions name="widgetOrderForm.wsdl"
    targetNamespace="http://widgetVendor.com/widgetOrderForm"
    xmlns="http://schemas.xmlsoap.org/wsdl/"
    xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
    xmlns:tns="http://widgetVendor.com/widgetOrderForm"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:xsd1="http://widgetVendor.com/types/widgetTypes"
    xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">

<types>
  <schema targetNamespace="http://widgetVendor.com/types/widgetTypes"
           xmlns="http://www.w3.org/2001/XMLSchema"
           xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
    <element name="keyElem" type="xsd:base64Binary"/>
  </schema>
</types>

<message name="widgetOrder">
  <part name="numOrdered" type="xsd:int"/>
  <part name="keyVal" element="xsd1:keyElem"/>
</message>
<message name="widgetOrderBill">
  <part name="price" type="xsd:float"/>
  <part name="keyVal" element="xsd1:keyElem"/>
</message>
<message name="badSize">
  <part name="numInventory" type="xsd:int"/>
</message>

<portType name="orderWidgets">
  <operation name="placeWidgetOrder">
    <input message="tns:widgetOrder" name="order"/>
    <output message="tns:widgetOrderBill" name="bill"/>
    <fault message="tns:badSize" name="sizeFault"/>
  </operation>
</portType>

<binding name="orderWidgetsBinding" type="tns:orderWidgets">
  <soap12:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <operation name="placeWidgetOrder">
      <soap12:operation soapAction="" style="document"/>
      <input name="order">
        <soap12:body use="literal" parts="numOrdered"/>
        <soap12:header message="tns:widgetOrder" part="keyVal"/>
      </input>
      <output name="bill">
        <soap12:body use="literal" parts="bill"/>
        <soap12:header message="tns:widgetOrderBill" part="keyVal"/>
      </output>
      <fault name="sizeFault">
        <soap12:body use="literal"/>
      </fault>
  </operation>
</binding>
...
</definitions>

第 8 章 使用 SOAP 使用附件发送二进制数据

摘要

SOAP 附加功能提供了作为 SOAP 消息的一部分发送二进制数据的机制。将 SOAP 与附件一起使用需要将您的 SOAP 消息定义为 MIME 多部件消息。

概述

SOAP 消息通常不包含二进制数据。但是,W3C SOAP 1.1 规范允许使用 MIME 多部件/相关消息在 SOAP 消息中发送二进制数据。使用带有附件的 SOAP 调用这一技术。SOAP 附加在 W3C 的 SOAP 消息及附件 》中定义。

命名空间

用于定义 MIME 多部件/相关消息的 WSDL 扩展在命名空间 http://schemas.xmlsoap.org/wsdl/mime/ 中定义。

在下面的讨论中,假设此命名空间带有 mime 的前缀。设置此选项的 WSDL 定义 元素中的条目显示在 例 8.1 “合同中的 MIME 命名空间规格” 中。

例 8.1. 合同中的 MIME 命名空间规格

xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"

更改消息绑定

在默认的 SOAP 绑定中,输入、输出和错误 元素的第一个子元素是描述 SOAP 消息正文的 soap:body 元素,表示数据。将 SOAP 与附件一起使用时,soap:body 元素将被 mime:multipartRelated 元素替代。

注意

WSDL 不支持 对故障 消息使用 mime:multipartRelated

mime:multipartRelated 元素告知 Apache CXF,消息正文是可能包含二进制数据的多部分消息。元素的内容定义消息及其内容的部分。MIME:multipartRelated 元素包含一个或多个 mime:part 元素,用于描述消息的各部分。

第一个 mime:part 元素必须包含 soap:body 元素,它们通常出现在默认的 SOAP 绑定中。剩余的 mime:part 元素定义消息中发送的附件。

描述 MIME 多部件消息

使用 mime:multipartated 元素(包含 mime:part 元素)介绍了 MIME 多部件消息。要完全描述 MIME 多部件的信息,您必须执行以下操作:

  1. 在您将作为 MIME 多部件消息的输入或输出消息内,添加 mime:mulipartRelated 元素作为保护消息的第一个子元素。
  2. mime:part 子元素添加到 mime:multipartRelated 元素,并将其 name 属性设置为唯一字符串。
  3. 添加 soap:body 元素作为 mime:part 元素的子项,并相应地设置其属性。

    注意

    如果合同有默认的 SOAP 绑定,您可以将来自默认绑定中对应的消息中的 soap:body 元素复制到 MIME 多部分消息。

  4. 将另一个 mime:part 子元素添加到 mime:multipartReleated 元素,并将其 name 属性设置为唯一字符串。
  5. mime:content 子元素添加到 mime:part 元素以描述消息中此部分的内容。

    要完全描述 MIME 消息部分的内容: mime:content 元素具有以下属性:

    表 8.1. MIME:内容 属性

    属性描述 +

    part

    指定来自父消息定义中的 WSDL 消息 部分 的名称,该消息作为放置在线路上的 MIME 多部分消息的内容。

    +

    type

    此消息中数据的 MIME 类型。MIME 类型定义为类型,使用语法类型/类型来定义。

    +

    有多个预定义的 MIME 类型,如 image/jpegtext/plain。MIME 类型由互联网编号分配机构(IANA)维护,在 多用途 Internet 邮件扩展(MIME)形式中详细介绍:互联网消息正文和 多用途 Internet 邮件扩展(MIME)第 2 部分:媒体类型

    +

  6. 对于每个额外的 MIME 部分,重复步骤 [i303819][i303821]

示例

例 8.2 “使用带有附件的 SOAP 的合同” 显示 WSDL 片段定义以 JPEG 格式存储 Xrays 的服务。镜像数据 xRay 作为 xsd:base64binary 存储,并打包成 MIME 多部件消息的第二个部分 imageData。作为 SOAP 正文的一部分,输入消息的其余两个部分( patientNamepatientNumber 是 MIME 多部件)。

例 8.2. 使用带有附件的 SOAP 的合同

<?xml version="1.0" encoding="UTF-8"?>
<definitions name="XrayStorage"
    targetNamespace="http://mediStor.org/x-rays"
    xmlns="http://schemas.xmlsoap.org/wsdl/"
    xmlns:tns="http://mediStor.org/x-rays"
    xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">

  <message name="storRequest">
    <part name="patientName" type="xsd:string"/>
    <part name="patientNumber" type="xsd:int"/>
    <part name="xRay" type="xsd:base64Binary"/>
  </message>
  <message name="storResponse">
    <part name="success" type="xsd:boolean"/>
  </message>

  <portType name="xRayStorage">
    <operation name="store">
      <input message="tns:storRequest" name="storRequest"/>
      <output message="tns:storResponse" name="storResponse"/>
    </operation>
  </portType>

  <binding name="xRayStorageBinding" type="tns:xRayStorage">
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
      <operation name="store">
      <soap:operation soapAction="" style="document"/>
      <input name="storRequest">
        <mime:multipartRelated>
          <mime:part name="bodyPart">
            <soap:body use="literal"/>
          </mime:part>
          <mime:part name="imageData">
            <mime:content part="xRay" type="image/jpeg"/>
          </mime:part>
        </mime:multipartRelated>
      </input>
      <output name="storResponse">
        <soap:body use="literal"/>
      </output>
    </operation>
  </binding>

  <service name="xRayStorageService">
    <port binding="tns:xRayStorageBinding" name="xRayStoragePort">
      <soap:address location="http://localhost:9000"/>
    </port>
  </service>
</definitions>

第 9 章 使用 SOAP MTOM 发送二进制数据

摘要

SOAP 消息传输优化机制(MTOM)将 SOAP 替换为附件作为 XML 消息的一部分发送二进制数据的机制。将 MTOM 与 Apache CXF 搭配使用需要把正确的模式类型添加到服务的合同中,并启用 MTOM 优化。

9.1. MTOM 概述

SOAP 消息传输优化机制(MTOM)指定作为 SOAP 消息的一部分发送二进制数据的优化方法。与 SOAP 与附件不同,MTOM 需要使用 XML 二进制优化打包(XOP)软件包来传输二进制数据。使用 MTOM 发送二进制数据并不需要在 SOAP 绑定中完全定义 MIME 多部件/Related 消息。但是,这样做需要您执行以下操作:

  1. 您要发送的数据添加注解。

    您可以注解 WSDL 或实施数据的 Java 类。

  2. 启用 运行时的 MTOM 支持。

    这可以通过编程方式或通过配置来完成。

  3. 作为 附件传输的数据开发数据处理程序。

    注意

    开发 数据处理程序已超出本书范畴。

9.2. 使用 MTOM 注解数据类型

概述

在 WSDL 中,当定义用于传输二进制数据的数据类型时,如镜像文件或声音文件,您可以定义类型为 xsd:base64Binary 数据的元素。默认情况下,任何类型为 xsd:base64Binary 的元素都会生成使用 MTOM 进行序列化的 byte[]。但是,代码生成器的默认行为不会充分利用序列化。

要充分利用 MTOM,您必须添加注解到服务的 WSDL 文档或用于实施二进制数据结构的 JAXB 类。将注解添加到 WSDL 文档中会强制代码生成器为二进制数据生成流传输数据处理程序。标注 JAXB 类涉及指定正确内容类型,并可能涉及更改包含二进制数据的字段的类型规格。

先 WSDL

例 9.1 “MTOM 信息” 显示 WSDL 文档,它使用一条消息,其中包含一个字符串字段、一个整数字段和二进制字段。二进制文件字段旨在承载大镜像文件,因此不适合将其作为普通 SOAP 消息的一部分进行发送。

例 9.1. MTOM 信息

<?xml version="1.0" encoding="UTF-8"?>
<definitions name="XrayStorage"
    targetNamespace="http://mediStor.org/x-rays"
    xmlns="http://schemas.xmlsoap.org/wsdl/"
    xmlns:tns="http://mediStor.org/x-rays"
    xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
    xmlns:xsd1="http://mediStor.org/types/"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">

  <types>
    <schema targetNamespace="http://mediStor.org/types/"
            xmlns="http://www.w3.org/2001/XMLSchema">
      <complexType name="xRayType">
        <sequence>
          <element name="patientName" type="xsd:string" />
          <element name="patientNumber" type="xsd:int" />
          <element name="imageData" type="xsd:base64Binary" />
        </sequence>
      </complexType>
      <element name="xRay" type="xsd1:xRayType" />
    </schema>
  </types>

  <message name="storRequest">
    <part name="record" element="xsd1:xRay"/>
  </message>
  <message name="storResponse">
    <part name="success" type="xsd:boolean"/>
  </message>

  <portType name="xRayStorage">
    <operation name="store">
      <input message="tns:storRequest" name="storRequest"/>
      <output message="tns:storResponse" name="storResponse"/>
    </operation>
  </portType>

  <binding name="xRayStorageSOAPBinding" type="tns:xRayStorage">
    <soap12:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <operation name="store">
      <soap12:operation soapAction="" style="document"/>
      <input name="storRequest">
        <soap12:body use="literal"/>
      </input>
      <output name="storResponse">
        <soap12:body use="literal"/>
      </output>
    </operation>
  </binding>
  ...
</definitions>

如果要使用 MTOM 将消息的二进制部分作为优化的附件发送,您必须将 xmime:expectedContentTypes 属性添加到包含二进制数据的元素中。此属性在 http://www.w3.org/2005/05/xmlmime 命名空间中定义,并指定该元素预期包含的 MIME 类型。您可以指定一个以逗号分隔的 MIME 类型列表。此属性的设置会改变代码生成器如何为数据创建 JAXB 类。对于大多数 MIME 类型,代码生成器会创建一个 DataHandler。某些 MIME 类型(如镜像的那些类型)定义了映射映射。

对于大多数使用,您可以指定 application/octet-stream

例 9.2 “MTOM 的二进制数据” 显示如何使用 MTOM 从 例 9.1 “MTOM 信息” 修改 xRayType

例 9.2. MTOM 的二进制数据

...
  <types>
    <schema targetNamespace="http://mediStor.org/types/"
            xmlns="http://www.w3.org/2001/XMLSchema"
            xmlns:xmime="http://www.w3.org/2005/05/xmlmime">
      <complexType name="xRayType">
        <sequence>
          <element name="patientName" type="xsd:string" />
          <element name="patientNumber" type="xsd:int" />
          <element name="imageData" type="xsd:base64Binary"
                   xmime:expectedContentTypes="application/octet-stream"/>
        </sequence>
      </complexType>
      <element name="xRay" type="xsd1:xRayType" />
    </schema>
  </types>
...

xRayType 生成的 JAXB 类不再包含 字节[]。相反,代码生成器会看到 xmime:expectedContentTypes 属性,并为 imageData 字段生成 DataHandler。

注意

您不需要更改 绑定 元素以使用 MTOM。当发送数据时,运行时会进行适当的更改。

Java 第一

如果您正在进行 Java 首个开发,您可以通过执行以下操作使 JAXB 类 MTOM 准备好:

  1. 确保包含二进制数据的字段是 DataHandler。
  2. @XmlMimeType() 注解添加到包含您要作为 MTOM 附加数据的字段。

例 9.3 “用于 MTOM 的 JAXB 类” 显示为使用 MTOM 标注的 JAXB 类。

例 9.3. 用于 MTOM 的 JAXB 类

@XmlType
public class XRayType {
    protected String patientName;
    protected int patientNumber;
    @XmlMimeType("application/octet-stream")
    protected DataHandler imageData;
  ...
}

9.3. 启用 MTOM

默认情况下,Apache CXF 运行时不会启用 MTOM 支持。它将所有二进制数据作为普通 SOAP 消息的一部分或作为未优化的附件发送。您可以以编程方式或使用配置来激活 MTOM 支持。

9.3.1. 使用 JAX-WS API

概述

服务供应商和消费者都必须启用 MTOM 优化功能。JAX-WS API 为每种类型端点提供不同的机制。

服务供应商

如果您使用 JAX-WS API 发布您的服务提供商,您可以启用运行时的 MTOM 支持,如下所示:

  1. 访问您发布的服务的 Endpoint 对象。

    访问 Endpoint 对象的最简单方法是在发布端点时。更多信息请参阅 第 31 章 发布服务

  2. 使用 getBinding() 方法从 Endpoint 获取 SOAP 绑定,如 例 9.4 “从端点获取 SOAP Binding” 所示。

    例 9.4. 从端点获取 SOAP Binding

    // Endpoint ep is declared previously
    SOAPBinding binding = (SOAPBinding)ep.getBinding();

    您必须将返回的绑定对象转换为 SOAPBinding 对象,以访问 MTOM 属性。

  3. 使用绑定的 setMTOMEnabled() 方法将绑定的 MTOM enabled 属性设为 true,如 例 9.5 “设置服务提供商的 MTOM Enabled Property” 所示。

    例 9.5. 设置服务提供商的 MTOM Enabled Property

    binding.setMTOMEnabled(true);

消费者

要让 MTOM 启用 JAX-WS 消费者,您必须执行以下操作:

  1. 将使用者的代理转换为 BindingProvider 对象。

    有关获取消费者代理的详情,请参考 第 25 章 在没有 WSDL 合同的情况下开发消费者第 28 章 从 WSDL 合同开发消费者

  2. 使用 getBinding() 方法从 BindingProvider 获取 SOAP 绑定,如 例 9.6 “从绑定 Provider获取 SOAP 绑定” 所示。

    例 9.6. 从绑定 Provider获取 SOAP 绑定

    // BindingProvider bp declared previously
    SOAPBinding binding = (SOAPBinding)bp.getBinding();
  3. 使用绑定的 setMTOMEnabled() 方法将绑定 MTOM enabled 属性设为 true,如 例 9.7 “设置 Consumer 的 MTOM Enabled Property” 所示。

    例 9.7. 设置 Consumer 的 MTOM Enabled Property

    binding.setMTOMEnabled(true);

9.3.2. 使用配置

概述

如果使用 XML 发布您的服务,比如部署到容器时,您可以在端点的配置文件中启用端点的 MTOM 支持。有关配置端点的详情请参考 第 IV 部分 “配置 Web 服务端点”

流程

MTOM 属性在您的端点的 jaxws:endpoint 元素内设置。启用 MTOM 执行以下操作:

  1. jaxws:property 子元素添加到端点的 jaxws:endpoint 元素。
  2. jaxws:property 元素 添加条目 子元素。
  3. entry 元素的 key 属性设置为启用了 mtom-enabled
  4. entry 元素的 value 属性设置为 true

示例

例 9.8 “配置启用 MTOM” 显示启用 MTOM 的端点。

例 9.8. 配置启用 MTOM

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:jaxws="http://cxf.apache.org/jaxws"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
                           http://cxf.apache.org/jaxws http://cxf.apache.org/schema/jaxws.xsd">

  <jaxws:endpoint id="xRayStorage"
                  implementor="demo.spring.xRayStorImpl"
                  address="http://localhost/xRayStorage">
    <jaxws:properties>
      <entry key="mtom-enabled" value="true"/>
    </jaxws:properties>
  </jaxws:endpoint>
</beans>

第 10 章 使用 XML 文档

摘要

纯 XML 有效负载格式提供了 SOAP 绑定的一种替代方式,允许服务使用直接 XML 文档来交换数据,而无需增加 SOAP 信封。

XML 绑定命名空间

用于描述 XML 格式绑定的扩展在命名空间 http://cxf.apache.org/bindings/xformat 中定义。Apache CXF 工具使用前缀 xformat 来代表 XML 绑定扩展。在您的合同中添加以下行:

xmlns:xformat="http://cxf.apache.org/bindings/xformat"

手动编辑

将接口映射到纯 XML 有效负载格式,请执行以下操作:

  1. 添加命名空间声明,使其包含定义 XML 绑定的扩展。请参阅 “XML 绑定命名空间”一节
  2. 在您的合同中添加标准 WSDL 绑定 元素以存放 XML 绑定,为绑定指定 一个唯一名称,并指定代表接口绑定的 WSDL portType 元素的名称。
  3. xformat: binding 子元素添加到绑定元素中,以标识消息作为纯 XML 文档处理,而无需 SOAP envelopes。
  4. 另外,还可将 xformat:binding 元素的 rootNode 属性设置为有效的 QName。如需有关 rootNode 属性影响的更多信息,请参阅 “线路上的 XML 消息”一节
  5. 对于绑定接口中定义的每个操作,添加标准的 WSDL 操作 元素来保存操作消息的绑定信息。
  6. 对于添加到绑定的每个操作,添加 输入输出和错误 子元素来代表操作使用的消息。

    这些元素对应于逻辑操作接口定义中定义的消息。

  7. (可选)添加带有有效 rootNode 属性的 xformat:body 元素到添加的 输入输出fault 元素,以覆盖绑定级别设置的 rootNode 的值。
注意

如果有任何消息没有相关部分,例如返回无效操作的输出消息,则必须为消息设置 rootNode 属性,以确保 wire 上写入的消息是有效的,但为空,XML 文档。

线路上的 XML 消息

当您指定接口的信息要作为 XML 文档(没有 SOAP 信封)时,您必须小心谨慎,以确保当它们在线路上写入时,您的消息形成有效的 XML 文档。您还需要确保接收 XML 文档的非 Apache CXF 参与者了解 Apache CXF 生成的消息。

解决了这两个问题的简单方法是,使用 global xformat:binding 元素上的可选 rootNode 属性或单个消息的 xformat:body 元素。rootNode 属性指定作为 Apache CXF 生成的 XML 文档的根节点元素的 QName。如果没有设置 rootNode 属性时,在使用 doc 风格消息时,Apache CXF 将消息部分的 root 元素用作根元素,或者使用消息部分名称作为 rpc 样式消息时的 root 元素。

例如,如果 rootNode 属性未设置 例 10.1 “有效的 XML Binding Message” 中定义的消息,则会使用根元素 lineNumber 生成 XML 文档。

例 10.1. 有效的 XML Binding Message

<type ... >
  ...
  <element name="operatorID" type="xsd:int"/>
  ...
</types>
<message name="operator">
  <part name="lineNumber" element="ns1:operatorID"/>
</message>

对于一个部分的消息,Apache CXF 将始终生成有效的 XML 文档,即使未设置 rootNode 属性。但是,例 10.2 “无效的 XML Binding 消息” 中的信息会生成无效的 XML 文档。

例 10.2. 无效的 XML Binding 消息

<types>
  ...
  <element name="pairName" type="xsd:string"/>
  <element name="entryNum" type="xsd:int"/>
  ...
</types>

<message name="matildas">
  <part name="dancing" element="ns1:pairName"/>
  <part name="number" element="ns1:entryNum"/>
</message>

如果没有 XML 绑定中指定的 rootNode 属性,Apache CXF 将生成与 例 10.3 “无效的 XML 文档” 中定义的消息类似的 XML 文档。例 10.2 “无效的 XML Binding 消息”生成的 XML 文档无效,因为它有两个根元素: pairNameentryNum

例 10.3. 无效的 XML 文档

<pairName>
  Fred&Linda
</pairName>
<entryNum>
  123
</entryNum>

如果您设置了 rootNode 属性,如 例 10.4 “带有 rootNode 集的 XML Binding” Apache CXF 所示,则会将元素嵌套到指定的根元素中。在本例中,为整个绑定定义了 rootNode 属性,并指定根元素将命名为 entrants。

例 10.4. 带有 rootNode 集的 XML Binding

<portType name="danceParty">
  <operation name="register">
    <input message="tns:matildas" name="contestant"/>
  </operation>
</portType>

<binding name="matildaXMLBinding" type="tns:dancingMatildas">
  <xmlformat:binding rootNode="entrants"/>
  <operation name="register">
    <input name="contestant"/>
    <output name="entered"/>
</binding>

从输入消息生成的 XML 文档类似于 例 10.5 “使用 rootNode 属性生成的 XML 文档”。请注意,XML 文档现在只有一个根元素。

例 10.5. 使用 rootNode 属性生成的 XML 文档

<entrants>
  <pairName>
    Fred&Linda
  <entryNum>
    123
  </entryNum>
</entrants>

覆盖绑定的 rootNode 属性设置

您还可以使用消息中的 xformat:body 元素在消息绑定中为每个单独消息设置 rootNode 属性,或者覆盖特定消息的全局设置。例如,如果您想要 例 10.4 “带有 rootNode 集的 XML Binding” 中定义的输出消息与输入消息不同的 root 元素,您可以覆盖绑定的根元素,如 例 10.6 “使用 xformat:body 所示。

例 10.6. 使用 xformat:body

<binding name="matildaXMLBinding" type="tns:dancingMatildas">
  <xmlformat:binding rootNode="entrants"/>
  <operation name="register">
    <input name="contestant"/>
    <output name="entered">
      <xformat:body rootNode="entryStatus" />
    </output>
  </operation>
</binding>

部分 III. Web 服务传输

这部分论述了如何将 Apache CXF 传输添加到 WSDL 文档。

第 11 章 了解 WSDL 中如何定义端点

摘要

端点代表实例化服务。它们通过将绑定和用于公开端点的网络详情进行定义。

概述

端点可以被视为服务的物理清单。它结合了一个绑定,指定服务所使用的逻辑数据的物理表示,以及一组网络详细信息,它们用于定义用于使服务可以被其他端点联系的物理连接详情。

注意

CXF 提供程序是 CXF 消费者的服务器,对应于客户端。如果您在路由中使用 CXF(camel-cxf)组件作为起始端点,则端点既是 Camel 消费者和 CXF 供应商。如果您使用 Camel CXF 组件,作为路由中的结束端点,则端点既是 Camel 制作者和 CXF 消费者。

端点和服务

与绑定只能映射单个接口一样,端点只能映射到单个服务。但是,服务可以被任意数量的端点清单。例如,您可以定义一个由四个不同端点清单的票据销售服务。但是,您不能有一个端点,它同时引用了一个 ticket 销售服务和一个小部件销售服务。

WSDL 元素

端点通过 WSDL 服务 元素和 WSDL 端口 元素的组合在合同中定义。service 元素是相关端口元素 的集合端口 元素定义实际的端点。

WSDL 服务 元素具有一个属性,名称,用于指定唯一名称。service 元素用作相关端口元素集合的父 元素。WSDL 不规范与 端口 元素相关。您可以以任何方式 将端口 元素关联。

WSDL 端口 元素具有 binding 属性,用于指定端点使用的绑定,是 wsdl:binding 元素的引用。它还包括 name 属性,这是在所有端口之间提供唯一名称的必需属性。port 元素是元素的父元素,用于指定端点使用的实际传输详细信息。以下部分介绍了用来指定传输详情的元素。

在合同中添加端点

Apache CXF 提供命令行工具,可为预定义的服务接口和绑定组合生成端点。

该工具将为您添加正确的元素到您的合同中。但是,建议您了解在定义端点工作中使用的不同传输方式。

您还可以使用任何文本编辑器在合同中添加端点。当您手动编辑合同时,您需要确保合同有效。

支持的传输

端点定义使用为每个传输定义的扩展 Apache CXF 进行构建。这包括以下传输:

  • HTTP
  • CORBA
  • Java 消息传递服务

第 12 章 使用 HTTP

摘要

HTTP 是 Web 的底层传输。它为端点之间通信提供了一个标准化、强大且灵活的平台。由于这些因素是大多数 WS-* 规范的假设传输,并且是 RESTful 架构不可或缺的。

12.1. 添加基本 HTTP 端点

备选 HTTP 运行时

Apache CXF 支持以下替代 HTTP 运行时实施:

Netty HTTP URL

通常,HTTP 端点使用在类路径(Undertow 或 Netty)中包含哪些 HTTP 运行时。但是,如果 classpath 中同时包含 Undertow 运行时和 Netty 运行时,则需要在希望使用 Netty 运行时而明确指定,因为默认情况下将使用 Undertow 运行时。

如果 classpath 上有多个 HTTP 运行时,您可以通过指定要以下格式的端点 URL 来选择 Undertow 运行时:

netty://http://RestOfURL

有效负载类型

根据您使用的有效负载格式,可通过三种方式指定 HTTP 端点的地址。

  • SOAP 1.1 使用标准化 soap:address 元素。
  • SOAP 1.2 使用 soap12:address 元素。
  • 所有其他有效负载格式都使用 http:address 元素。
注意

从 Camel 2.16.0 发行版本,Apache Camel CXF Payload 支持开箱即用流缓存。

SOAP 1.1

当您通过 HTTP 发送 SOAP 1.1 消息时,必须使用 SOAP 1.1 地址 元素来指定端点的地址。它有一个属性( 位置 ),用于指定端点的地址为 URL。SOAP 1.1 地址 元素在命名空间 http://schemas.xmlsoap.org/wsdl/soap/ 中定义。

例 12.1 “SOAP 1.1 端口元素” 显示用于通过 HTTP 发送 SOAP 1.1 消息 的端口 元素。

例 12.1. SOAP 1.1 端口元素

<definitions ...
             xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" ...>
  ...
  <service name="SOAP11Service">
    <port binding="SOAP11Binding" name="SOAP11Port">
      <soap:address location="http://artie.com/index.xml">
    </port>
  </service>
  ...
<definitions>

SOAP 1.2

当您通过 HTTP 发送 SOAP 1.2 消息时,必须使用 SOAP 1.2 地址 元素来指定端点的地址。它有一个属性( 位置 ),用于指定端点的地址为 URL。SOAP 1.2 地址 元素在命名空间 http://schemas.xmlsoap.org/wsdl/soap12/ 中定义。

例 12.2 “SOAP 1.2 端口元素” 显示用于通过 HTTP 发送 SOAP 1.2 消息 的端口 元素。

例 12.2. SOAP 1.2 端口元素

<definitions ...
             xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" ... >
  <service name="SOAP12Service">
    <port binding="SOAP12Binding" name="SOAP12Port">
      <soap12:address location="http://artie.com/index.xml">
    </port>
  </service>
  ...
</definitions>

其他消息类型

当您的消息映射到 SOAP 以外的任何有效负载格式时,您必须使用 HTTP 地址 元素来指定端点的地址。它有一个属性( 位置 ),用于指定端点的地址为 URL。HTTP 地址 元素在命名空间 http://schemas.xmlsoap.org/wsdl/http/ 中定义。

例 12.3 “HTTP 端口元素” 显示用于发送 XML 消息 的端口 元素。

例 12.3. HTTP 端口元素

<definitions ...
             xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" ... >
  <service name="HTTPService">
    <port binding="HTTPBinding" name="HTTPPort">
      <http:address location="http://artie.com/index.xml">
    </port>
  </service>
  ...
</definitions>

12.2. 配置一个 Consumer

12.2.1. HTTP Consumer 端点的机制

HTTP 使用者端点可指定多个 HTTP 连接属性,包括端点是否自动接受重定向响应,端点是否可以使用块,无论端点是否会请求一个 keep-alive,以及端点如何与代理交互。除了 HTTP 连接属性外,HTTP 消费者端点还可指定它的安全性。

消费者端点可使用两种机制配置:

12.2.2. 使用配置

命名空间

用于配置 HTTP 消费者端点的元素在命名空间 http://cxf.apache.org/transports/http/configuration 中定义。通常会使用前缀 http-conf 来引用。要使用 HTTP 配置元素,您必须将 例 12.4 “HTTP Consumer 配置命名空间” 中显示的行添加到端点配置文件的 Bean 元素中。另外,您必须将配置元素的命名空间添加到 xsi:schemaLocation 属性。

例 12.4. HTTP Consumer 配置命名空间

<beans ...
       xmlns:http-conf="http://cxf.apache.org/transports/http/configuration"
       ...
       xsi:schemaLocation="...
                           http://cxf.apache.org/transports/http/configuration
                              http://cxf.apache.org/schemas/configuration/http-conf.xsd
                          ...">

Undertow 运行时或 Netty 运行时

您可以使用 http-conf 命名空间中的元素配置 Undertow 运行时或 Netty 运行时。

conduit 元素

您可以使用 http-conf:conduit 元素及其子项配置 HTTP 消费者端点。http-conf:conduit 元素采用单个属性 name,用于指定与端点对应的 WSDL 端口 元素。name 属性的值为 portQName'.http-conduit'。例 12.5 “http-conf:conduit Element” 显示 http-conf:conduit 元素,用于在端点的目标命名空间中为端点添加由 WSDL 片段 &lt ;port binding="widgetSOAPBinding" name="widgetSOAPPort > 指定的端点配置。

例 12.5. http-conf:conduit Element

...
  <http-conf:conduit name="{http://widgets/widgetvendor.net}widgetSOAPPort.http-conduit">
    ...
  </http-conf:conduit>
...

http-conf:conduit 元素具有指定配置信息的子元素。表 12.1 “用于配置 HTTP 消费者端点的元素” 中描述的它们。

表 12.1. 用于配置 HTTP 消费者端点的元素

元素描述

http-conf:client

指定 HTTP 连接属性,如超时、keep-alive 请求、内容类型等。请参阅 “client 元素”一节

HTTP-conf:authorization

指定配置端点使用的基本身份验证方法的参数。首选方法是提供 http-conf:basicAuthSupplier 对象。

HTTP-conf:proxyAuthorization

指定用于针对传出 HTTP 代理服务器配置基本身份验证的参数。

http-conf:tlsClientParameters

指定用于配置 SSL/TLS 的参数。

http-conf:basicAuthSupplier

指定提供端点使用的基本身份验证信息的 bean 参考或类名称,可以是预先选择或响应 401 HTTP 质询。

http-conf:trustDecider

指定检查 HTTP(S) URLConnection 对象的 bean 参考或类名称,以便在传输任何信息前与 HTTPS 服务供应商建立信任。

client 元素

http-conf:client 元素用于配置消费者端点的 HTTP 连接的非安全性属性。其属性(如 表 12.2 “HTTP 消费者配置属性” 所述)指定连接的属性。

表 12.2. HTTP 消费者配置属性

属性描述

ConnectionTimeout

指定在超时前,使用者尝试建立连接的时间(以毫秒为单位)。默认值为 30000

0 指定消费者继续无限期地发送请求。

ReceiveTimeout

指定使用者在超时前等待响应时间,以毫秒为单位。默认值为 30000

0 指定使用者会无限期等待。

AutoRedirect

指定消费者是否自动遵循发布的服务器重定向。默认值为 false

MaxRetransmits

指定消费者重新传输请求以满足重定向的最大次数。默认值为 -1,它指定允许无限的重新传输。

AllowChunking

指定使用者是否使用块发送请求。默认为 true,指定消费者在发送请求时使用块。

如果以下任意一个为 true,则无法使用块:

  • HTTP-conf:basicAuth Supplier 配置为预先提供凭证。
  • AutoRedirect 设置为 true

在这两种情况下,AllowChunking 的值会被忽略,并且不允许使用块。

accept

指定消费者准备好处理的介质类型。该值用作 HTTP Accept 属性的值。属性的值通过多用途互联网邮件扩展(MIME)类型来指定。

AcceptLanguage

指定接收响应的目的(例如,美国英语)。该值用作 HTTP AcceptLanguage 属性的值。

语言标签由国际机构用于标准(ISO)监管,通常通过组合语言代码(由 ISO-639 标准和国家代码确定),由 ISO-3166 标准决定,由连字符分隔。例如,en-US 代表美国英语。

AcceptEncoding

指定消费者准备处理的内容编码。内容编码标签由互联网编号授权机构(IANA)监管。该值用作 HTTP AcceptEncoding 属性的值。

ContentType

指定在邮件正文中发送的数据类型。使用多用途互联网邮件扩展(MIME)类型来指定介质类型。该值用作 HTTP ContentType 属性的值。默认为 text/xml

对于 Web 服务,应将其设置为 text/xml。如果客户端将 HTML 表单数据发送到 CGI 脚本,则应该将其设置为 application/x-www-form-url 编码的。如果 HTTP POST 请求绑定到固定有效负载格式(而不是 SOAP),则内容类型通常会设置为 application/octet-stream

主机

指定正在调用请求的资源的互联网主机和端口号。该值用作 HTTP Host 属性的值。

通常不需要此属性。只有某些 DNS 场景或应用程序设计才需要它。例如,它指示客户端为集群的首选主机(即,用于虚拟服务器映射到同一互联网协议(IP)地址)。

连接

指定在每个请求/响应对话框后是否保持打开或关闭特定连接。有两个有效的值:

  • keep-Alive - 指定使用者需要在初始请求/响应序列后保持打开的连接。如果服务器尊重,连接将保持打开,直到消费者将其关闭为止。
  • 关闭(默认)- 指定到服务器的连接在每个请求/响应序列后关闭。

CacheControl

指定由涉及的链中必须遵循的行为的指令,增加从消费者到服务提供商的请求。请参阅 第 12.2.4 节 “消费者缓存控制指令”

Cookie

指定要随所有请求发送的静态 Cookie。

BrowserType

指定请求源自的浏览器的信息。在来自 World Wide Web Consortium(W3C)的 HTTP 规格中,也称为 user-agent。某些服务器根据发送请求的客户端进行优化。

请参阅

指定指示消费者在特定服务上发出请求的资源的 URL。该值用作 HTTP 推荐 属性值

当一个请求是浏览器用户的结果时,可通过单击超链接而不是输入 URL 时使用此 HTTP 属性。这可允许服务器根据以前的任务流优化处理,并生成到资源的链接列表,以进行日志记录、优化缓存、过期或错误输入的链接等。但是,它通常用于 Web 服务应用程序。

如果 AutoRedirect 属性设为 true,并且请求将被重定向,则引用 属性中指定的任何值都会被覆盖。HTTP 推荐属性的值设置为重定向消费者的原始请求的服务的 URL。

DecoupledEndpoint

指定通过单独的 provider→consumer 连接接收响应的分离端点的 URL。有关使用分离端点的详情请参考 第 12.6 节 “在拒绝模式中使用 HTTP 传输”

您必须配置消费者端点,以便使用 WS-Addressing 进行分离端点。

ProxyServer

指定路由请求的代理服务器的 URL。

ProxyServerPort

指定路由请求的代理服务器的端口号。

ProxyServerType

指定用于路由请求的代理服务器的类型。有效值为:

  • HTTP(默认)
  • SOCKS

示例

例 12.6 “HTTP 消费者端点配置” 显示 HTTP 消费者端点的配置,该端点需要在请求之间保持与提供程序打开的连接,每个调用只会重新传输请求一次,并且无法使用块流。

例 12.6. HTTP 消费者端点配置

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:http-conf="http://cxf.apache.org/transports/http/configuration"
       xsi:schemaLocation="http://cxf.apache.org/transports/http/configuration
                             http://cxf.apache.org/schemas/configuration/http-conf.xsd
                           http://www.springframework.org/schema/beans
                             http://www.springframework.org/schema/beans/spring-beans.xsd">

  <http-conf:conduit name="{http://apache.org/hello_world_soap_http}SoapPort.http-conduit">
    <http-conf:client Connection="Keep-Alive"
                      MaxRetransmits="1"
                      AllowChunking="false" />
  </http-conf:conduit>
</beans>

更多信息

有关 HTTP conduits 的更多信息,请参阅 第 16 章 conduits

12.2.3. 使用 WSDL

命名空间

用于配置 HTTP 消费者端点的 WSDL 扩展元素在命名空间 http://cxf.apache.org/transports/http/configuration 中定义。通常会使用前缀 http-conf 来引用。要使用 HTTP 配置元素,您必须将 例 12.7 “HTTP Consumer WSDL Element 的命名空间” 中显示的行添加到端点的 WSDL 文档 的定义 元素中。

例 12.7. HTTP Consumer WSDL Element 的命名空间

<definitions ...
       xmlns:http-conf="http://cxf.apache.org/transports/http/configuration"

Undertow 运行时或 Netty 运行时

您可以使用 http-conf 命名空间中的元素配置 Undertow 运行时或 Netty 运行时。

client 元素

http-conf:client 元素用于在 WSDL 文档中指定 HTTP 使用者的连接属性。http-conf:client 元素是 WSDL 端口 元素的子项。它具有与配置文件中使用 的客户端 元素相同的属性。属性在 表 12.2 “HTTP 消费者配置属性” 中描述。

示例

例 12.8 “WSDL 以配置 HTTP 消费者端点” 显示配置 HTTP 消费者端点的 WSDL 片段,以指定它没有与缓存交互。

例 12.8. WSDL 以配置 HTTP 消费者端点

<service ... >
  <port ... >
    <soap:address ... />
    <http-conf:client CacheControl="no-cache" />
  </port>
</service>

12.2.4. 消费者缓存控制指令

表 12.3 “HTTP-conf:客户端 缓存控制指令” 列出 HTTP 消费者支持的缓存控制指令。

表 12.3. HTTP-conf:客户端 缓存控制指令

指令行为

no-cache

缓存无法使用特定的响应来满足后续的请求,而无需首先重新使用服务器重新显示该响应。如果使用此值指定特定的响应标头字段,则限制只适用于响应中的那些标头字段。如果没有指定响应标头字段,则限制将应用到整个响应。

no-store

缓存不得存储响应的任意部分或调用它的请求的任何部分。

max-age

消费者可以接受其年龄不超过指定时间(以秒为单位)。

max-stale

使用者可接受超过其过期时间的响应。如果一个值被分配给 max-stale,它代表响应的过期时间以外的秒数,则用户仍然可以接受该响应。如果没有分配值,消费者可以接受任何年龄的过时的响应。

min-fresh

消费者希望对仍有至少指定的秒数而全新的响应。

no-transform

缓存不得修改提供程序和消费者之间的媒体类型或内容位置。

only-if-cached

缓存应只返回当前存储在缓存中的响应,而不是需要重新加载或重新验证的响应。

cache-extension

为其他缓存指令指定额外的扩展。扩展可以是信息或行为。在标准指令的上下文中指定扩展指令,以便应用程序不了解扩展指令可遵循标准指令强制的行为。

12.3. 配置服务提供商

12.3.1. HTTP 服务提供商的机制

HTTP 服务提供商端点可指定许多 HTTP 连接属性,包括是否遵守活动请求、与缓存交互的方式,以及允许它与消费者通信时所造成的错误。

可以使用两种机制配置服务供应商端点:

12.3.2. 使用配置

命名空间

用于配置 HTTP 供应商端点的元素在命名空间 http://cxf.apache.org/transports/http/configuration 中定义。通常会使用前缀 http-conf 来引用。要使用 HTTP 配置元素,您必须将 例 12.9 “HTTP Provider Configuration Namespace” 中显示的行添加到端点配置文件的 Bean 元素中。另外,您必须将配置元素的命名空间添加到 xsi:schemaLocation 属性。

例 12.9. HTTP Provider Configuration Namespace

<beans ...
       xmlns:http-conf="http://cxf.apache.org/transports/http/configuration"
       ...
       xsi:schemaLocation="...
                           http://cxf.apache.org/transports/http/configuration
                              http://cxf.apache.org/schemas/configuration/http-conf.xsd
                          ...">

Undertow 运行时或 Netty 运行时

您可以使用 http-conf 命名空间中的元素配置 Undertow 运行时或 Netty 运行时。

destination 元素

您可以使用 http-conf:destination 元素及其子项配置 HTTP 服务供应商端点。http-conf:destination 元素采用单个属性 name,用于指定与端点对应的 WSDL 端口 元素。name 属性的值采用以下形式的 portQName'.http-destination'。例 12.10 “HTTP-conf:destination Element” 显示 http-conf:destination 元素,用于为端点添加由 WSDL 片段 < port binding="widgetSOAPBinding" name="widgetSOAPPort > 指定的端点配置 http://widgets.widgetvendor.net。

例 12.10. HTTP-conf:destination Element

...
  <http-conf:destination name="{http://widgets/widgetvendor.net}widgetSOAPPort.http-destination">
    ...
  </http-conf:destination>
...

http-conf:destination 元素有多个指定配置信息的子元素。表 12.4 “用于配置 HTTP 服务提供商端点的元素” 中描述的它们。

表 12.4. 用于配置 HTTP 服务提供商端点的元素

元素描述

http-conf:server

指定 HTTP 连接属性。请参阅 “server 元素”一节

http-conf:contextMatchStrategy

指定配置用于处理 HTTP 请求的上下文匹配策略的参数。

http-conf:fixedParameterOrder

指定此目的地处理的 HTTP 请求的参数顺序是否已解决。

server 元素

http-conf:server 元素用于配置服务提供商端点 HTTP 连接的属性。其属性(如 表 12.5 “HTTP 服务提供商配置属性” 所述)指定连接的属性。

表 12.5. HTTP 服务提供商配置属性

属性描述

ReceiveTimeout

设定连接超时前服务提供程序尝试接收请求的时间长度,以毫秒为单位。默认值为 30000

0 指定供应商不会超时。

SuppressClientSendErrors

指定在收到请求时是否抛出异常。默认为 false ;遇到错误时会抛出异常。

SuppressClientReceiveErrors

指定在向消费者发送响应时是否遇到错误时是否抛出异常。默认为 false ;遇到错误时会抛出异常。

HonorKeepAlive

指定在发送响应后,服务提供商是否遵循连接是否保持打开状态。默认为 false ;忽略 keep-alive 请求。

RedirectURL

如果客户端请求的 URL 不再适合所请求的资源,则指定客户端请求应重定向到的 URL。在本例中,如果服务器响应的第一行中没有自动设置状态代码,则状态代码设置为 302,状态描述设置为 Object Moved。该值用作 HTTP RedirectURL 属性的值。

CacheControl

指定由涉及的链中必须遵循的行为的指令,由来自服务提供商的响应增加至消费者。请参阅 第 12.3.4 节 “服务提供商缓存控制指令”

ContentLocation

设置在响应中发送资源所在的 URL。

ContentType

指定在响应中发送的信息的介质类型。使用多用途互联网邮件扩展(MIME)类型来指定介质类型。该值用作 HTTP ContentType 位置的值。

ContentEncoding

指定应用于由服务提供商发送的信息应用的任何额外内容编码。内容编码标签由互联网编号授权机构(IANA)监管。可能的内容编码值包括 zip、gzip、压缩、deflate 和 identity。这个值被用作 HTTP ContentEncoding 属性的值。

内容编码的主要用途是允许使用一些编码机制(如 zip 或 gzip)压缩文档。Apache CXF 对内容编码没有验证。用户负责确保应用程序级别支持指定的内容编码。

ServerType

指定发送响应的服务器类型。使用 form program-name/version 的值,如 Apache/1.2.5

示例

例 12.11 “HTTP 服务提供商端点配置” 显示 HTTP 服务提供商端点的配置,该端点遵循保留请求并阻止所有通信错误。

例 12.11. HTTP 服务提供商端点配置

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:http-conf="http://cxf.apache.org/transports/http/configuration"
       xsi:schemaLocation="http://cxf.apache.org/transports/http/configuration
                             http://cxf.apache.org/schemas/configuration/http-conf.xsd
                           http://www.springframework.org/schema/beans
                             http://www.springframework.org/schema/beans/spring-beans.xsd">

  <http-conf:destination name="{http://apache.org/hello_world_soap_http}SoapPort.http-destination">
    <http-conf:server SuppressClientSendErrors="true"
                      SuppressClientReceiveErrors="true"
                      HonorKeepAlive="true" />
  </http-conf:destination>
</beans>

12.3.3. 使用 WSDL

命名空间

用于配置 HTTP 提供商端点的 WSDL 扩展元素在命名空间 http://cxf.apache.org/transports/http/configuration 中定义。通常会使用前缀 http-conf 来引用。要使用 HTTP 配置元素,您必须将 例 12.12 “HTTP Provider WSDL Element 的 Namespace” 中显示的行添加到端点的 WSDL 文档 的定义 元素中。

例 12.12. HTTP Provider WSDL Element 的 Namespace

<definitions ...
       xmlns:http-conf="http://cxf.apache.org/transports/http/configuration"

Undertow 运行时或 Netty 运行时

您可以使用 http-conf 命名空间中的元素配置 Undertow 运行时或 Netty 运行时。

server 元素

http-conf:server 元素用于在 WSDL 文档中指定 HTTP 服务提供商的连接属性。http-conf:server 元素是 WSDL 端口 元素的子级。它具有与配置文件中使用 的服务器 元素相同的属性。属性在 表 12.5 “HTTP 服务提供商配置属性” 中描述。

示例

例 12.13 “WSDL 以配置 HTTP 服务供应商端点” 显示 WSDL 片段,它将配置 HTTP 服务提供商端点,指定它不会与缓存交互。

例 12.13. WSDL 以配置 HTTP 服务供应商端点

<service ... >
  <port ... >
    <soap:address ... />
    <http-conf:server CacheControl="no-cache" />
  </port>
</service>

12.3.4. 服务提供商缓存控制指令

表 12.6 “HTTP-conf:服务器 缓存控制指令” 列出 HTTP 服务提供商支持的缓存控制指令。

表 12.6. HTTP-conf:服务器 缓存控制指令

指令行为

no-cache

缓存无法使用特定的响应来满足后续的请求,而无需首先重新使用服务器重新显示该响应。如果使用此值指定特定的响应标头字段,则限制只适用于响应中的那些标头字段。如果没有指定响应标头字段,则限制将应用到整个响应。

public

任何缓存都可以存储响应。

private

公共(共享)缓存无法存储响应,因为响应适合一个用户。如果使用此值指定特定的响应标头字段,则限制只适用于响应中的那些标头字段。如果没有指定响应标头字段,则限制将应用到整个响应。

no-store

缓存不得存储调用它的请求的任何部分或任何部分。

no-transform

缓存不得修改服务器与客户端之间的响应中的介质类型或位置。

must-revalidate

在后续响应中使用该条目前,缓存必须重新验证与响应相关的过期条目。

proxy-revalidate

与 must-revalidate 操作相同,但只能对共享缓存强制,并被私有未共享缓存忽略。使用这个指令时,还必须使用 public cache 指令。

max-age

客户端可以接受其年龄没有超过指定秒数的响应。

s-max-age

与 max-age 相似,但只能对共享缓存强制实施,并且被私有未共享缓存忽略。由 s-max-age 指定的年龄会覆盖由 max-age 指定的时间。当使用这个指令时,还必须使用 proxy-revalidate 指令。

cache-extension

为其他缓存指令指定额外的扩展。扩展可以是信息或行为。在标准指令的上下文中指定扩展指令,以便应用程序不了解扩展指令可遵循标准指令强制的行为。

12.4. 配置 Undertow 运行时

概述

Undertow 运行时供 HTTP 服务提供商和 HTTP 用户使用分离端点。可以配置运行时的线程池,您可以通过 Undertow 运行时设置 HTTP 服务提供商的多个安全设置。

Maven 依赖项

如果将 Apache Maven 用作构建系统,您可以通过在项目的 pom.xml 文件中包含下列依赖项,将 Undertow 运行时添加到项目中:

<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-transports-http-undertow</artifactId>
    <version>${cxf-version}</version>
</dependency>

命名空间

用于配置 Undertow 运行时的元素在命名空间 http://cxf.apache.org/transports/http-undertow/configuration 中定义。若要使用 Undertow 配置元素,您必须将 例 12.14 “Undertow 运行时配置命名空间” 中显示的行添加到端点配置文件的 Bean 元素中。在本例中,命名空间被分配了前缀 httpu。另外,您必须将配置元素的命名空间添加到 xsi:schemaLocation 属性。

例 12.14. Undertow 运行时配置命名空间

<beans ...
       xmlns:httpu="http://cxf.apache.org/transports/http-undertow/configuration"
       ...
       xsi:schemaLocation="...
                           http://cxf.apache.org/transports/http-undertow/configuration
                              http://cxf.apache.org/schemas/configuration/http-undertow.xsd
                          ...">

engine-factory 元素

httpu:engine-factory 元素是用来配置供应用使用的 Undertow 运行时的根元素。它具有单一必需属性 总线,其值是管理所配置的 Undertow 实例的 总线 名称。

注意

该值通常是 cxf,它是默认 总线实例的名称

http:engine-factory 元素有三个子项,其中包含用于配置使用 Undertow 运行时工厂实例化的 HTTP 端口的信息。子对象在 表 12.7 “配置Undertow Runtime onnectionFactoryy 的元素” 中描述。

表 12.7. 配置Undertow Runtime onnectionFactoryy 的元素

元素描述

httpu:engine

指定特定 Undertow 运行时实例的配置。请参阅 “engine 元素”一节

httpu:identifiedTLSServerParameters

指定用于保护 HTTP 服务提供商的可重复利用属性集合。它有一个属性 id,它指定可以引用该属性集的唯一标识符。

httpu:identifiedThreadingParameters

指定控制 Undertow 实例的线程池的可重复利用属性集合。它有一个属性 id,它指定可以引用该属性集的唯一标识符。

请参阅 “配置线程池”一节

engine 元素

httpu:engine 元素用于配置 Undertow 运行时的特定实例。它有两个属性( host ),它指定具有嵌入式 undertow 和端口 的全局 IP 地址,用于指定由 Undertow 实例管理的端口数量。

注意

您可以为 端口 属性指定一个 0 值。httpu:engine 元素中指定的任何线程属性设为 0, 用作未明确配置的所有 Undertow 侦听器的配置。

每个 httpu:engine 元素可以包含两个子项:一个用于配置安全属性,另一个用于配置 Undertow 实例的线程池。对于每种配置,您可以直接提供配置信息,也可以提供对父 httpu:engine-factory 元素中定义的一组配置属性的引用。

表 12.8 “配置 Undertow 运行时实例的元素” 中描述了用于提供配置属性的子元素。

表 12.8. 配置 Undertow 运行时实例的元素

元素描述

httpu:tlsServerParameters

指定一组属性,用于配置用于特定 Undertow 实例的安全性。

httpu:tlsServerParametersRef

指的是由 identifiedTLSServerParameters 元素定义的一组安全属性。id 属性提供 identifiedTLSServerParameters 元素的 id。

httpu:threadingParameters

指定特定 Undertow 实例使用的线程池的大小。请参阅 “配置线程池”一节

httpu:threadingParametersRef

指的是由 指定的ThreadingParameters 元素定义的一组属性。id 属性提供所 识别的ThreadingParameters 元素的 id。

配置线程池

您可以通过以下任一方式配置 Undertow 实例的线程池的大小:

  • 使用 engine-factory 元素中的 标识ThreadingParameters 元素来指定线程池的大小。然后,您可以使用 threadingParametersRef 元素来引用元素。
  • 使用 threadingParameters 元素直接指定线程池的大小。

threadingParameters 有两个属性来指定线程池的大小。属性在 表 12.9 “配置 Undertow 线程池的属性” 中描述。

注意

httpu:identifiedThreadingParameters 元素具有一个子 线程参数 元素。

表 12.9. 配置 Undertow 线程池的属性

属性描述

workerIOThreads

指定为 worker 创建的 I/O 线程数量。如果未指定,则会选择 dafult 值。默认值为每个 CPU 内核的一个 I/O 线程。

minThreads

指定用于处理请求的最小线程数量。

最大线程数

指定用于处理请求的最大线程数量。

示例

例 12.15 “配置 Undertow 实例” 显示配置片段,在端口号 9001 上配置 Undertow 实例。

例 12.15. 配置 Undertow 实例

<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:sec="http://cxf.apache.org/configuration/security"
  xmlns:http="http://cxf.apache.org/transports/http/configuration"
  xmlns:httpu="http://cxf.apache.org/transports/http-undertow/configuration"
  xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"
  xsi:schemaLocation="http://cxf.apache.org/configuration/security
  		      http://cxf.apache.org/schemas/configuration/security.xsd
            http://cxf.apache.org/transports/http/configuration
            http://cxf.apache.org/schemas/configuration/http-conf.xsd
            http://cxf.apache.org/transports/http-undertow/configuration
            http://cxf.apache.org/schemas/configuration/http-undertow.xsd
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
  ...

  <httpu:engine-factory bus="cxf">
    <httpu:identifiedTLSServerParameters id="secure">
      <sec:keyManagers keyPassword="password">
        <sec:keyStore type="JKS" password="password"
                      file="certs/cherry.jks"/>
      </sec:keyManagers>
    </httpu:identifiedTLSServerParameters>

    <httpu:engine port="9001">
      <httpu:tlsServerParametersRef id="secure" />
      <httpu:threadingParameters minThreads="5"
                                 maxThreads="15" />
    </httpu:engine>
  </httpu:engine-factory>
 </beans>

限制并发请求和队列大小

您可以配置 Request Limiting Handler,该处理程序将设置并发连接请求数和可通过 Undertow 服务器实例处理的最大队列大小。此配置示例如下所示 例 12.16 “限制连接请求和队列大小”

表 12.10. 用于配置请求限制处理程序的属性

属性描述

maximumConcurrentRequests

指定由 Undertow 实例处理的最大并发请求数量。如果请求数超过这个限制,则请求会被放入。

queueSize

指定可通过 Undertow 实例处理的请求总数。如果请求数超过这个限制,则请求将被拒绝。

例 12.16. 限制连接请求和队列大小

<httpu:engine-factory>
     <httpu:engine port="8282">
         <httpu:handlers>
             <bean class="org.jboss.fuse.quickstarts.cxf.soap.CxfRequestLimitingHandler">
                 <property name="maximumConcurrentRequests" value="1" />
                 <property name="queueSize" value="1"/>
             </bean>
         </httpu:handlers>
     </httpu:engine>
</httpu:engine-factory>

12.5. 配置网络运行时

概述

Netty 运行时供 HTTP 服务供应商和 HTTP 消费者使用分离端点。可以配置运行时的线程池,您还可以通过 Netty 运行时设置 HTTP 服务提供商的多个安全设置。

Maven 依赖项

如果将 Apache Maven 用作构建系统,您可以通过在项目的 pom.xml 文件中包括以下依赖项,将 Netty 运行时(用于定义 Web 服务端点)的服务器端实施添加到项目中:

<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-transports-http-netty-server</artifactId>
    <version>${cxf-version}</version>
</dependency>

您可以通过在项目的 pom.xml 文件中包括以下依赖项,将 Netty 运行时(用于定义 Web 服务客户端)的客户端实施添加到项目中:

<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-transports-http-netty-client</artifactId>
    <version>${cxf-version}</version>
</dependency>

命名空间

用于配置 Netty 运行时的元素在命名空间 http://cxf.apache.org/transports/http-netty-server/configuration 中定义。通常会使用前缀 httpn 来引用。要使用 Netty 配置元素,您必须将 例 12.17 “Netty Runtime Configuration Namespace” 中显示的行添加到端点配置文件的 Bean 元素中。另外,您必须将配置元素的命名空间添加到 xsi:schemaLocation 属性。

例 12.17. Netty Runtime Configuration Namespace

<beans ...
       xmlns:httpn="http://cxf.apache.org/transports/http-netty-server/configuration"
       ...
       xsi:schemaLocation="...
               http://cxf.apache.org/transports/http-netty-server/configuration
            http://cxf.apache.org/schemas/configuration/http-netty-server.xsd
               ...">

engine-factory 元素

httpn:engine-factory 元素是用来配置应用程序使用的 Netty 运行时的根元素。它只有一个必需属性 bus,其值是管理所配置的 Netty 实例的 总线 名称。

注意

该值通常是 cxf,它是默认 总线实例的名称

httpn:engine-factory 元素有三个子项,其中包含用于配置由 Netty runtime factory 实例化的 HTTP 端口的信息。子对象在 表 12.11 “配置 Netty Runtime Factory 的元素” 中描述。

表 12.11. 配置 Netty Runtime Factory 的元素

元素描述

httpn:engine

指定特定 Netty 运行时实例的配置。请参阅 “engine 元素”一节

httpn:identifiedTLSServerParameters

指定用于保护 HTTP 服务提供商的可重复利用属性集合。它有一个属性 id,它指定可以引用该属性集的唯一标识符。

httpn:identifiedThreadingParameters

指定控制 Netty 实例的线程池的可重复使用的属性集合。它有一个属性 id,它指定可以引用该属性集的唯一标识符。

请参阅 “配置线程池”一节

engine 元素

httpn:engine 元素用于配置 Netty 运行时的特定实例。表 12.12 “配置网络运行时实例的属性” 显示 httpn:engine 元素支持的属性。

表 12.12. 配置网络运行时实例的属性

属性描述

port

指定 Netty HTTP 服务器实例使用的端口。您可以为端口属性指定一个 0 值。引擎元素中指定的线程属性设为 0,其 port 属性设置为 0,所有未明确配置的 Netty 侦听器的配置。

主机

指定 Netty HTTP 服务器实例使用的侦听地址。该值可以是主机名或 IP 地址。如果没有指定,Netty HTTP 服务器将侦听所有本地地址。

readIdleTime

指定 Netty 连接的最大读取闲置时间。每当底层流上有任何读取操作时,计时器都会被重置。

writeIdleTime

指定 Netty 连接的最大写入闲置时间。每当底层流上有任何写入操作时,计时器都会被重置。

maxChunkContentSize

指定 Netty 连接的最大聚合内容大小。默认值为 10MB。

httpn:engine 元素具有一个用于配置安全属性的子元素,一个用于配置 Netty 实例的线程池。对于每种配置,您可以直接提供配置信息,也可以提供对父 httpn:engine-factory 元素中定义的一组配置属性的引用。

httpn:engine 支持的子元素显示在 表 12.13 “配置网络运行时实例的元素” 中。

表 12.13. 配置网络运行时实例的元素

元素描述

httpn:tlsServerParameters

指定一组用于配置用于特定 Netty 实例的安全的属性。

httpn:tlsServerParametersRef

指的是由 identifiedTLSServerParameters 元素定义的一组安全属性。id 属性提供 identifiedTLSServerParameters 元素的 id。

httpn:threadingParameters

指定特定 Netty 实例使用的线程池大小。请参阅 “配置线程池”一节

httpn:threadingParametersRef

指的是由 指定的ThreadingParameters 元素定义的一组属性。id 属性提供所 识别的ThreadingParameters 元素的 id。

httpn:sessionSupport

true 时,启用对 HTTP 会话的支持。默认为 false

httpn:reuseAddress

指定设置 ReuseAddress TCP 套接字选项的布尔值。默认为 false

配置线程池

您可以通过以下任一方式配置 Netty 实例的线程池的大小:

  • 使用 engine-factory 元素中的 标识ThreadingParameters 元素来指定线程池的大小。然后,您可以使用 threadingParametersRef 元素来引用元素。
  • 使用 threadingParameters 元素直接指定线程池的大小。

threadingParameters 元素有一个属性来指定线程池的大小,如 表 12.14 “配置网络线程池的属性” 所述。

注意

httpn:identifiedThreadingParameters 元素具有一个子 线程参数 元素。

表 12.14. 配置网络线程池的属性

属性描述

threadPoolSize

指定用于处理请求的 Netty 实例可用的线程数量。

示例

例 12.18 “配置网络实例” 显示配置各种 Netty 端口的配置片段。

例 12.18. 配置网络实例

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:beans="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:h="http://cxf.apache.org/transports/http/configuration"
       xmlns:httpn="http://cxf.apache.org/transports/http-netty-server/configuration"
       xmlns:sec="http://cxf.apache.org/configuration/security"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
        http://cxf.apache.org/configuration/security
            http://cxf.apache.org/schemas/configuration/security.xsd
        http://cxf.apache.org/transports/http/configuration
            http://cxf.apache.org/schemas/configuration/http-conf.xsd
        http://cxf.apache.org/transports/http-netty-server/configuration
            http://cxf.apache.org/schemas/configuration/http-netty-server.xsd"
>
    ...
    <httpn:engine-factory bus="cxf">
       <httpn:identifiedTLSServerParameters id="sample1">
         <httpn:tlsServerParameters jsseProvider="SUN" secureSocketProtocol="TLS">
            <sec:clientAuthentication want="false" required="false"/>
         </httpn:tlsServerParameters>
       </httpn:identifiedTLSServerParameters>

       <httpn:identifiedThreadingParameters id="sampleThreading1">
          <httpn:threadingParameters threadPoolSize="120"/>
       </httpn:identifiedThreadingParameters>

       <httpn:engine port="9000" readIdleTime="30000" writeIdleTime="90000">
          <httpn:threadingParametersRef id="sampleThreading1"/>
       </httpn:engine>

       <httpn:engine port="0">
          <httpn:threadingParameters threadPoolSize="400"/>
       </httpn:engine>

       <httpn:engine port="9001" readIdleTime="40000" maxChunkContentSize="10000">
         <httpn:threadingParameters threadPoolSize="99" />
         <httpn:sessionSupport>true</httpn:sessionSupport>
       </httpn:engine>

       <httpn:engine port="9002">
         <httpn:tlsServerParameters>
           <sec:clientAuthentication want="true" required="true"/>
         </httpn:tlsServerParameters>
       </httpn:engine>

       <httpn:engine port="9003">
          <httpn:tlsServerParametersRef id="sample1"/>
       </httpn:engine>

    </httpn:engine-factory>
</beans>

12.6. 在拒绝模式中使用 HTTP 传输

概述

在普通的 HTTP 请求/响应场景中,请求和响应使用相同的 HTTP 连接发送。服务提供商处理请求并响应包含适当 HTTP 状态代码和响应内容的响应。如果是成功请求,HTTP 状态代码将设为 200。

在某些情况下,比如使用 WS-RM,或者请求执行延长的时间,因此分离请求和响应消息是合理的。在这种情况下,服务提供程序通过 HTTP 连接的后端通道将消费者发送 202 Accepted 响应到消费者,后者上接收了请求。然后,它会处理请求,并使用新的解除服务器→client HTTP 连接将响应发回到消费者。使用者运行时收到传入的响应,并在返回到应用代码之前将其与适当的请求相关联。

配置分离交互

以分离模式使用 HTTP 传输需要您执行以下操作:

  1. 配置使用者以使用 WS-Addressing。

    请参阅 “配置端点以使用 WS-Addressing”一节

  2. 将使用者配置为使用分离端点。

    请参阅 “配置使用者”一节

  3. 配置消费者与之交互的任何服务提供商,以使用 WS-Addressing。

    请参阅 “配置端点以使用 WS-Addressing”一节

配置端点以使用 WS-Addressing

指定使用者和任何服务提供程序使用 WS-Addressing。

您可以通过以下两种方式之一指定端点使用 WS-Addressing:

  • 添加 wswa:UsingAddressing 元素到端点的 WSDL 端口 元素,如 例 12.19 “使用 WSDL 激活 WS-Addressing” 所示。

    例 12.19. 使用 WSDL 激活 WS-Addressing

    ...
    <service name="WidgetSOAPService">
      <port name="WidgetSOAPPort" binding="tns:WidgetSOAPBinding">
        <soap:address="http://widgetvendor.net/widgetSeller" />
        <wswa:UsingAddressing xmlns:wswa="http://www.w3.org/2005/02/addressing/wsdl"/>
      </port>
    </service>
    ...
  • 将 WS-Addressing 策略添加到端点的 WSDL 端口 元素,如 例 12.20 “使用策略激活 WS-Addressing” 所示。

    例 12.20. 使用策略激活 WS-Addressing

    ...
    <service name="WidgetSOAPService">
      <port name="WidgetSOAPPort" binding="tns:WidgetSOAPBinding">
        <soap:address="http://widgetvendor.net/widgetSeller" />
        <wsp:Policy xmlns:wsp="http://www.w3.org/2006/07/ws-policy"> <wsam:Addressing xmlns:wsam="http://www.w3.org/2007/02/addressing/metadata"> <wsp:Policy/> </wsam:Addressing> </wsp:Policy>
      </port>
    </service>
    ...
注意

WS-Addressing 策略取代了 wswa:UsingAddressing WSDL 元素。

配置使用者

使用 http-conf:conduit 元素的 DecoupledEndpoint 属性,将消费者端点配置为使用分离的端点。

例 12.21 “将 Consumer 配置为使用已拒绝的 HTTP 端点” 显示设置 例 12.19 “使用 WSDL 激活 WS-Addressing” 中定义的端点的配置,以使用分离端点。用户现在收到所有响应 http://widgetvendor.net/widgetSellerInbox

例 12.21. 将 Consumer 配置为使用已拒绝的 HTTP 端点

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:http="http://cxf.apache.org/transports/http/configuration"
       xsi:schemaLocation="http://cxf.apache.org/transports/http/configuration
                             http://cxf.apache.org/schemas/configuration/http-conf.xsd
                           http://www.springframework.org/schema/beans
                             http://www.springframework.org/schema/beans/spring-beans.xsd">

  <http:conduit name="{http://widgetvendor.net/services}WidgetSOAPPort.http-conduit">
    <http:client DecoupledEndpoint="http://widgetvendor.net:9999/decoupled_endpoint" />
  </http:conduit>
</beans>

如何处理消息

在分离模式下使用 HTTP 传输会增加对 HTTP 消息处理的额外复杂性。虽然为应用程序中的实施级别代码增加了复杂性是透明的,但了解调试原因可能很重要。

图 12.1 “拒绝 HTTP 传输中的消息流” 显示在分离模式下使用 HTTP 时的信息流。

图 12.1. 拒绝 HTTP 传输中的消息流

分离的消息交换中有十五步。

请求启动以下进程:

  1. 使用者实施调用操作,并且生成请求消息。
  2. WS-Addressing 层将 WS-A 标头添加到消息中。

    当在消费者配置中指定分离端点时,分离端点的地址会被放在 WS-A ReplyTo 标头中。

  3. 邮件将发送到服务供应商。
  4. 服务提供商收到消息。
  5. 来自消费者的请求消息被分配到提供商的 WS-A 层。
  6. 由于 WS-A ReplyTo 标头没有设置为 anonymous,因此提供商会向一个 HTTP 状态代码发回一个消息,确认已接收了请求。
  7. HTTP 层使用原始连接的 back-channel 将 202 Accepted 消息发回给消费者。
  8. 使用者收到用于发送原始消息的 HTTP 连接后端频道的 202 Accepted 回复。

    当消费者收到 202 Accepted 回复时,HTTP 连接将关闭。

  9. 请求传递到处理请求的服务提供商的实现。
  10. 当响应就绪时,它将被分配给 WS-A 层。
  11. WS-A 层将 WS-Addressing 标头添加到响应消息中。
  12. HTTP 传输将响应发送到消费者的解除端点。
  13. 消费者分离的端点接收来自服务提供商的响应。
  14. 响应被分配给消费者的 WS-A 层,它使用 WS-A RelatesTo 标头与正确的请求相关联。
  15. 关联的响应将返回到客户端实施,调用调用被取消阻塞。

第 13 章 使用 JMS 的 SOAP

摘要

Apache CXF 实施 W3C 标准 SOAP/JMS 传输。这个标准旨在提供更加可靠的 SOAP/HTTP 服务的替代方案。使用此传输的 Apache CXF 应用程序应该能够与实施 SOAP/JMS 标准的应用程序交互。传输在端点的 WSDL 中直接配置。

注意 :在 CXF 3.0 中删除了对 JMS 1.0.2 API 的支持。如果您使用红帽 JBoss Fuse 6.2 或更高版本(包括 CXF 3.0),您的 JMS 供应商必须支持 JMS 1.1 API。

13.1. 基本配置

概述

JMS 协议的 SOAP 由 World Wide Web Consortium(W3C)定义,作为向大多数服务使用的定制 SOAP/HTTP 协议提供更可靠的传输层的方法。Apache CXF 实现与规格完全兼容,并与也兼容的框架兼容。

此传输使用 JNDI 来查找 JMS 目的地。调用操作时,请求将打包为 SOAP 消息,并发送到指定目的地的 JMS 消息正文。

使用 SOAP/JMS 传输:

  1. 指定传输类型是 SOAP/JMS。
  2. 使用 JMS URI 指定目标目的地。
  3. 另外,还可配置 JNDI 连接。
  4. (可选)添加额外的 JMS 配置。

指定 JMS 传输类型

您可以将 SOAP 绑定配置为在指定 WSDL 绑定时使用 JMS 传输。将 soap:binding 元素的 transport 属性设置为 http://www.w3.org/2010/soapjms/例 13.1 “SOAP over JMS 绑定规格” 显示使用 SOAP/JMS 的 WSDL 绑定。

例 13.1. SOAP over JMS 绑定规格

<wsdl:binding ... >
  <soap:binding style="document"
                transport="http://www.w3.org/2010/soapjms/" />
  ...
</wsdl:binding>

指定目标目的地

在为端点指定 WSDL 端口时,您可以指定 JMS 目标目的地的地址。SOAP/JMS 端点的地址规格使用与 SOAP/HTTP 端点相同的 soap:address 元素和属性。差别在于地址规格。JMS 端点使用 JMS 1.0 的 URI Scheme 中定义的 JMS URI。例 13.2 “JMS URI 语法” 显示 JMS URI 的语法。

例 13.2. JMS URI 语法

jms:variant:destination?options

表 13.1 “JMS URI 变体” 描述 JMS URI 的可用变体。

表 13.1. JMS URI 变体

变体描述

jndi

指定目的地名称是 JNDI 队列名称。使用这个变体时,您必须提供配置来访问 JNDI 供应商。

jndi-topic

指定目的地名称是 JNDI 主题名称。使用这个变体时,您必须提供配置来访问 JNDI 供应商。

队列

指定目的地是使用 JMS 解析的队列名称。提供的字符串 传递到 Session.createQueue(),以创建目的地的表示形式。

topic

指定目标为使用 JMS 解析的主题名称。提供的字符串 传递到 Session.createTopic(),以创建目的地的表示形式。

JMS URI 的选项 部分用于配置传输,并在 第 13.2 节 “JMS URI” 中讨论。

例 13.3 “SOAP/JMS 端点地址” 显示 SOAP/JMS 端点的 WSDL 端口条目,该端点使用 JNDI 查找其目标。

例 13.3. SOAP/JMS 端点地址

<wsdl:port ... >
  ...
  <soap:address location="jms:jndi:dynamicQueues/test.cxf.jmstransport.queue" />
</wsdl:port>

配置 JNDI 和 JMS 传输

SOAP/JMS 提供了多种方法来配置 JNDI 连接和 JMS 传输:

13.2. JMS URI

概述

使用 SOAP/JMS 时,将使用 JMS URI 指定端点的目标目的地。JMS URI 也可以通过在 URI 中附加一个或多个选项来配置 JMS 连接。这些选项在 IETF 标准中详述,Java 消息服务 1.0 的 URI Scheme 进行了详细。它们可用于配置 JNDI 系统、要使用的回复目的地、要使用的交付模式和其他 JMS 属性。

语法

例 13.4 “JMS URI 选项的语法” 所示,您可以在 JMS URI 的末尾附加一个或多个选项,方法是使用问号(?)从目标地址中分离它们。多个选项由 符号(和)分隔例 13.4 “JMS URI 选项的语法” 演示了在 JMS URI 中使用多个选项的语法。

例 13.4. JMS URI 选项的语法

jms:variant:jmsAddress?option1=value1&option2=value2&_optionN_=valueN

JMS 属性

表 13.2 “JMS 属性设置为 URI 选项” 显示影响 JMS 传输层的 URI 选项。

表 13.2. JMS 属性设置为 URI 选项

属性默认描述

conduitIdSelectorPrefix

 

[可选] 一个字符串值,它前缀放在 conduit 所创建的所有 correlation ID 中。选择器可以使用它来侦听回复。

deliveryMode

PERSISTENT

指定是否使用 JMS PROJECTI STENTNON_PROJECTISTENT 消息语义。如果是 BASEI STENT 交付模式,JMS 代理会在确认它们前将消息存储在持久性存储中;而 NON_955ISTENT 消息仅保存在内存中。

durableSubscriptionClientID

 

[可选] 指定连接的客户端标识符。此属性用于将连接与提供程序代表客户端维护的状态关联。这可让后续具有相同身份的订阅者恢复之前订阅者留下它的状态。

durableSubscriptionName

 

[可选] 指定订阅的名称。

messageType

byte

指定 CXF 使用的 JMS 消息类型。有效值为:

  • 字节
  • text
  • 二进制(二进制)

password

 

[可选] 指定用于创建连接的密码。不建议将此属性附加到 URI。

priority

4

指定 JMS 消息优先级,范围从 0(最低)到 9(最高)。

receiveTimout

60000

指定时间(以毫秒为单位),在使用请求/回复时,客户端将等待回复。

reconnectOnException

true

[在 CXF 3.0] 中已弃用,指定传输是否应在异常时重新连接。

从 3.0 开始,当出现异常时,传输总是重新连接。

replyToName

 

[可选] 指定队列信息的回复目的地。回复目的地会出现在 JMSReplyTo 标头中。建议为具有请求性语义的应用设置此属性,因为如果未指定,JMS 提供程序将分配一个临时回复队列。

此属性的值会根据 JMS URI 中指定的变体进行解释:

  • JNDI 变体 - 由 JNDI 解析的目标队列的名称
  • 使用 JMS 解析目标队列的队列变体名称

sessionTransacted

false

指定事务类型。有效值为:

  • true- 资源本地事务
  • false-JTA 事务

timeToLive

0

指定 JMS 提供程序将丢弃消息的时间(以毫秒为单位)。值为 0 表示无限生命周期。

topicReplyToName

 

[可选] 指定主题信息的答复目的地。此属性的值会根据 JMS URI 中指定的变体进行解释:

  • JNDI-topic- 由 JNDI 解析的目标主题的名称
  • 主题- 由 JMS 解析的目标主题的名称

使用ConduitIdSelector

true

指定 conduit 的 UUID 作为所有关联 ID 的前缀。

因为所有 conduits 都被分配一个唯一 UUID,请将此属性设置为 true 可让多个端点共享 JMS 队列或主题。

username

 

[可选] 指定用来创建连接的用户名。

JNDI 属性

表 13.3 “JNDI 属性设为 URI 选项” 显示可用于为此端点配置 JNDI 的 URI 选项。

表 13.3. JNDI 属性设为 URI 选项

属性描述

jndiConnectionFactoryName

指定 JMS 连接工厂的 JNDI 名称。

jndiInitialContextFactory

指定 JNDI 提供程序的完全限定 Java 类名称(必须是 javax.jms.InitialContextFactory 类型)。等同于设置 java.naming.factory.initial Java 系统属性。

jndiTransactionManagerName

指定在 Spring、蓝图或 JNDI 中搜索的 JTA 事务管理器的名称。如果找到事务管理器,则将启用 JTA 事务。请参阅 sessionTransacted JMS 属性。

jndiURL

指定初始化 JNDI 供应商的 URL。等同于设置 java.naming.provider.url Java 系统属性。

其他 JNDI 属性

其属性 java.naming.factory.initialjava.naming.provider.url 是初始化任何 JNDI 提供者所需的标准属性。但是,除标准外,JNDI 提供程序还可能支持自定义属性。在本例中,您可以通过设置 jndi-PropertyName 格式的 URI 选项来设置任意 JNDI 属性。

例如,如果您使用 SUN 的 LDAP 实现,您可以使用 JNDI 属性 java.naming.factory.control 在 JMS URI 中,如 例 13.5 “在 JMS URI 中设置 JNDI 属性” 所示。

例 13.5. 在 JMS URI 中设置 JNDI 属性

jms:queue:FOO.BAR?jndi-java.naming.factory.control=com.sun.jndi.ldap.ResponseControlFactory

示例

如果尚未配置 JMS 提供程序,则可以使用选项在 URI 中提供先决条件 JNDI 配置详情(请参阅 表 13.3 “JNDI 属性设为 URI 选项”)。例如,若要配置端点以使用 Apache ActiveMQ JMS 提供程序并连接到名为 test.cxf.jmstransport.queue 的队列,可使用 例 13.6 “配置 JNDI 连接的 JMS URI” 中显示的 URI。

例 13.6. 配置 JNDI 连接的 JMS URI

jms:jndi:dynamicQueues/test.cxf.jmstransport.queue
?jndiInitialContextFactory=org.apache.activemq.jndi.ActiveMQInitialContextFactory
&jndiConnectionFactoryName=ConnectionFactory
&jndiURL=tcp://localhost:61616

发布服务

JAX-WS 标准 publish() 方法无法用于发布 SOAP/JMS 服务。反之,您必须使用 Apache CXF 的 JaxWsServerFactoryBean 类,如 例 13.7 “发布 SOAP/JMS 服务” 所示。

例 13.7. 发布 SOAP/JMS 服务

String address = "jms:jndi:dynamicQueues/test.cxf.jmstransport.queue3"
    + "?jndiInitialContextFactory"
    + "=org.apache.activemq.jndi.ActiveMQInitialContextFactory"
    + "&jndiConnectionFactoryName=ConnectionFactory"
    + "&jndiURL=tcp://localhost:61500";
Hello implementor = new HelloImpl();
JaxWsServerFactoryBean svrFactory = new JaxWsServerFactoryBean();
svrFactory.setServiceClass(Hello.class);
svrFactory.setAddress(address);
svrFactory.setTransportId(JMSSpecConstants.SOAP_JMS_SPECIFICIATION_TRANSPORTID);
svrFactory.setServiceBean(implementor);
svrFactory.create();

例 13.7 “发布 SOAP/JMS 服务” 中的代码执行以下操作:

创建代表类端点地址的 JMS URI。

实例化 JaxWsServerFactoryBean 以发布该服务。

使用服务的 JMS URI 设置 factory bean 的 address 字段。

指定工厂创建的服务将使用 SOAP/JMS 传输。

消耗服务

标准 JAX-WS API 无法用于使用 SOAP/JMS 服务。反之,您必须使用 Apache CXF 的 JaxWsProxyFactoryBean 类,如 例 13.8 “消耗 SOAP/JMS 服务” 所示。

例 13.8. 消耗 SOAP/JMS 服务

// Java
public void invoke() throws Exception {
    String address = "jms:jndi:dynamicQueues/test.cxf.jmstransport.queue3"
        + "?jndiInitialContextFactory"
        + "=org.apache.activemq.jndi.ActiveMQInitialContextFactory"
        + "&jndiConnectionFactoryName=ConnectionFactory&jndiURL=tcp://localhost:61500";
    JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
    factory.setAddress(address);
    factory.setTransportId(JMSSpecConstants.SOAP_JMS_SPECIFICIATION_TRANSPORTID);
    factory.setServiceClass(Hello.class);
    Hello client = (Hello)factory.create();
    String reply = client.sayHi(" HI");
    System.out.println(reply);
}

例 13.8 “消耗 SOAP/JMS 服务” 中的代码执行以下操作:

创建代表类端点地址的 JMS URI。

实例化 JaxWsProxyFactoryBean 来创建代理。

使用服务的 JMS URI 设置 factory bean 的 address 字段。

指定工厂创建的代理将使用 SOAP/JMS 传输。

13.3. WSDL 扩展

概述

您可以通过将 WSDL 扩展元素插入到合同中(在绑定范围、服务范围或端口范围)中,指定 JMS 传输的基本配置。WSDL 扩展允许您指定引导 JNDI InitialContext 的属性,然后可用来查找 JMS 目的地。您也可以设置一些影响 JMS 传输层行为的属性。

SOAP/JMS 命名空间

SOAP/JMS WSDL 扩展在 http://www.w3.org/2010/soapjms/ 命名空间中定义。要在 WSDL 合同中使用它们,请将以下设置添加到 wsdl:definitions 元素中:

<wsdl:definitions ...
    xmlns:soapjms="http://www.w3.org/2010/soapjms/"
  ... >

WSDL 扩展元素

表 13.4 “SOAP/JMS WSDL 扩展元素” 显示可用于配置 JMS 传输的所有 WSDL 扩展元素。

表 13.4. SOAP/JMS WSDL 扩展元素

元素默认描述

soapjms:jndiInitialContextFactory

 

指定 JNDI 提供程序的完全限定 Java 类名称。等同于设置 java.naming.factory.initial Java 系统属性。

soapjms:jndiURL

 

指定初始化 JNDI 供应商的 URL。等同于设置 java.naming.provider.url Java 系统属性。

soapjms:jndiContextParameter

 

指定用于创建 JNDI InitialContext 的额外属性。使用 namevalue 属性来指定属性。

soapjms:jndiConnectionFactoryName

 

指定 JMS 连接工厂的 JNDI 名称。

soapjms:deliveryMode

PERSISTENT

指定是否使用 JMS PROJECTI STENTNON_PROJECTISTENT 消息语义。如果是 BASEI STENT 交付模式,JMS 代理会在确认它们前将消息存储在持久性存储中;而 NON_955ISTENT 消息仅保存在内存中。

soapjms:replyToName

 

[可选] 指定队列信息的回复目的地。回复目的地会出现在 JMSReplyTo 标头中。建议为具有请求性语义的应用设置此属性,因为如果未指定,JMS 提供程序将分配一个临时回复队列。

此属性的值会根据 JMS URI 中指定的变体进行解释:

  • JNDI 变体 - 由 JNDI 解析的目标队列的名称
  • 使用 JMS 解析目标队列的队列变体名称

soapjms:priority

4

指定 JMS 消息优先级,范围从 0(最低)到 9(最高)。

soapjms:timeToLive

0

JMS 提供程序将丢弃消息的时间(以毫秒为单位)。值为 0 代表无限生命周期。

配置范围

WSDL 合同中的 WSDL 元素放置会影响合同中定义的端点更改的范围。SOAP/JMS WSDL 元素可以放置为 ws:binding 元素的子项、wsdl:service 元素或 wsdl:port 元素。SOAP/JMS 元素的父项决定将配置放入以下哪个范围:

绑定范围
您可以通过在 wsdl: binding 元素内放置扩展元素,将 JMS 传输配置为绑定范围。此范围内的元素定义使用此绑定的所有端点的默认配置。绑定范围内的任何设置都可在服务范围或端口范围中覆盖。
服务范围
您可以通过将扩展元素放在 wsdl: service 元素内,将 JMS 传输配置为服务范围。此范围内的元素定义此服务中所有端点的默认配置。服务范围中的任何设置都可在端口范围中覆盖。
端口范围
您可以通过将扩展元素放在 wsdl: port 元素内,将 JMS 传输配置为端口范围。端口范围中的元素定义此端口的配置。它们覆盖在服务范围或绑定范围中定义的相同扩展元素的默认值。

示例

例 13.9 “与 SOAP/JMS 配置进行 WSDL 合同” 显示 SOAP/JMS 服务的 WSDL 合同。它在绑定范围中配置 JNDI 层,即服务范围中的消息发送详情,以及端口范围中的回复目的地。

例 13.9. 与 SOAP/JMS 配置进行 WSDL 合同

<wsdl:definitions ...
    xmlns:soapjms="http://www.w3.org/2010/soapjms/"
  ... >
  ...
  <wsdl:binding name="JMSGreeterPortBinding" type="tns:JMSGreeterPortType">
    ...
    <soapjms:jndiInitialContextFactory>
      org.apache.activemq.jndi.ActiveMQInitialContextFactory
    </soapjms:jndiInitialContextFactory>
    <soapjms:jndiURL>tcp://localhost:61616</soapjms:jndiURL>
    <soapjms:jndiConnectionFactoryName>
      ConnectionFactory
    </soapjms:jndiConnectionFactoryName>
    ...
  </wsdl:binding>
  ...
  <wsdl:service name="JMSGreeterService">
    ...
    <soapjms:deliveryMode>NON_PERSISTENT</soapjms:deliveryMode>
    <soapjms:timeToLive>60000</soapjms:timeToLive>
    ...
    <wsdl:port binding="tns:JMSGreeterPortBinding" name="GreeterPort">
      <soap:address location="jms:jndi:dynamicQueues/test.cxf.jmstransport.queue" />
      <soapjms:replyToName>
        dynamicQueues/greeterReply.queue
      </soapjms:replyToName>
      ...
    </wsdl:port>
    ...
  </wsdl:service>
  ...
</wsdl:definitions>

例 13.9 “与 SOAP/JMS 配置进行 WSDL 合同” 中的 WSDL 执行以下操作:

为 SOAP/JMS 扩展声明命名空间。

在绑定范围内配置 JNDI 连接。

将 JMS delivery 风格设置为非持久性,每个消息都设置为 live。

指定目标目的地。

配置 JMS 传输,以便在 greeterReply.queue 队列中发送回复消息。

第 14 章 使用通用 JMS

摘要

Apache CXF 提供 JMS 传输的通用实施。通用 JMS 传输不限于使用 SOAP 消息,并允许连接到使用 JMS 的任何应用程序。

注意 :在 CXF 3.0 中删除了对 JMS 1.0.2 API 的支持。如果您使用红帽 JBoss Fuse 6.2 或更高版本(包括 CXF 3.0),您的 JMS 供应商必须支持 JMS 1.1 API。

14.1. 配置 JMS 的方法

Apache CXF 通用 JMS 传输可以连接到任何 JMS 提供程序,并使用将 JMS 消息与 text Message 或 ByteMessage 的正文交换的应用程序。

有两种方法可以启用和配置 JMS 传输:

14.2. 使用 JMS 配置 bean

概述

为简化 JMS 配置并使其更加强大,Apache CXF 使用单一 JMS 配置 bean 配置来配置 JMS 端点。bean 由 org.apache.cxf.transport.jms.JMSConfiguration 类实施。它可用于直接配置端点,或者配置 JMS conduit 和目的地。

配置命名空间

JMS 配置 bean 使用 Spring p-namespace 使配置尽可能简单。要使用此命名空间,您需要在配置的根元素中声明它,如 例 14.1 “声明 Spring p-namespace” 所示。

例 14.1. 声明 Spring p-namespace

<beans ...
  xmlns:p="http://www.springframework.org/schema/p"
  ... >
  ...
</beans>

指定配置

您可以通过定义类 org.apache.cxf.transport.jms.JMSConfiguration 来指定 JMS 配置。an 的属性提供传输的配置设置。

重要

在 CXF 3.0 中,JMS 传输不再依赖于 Spring JMS,因此删除了一些与 Spring JMS 相关的选项。

表 14.1 “常规 JMS 配置属性” 列出对提供程序和消费者通用的属性。

表 14.1. 常规 JMS 配置属性

属性默认描述

connectionFactory

 

[required] 指定对定义 JMS ConnectionFactory 的 bean 的引用。

wrapInSingleConnectionFactory

true [pre v3.0]

CXF 3.0 中删除

预先 CXF 3.0 指定是否将 ConnectionFactory 与 Spring SingleConnectionFactory 换行。

在使用没有池连接的 ConnectionFactory 时启用此属性,因为它可以提高 JMS 传输的性能。这是因为 JMS 传输为每个消息创建新连接,并且需要 SingleConnectionFactory 来缓存连接,使它能被重复使用。

reconnectOnException

false

发生异常时,CXF 中已弃用 CXF 始终重新连接。

pre CXF 3.0 指定在出现异常时是否创建新连接。

使用 Spring SingleConnectionFactory 嵌套 ConnectionFactory 时:

  • 对一个例外情况进行 true busybox,创建一个新连接

    在使用 PooledConnectionFactory 时,不要启用这个选项,因为这个选项只返回池的连接,但不会重新连接。

  • 异常错误,错误,不要尝试重新连接

targetDestination

 

指定目的地的 JNDI 名称或供应商名称。

replyDestination

 

指定发送回复的 JMS 目的地的 JMS 名称。此属性允许使用用户定义的目的地来回复。详情请查看 第 14.6 节 “使用 Named Reply Destination”

destinationResolver

DynamicDestinationResolver

指定对 Spring DestinationResolver 的引用。

此属性允许您定义目标名称如何解析到 JMS 目的地。有效值为:

  • DynamicDestinationResolver sHistoryLimit->_<resolve 目标名称使用 JMS 提供程序的功能。
  • JndiDestinationResolver >_<-resolve 目标名称使用 JNDI。

transactionManager

 

指定对 Spring 事务管理器的引用。这可让服务参与 JTA 事务。

taskExecutor

SimpleAsyncTaskExecutor

CXF 3.0 中删除

前 CXF 3.0 指定对 Spring TaskExecutor 的引用。这在监听程序中用来决定如何处理传入的信息。

useJms11

false

CXF 3.0 CXF 3.0 中删除 仅支持 JMS 1.1 功能。

前 CXF 3.0 指定是否使用了 JMS 1.1 功能。有效值为:

  • true abrt- theJMS 1.1 功能
  • false abrt- theJMS 1.0.2 功能

messageIdEnabled

true

CXF 3.0 中删除

前 CXF 3.0 指定 JMS 传输是否希望 JMS 代理提供消息 ID。有效值为:

  • true KUBECONFIG-broker 需要提供消息 ID
  • false InventoryService-brokerbroker 不需要提供消息 ID

    在本例中,端点调用其消息制作者的 setDisableMessageID() 方法,值设为 true。然后,代理会提供一个提示,它不需要生成消息 ID,或将其添加到端点的消息中。代理可以接受 hint,或者忽略它。

messageTimestampEnabled

true

CXF 3.0 中删除

前 CXF 3.0 指定 JMS 传输是否希望 JMS 代理提供消息时间戳。有效值为:

  • true abrt- thebroker 需要提供消息时间戳
  • false InventoryService- thebroker 不需要提供消息时间戳

    在本例中,端点调用其消息 producer 的 setDisableMessageTimestamp() 方法,值设为 true。然后,代理会提供一个提示,它不需要生成时间戳,或将其添加到端点的消息中。代理可以接受 hint,或者忽略它。

cacheLevel

-1( 禁用功能)

CXF 3.0 中删除

前 CXF 3.0 指定 JMS 侦听器容器可以应用的缓存级别。有效值为:

  • 0 — CACHE_NONE
  • 1 INVENTORYSERVICE-JAXBCACHE_CONNECTION
  • 2 — CACHE_SESSION
  • 3 — CACHE_CONSUMER
  • 4 — CACHE_AUTO

详情请参阅 Class DefaultMessageListenerContainer

pubSubNoLocal

false

指定在使用主题时是否收到您自己的消息。

  • true NETWORK- thedo 没有接收您自己的信息
  • false WWPN-receive 询问您自己的信息

receiveTimeout

60000

指定时间(以毫秒为单位),以等待响应消息。

explicitQosEnabled

false

指定每个消息是否明确设置 QoS 设置(如优先级、持久性、时间为实时),或使用默认值(false)。

deliveryMode

2

指定消息是否持久。有效值为:

  • 1 (NON_955ISTENT)-messages 只保存内存
  • 2 (EFIISTENT)消息被保留到磁盘

priority

4

指定消息优先级。JMS 优先级值的范围是从 0( 最低)到 9 (最高)。详情请参阅您的 JMS 供应商的文档。

timeToLive

0( 无限)

指定丢弃的消息前的时间(以毫秒为单位)。

sessionTransacted

false

指定是否使用了 JMS 事务。

concurrentConsumers

1

CXF 3.0 中删除

前 CXF 3.0 指定侦听器的最小并发用户数。

maxConcurrentConsumers

1

CXF 3.0 中删除

前 CXF 3.0 为监听器指定最大并发用户数。

messageSelector

 

指定用于过滤传入消息的选择器的字符串值。此属性允许多个连接共享队列。有关使用指定选择器的语法的更多信息,请参阅 JMS 1.1 规格

subscriptionDurable

false

指定服务器是否使用持久订阅。

durableSubscriptionName

 

指定注册持久订阅的名称(字符串)。

messageType

text

指定消息数据如何打包为 JMS 消息。有效值为:

  • 文本 abrt->_< 表明数据将被打包为 text Message
  • byte Equal-jaxbspec 表示数据将被打包为字节数组(byte[])
  • 二进制 sHistoryLimit->_<spec 表示数据将被打包为 ByteMessage

pubSubDomain

false

指定目标目标是否为一个主题还是一个队列。有效值为:

  • true abrt- thetopic
  • false InventoryService- thequeue

jmsProviderTibcoEms

false

指定 JMS 提供程序是 Tibco EMS。

当设置为 true 时,安全性上下文中的主体会从 JMS_TIBCO_SENDER 标头填充。

useMessageIDAsCorrelationID

false

CXF 3.0 中删除

指定 JMS 是否将使用消息 ID 来关联消息。

当设置为 true 时,客户端会设置生成的关联 ID。

maxSuspendedContinuations

-1( 禁用功能)

CXF 3.0 指定 JMS 目标可能具有的最大暂停数量。当当前数量超过指定的最大值时,JMSListenerContainer 将停止。

reconnectPercentOfMax

70

CXF 3.0 指定当重启 JMSListenerContainer 时,会超过 maxSuspendedContinuations

当其当前暂停持续数低于 (maxSuspendedContinuations * reconnectPercentOfMax/100) 的值时,监听程序容器会被重启。

例 14.2 “JMS 配置 bean” 所示,an 的属性被指定为 bean 元素的属性。它们都在 Spring p 命名空间中声明。

例 14.2. JMS 配置 bean

<bean id="jmsConfig"
      class="org.apache.cxf.transport.jms.JMSConfiguration"
      p:connectionFactory="jmsConnectionFactory"
      p:targetDestination="dynamicQueues/greeter.request.queue"
      p:pubSubDomain="false" />

将配置应用到端点

JMSConfiguration bean 可以直接使用 Apache CXF 功能机制直接应用到服务器和客户端端点。要做到这一点:

  1. 将端点的 address 属性设置为 jms://
  2. 在端点配置中添加 jaxws:feature 元素。
  3. 为该功能添加类型 org.apache.cxf.transport.jms.JMSConfigFeature 的 bean。
  4. bean 元素的 p:jmsConfig-ref 属性设置为 JMSConfiguration bean 的 ID。

例 14.3 “将 JMS 配置添加到 JAX-WS 客户端” 显示使用来自 例 14.2 “JMS 配置 bean” 的 JMS 配置的 JAX-WS 客户端。

例 14.3. 将 JMS 配置添加到 JAX-WS 客户端

<jaxws:client id="CustomerService"
              xmlns:customer="http://customerservice.example.com/"
              serviceName="customer:CustomerServiceService"
              endpointName="customer:CustomerServiceEndpoint"
              address="jms://"
              serviceClass="com.example.customerservice.CustomerService">
  <jaxws:features>
    <bean xmlns="http://www.springframework.org/schema/beans"
          class="org.apache.cxf.transport.jms.JMSConfigFeature"
          p:jmsConfig-ref="jmsConfig"/>
  </jaxws:features>
</jaxws:client>

将配置应用到传输

JMSConfiguration Bean 可以使用 jms:jmsConfig-ref 元素应用到 JMS conduits 和 JMS 目的地。jms:jmsConfig-ref 元素的值是 JMSConfiguration bean 的 ID。

例 14.4 “将 JMS 配置添加到 JMS conduit” 显示使用来自 例 14.2 “JMS 配置 bean” 的 JMS 配置的 JMS conduit。

例 14.4. 将 JMS 配置添加到 JMS conduit

<jms:conduit name="{http://cxf.apache.org/jms_conf_test}HelloWorldQueueBinMsgPort.jms-conduit">
  ...
  <jms:jmsConfig-ref>jmsConf</jms:jmsConfig-ref>
</jms:conduit>

14.3. 优化客户端 JMS 性能

概述

两个主要设置会影响客户端的 JMS 性能:池和同步接收。

在客户端上,CXF 为每个消息创建一个新的 JMS 会话和 JMS producer。这是因为会话和制作者对象都是安全线程的。创建制作者特别要大量时间,因为它需要与服务器通信。

池连接工厂通过缓存连接、会话和制作者来提高性能。

对于 ActiveMQ,配置池很简单;例如:

import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.pool.PooledConnectionFactory;

ConnectionFactory cf = new ActiveMQConnectionFactory("tcp://localhost:61616");
PooledConnectionFactory pcf = new PooledConnectionFactory();

//Set expiry timeout because the default (0) prevents reconnection on failure
pcf.setExpiryTimeout(5000);
pcf.setConnectionFactory(cf);

JMSConfiguration jmsConfig = new JMSConfiguration();

jmsConfig.setConnectionFactory(pdf);

有关池的更多信息,请参阅红帽 JBoss Fuse 事务指南中的"Appendix A 优化 JMS Single- 和 Multiple-Resource Transactions"的性能

避免同步接收

对于请求/回复交换,JMS 传输会发送请求,然后等待回复。尽可能使用 JMS MessageListener 异步实施请求/回复消息传递。

但是,当需要在端点间共享队列时,CXF 必须使用同步的 Consumer.receive() 方法。此场景需要 MessageListener 来使用消息选择器来过滤消息。消息选择器必须预先识别,因此 MessageListener 只打开一次。

应该避免预先知道消息选择器的两个情况:

  • JMSMessageID 用作 JMSCorrelationID

    如果 JMS 属性使用 ConduitIdSelectorconduitSelectorPrefix,则客户端不会设置 JMS 传输,则客户端不会设置 JMSCorrelationId。这会导致服务器使用请求消息的 JMSMessageId 作为 JMSCorrelationId。因为 JMSMessageID 无法预先识别,客户端必须使用 synchronous Consumer.receive() 方法。

    请注意,您必须在 IBM JMS 端点(默认)中使用 Consumer.receive() 方法。

  • 用户在请求消息中设置 JMStype,然后设置自定义 JMSCorrelationID

    同样,因为不能提前知道自定义 JMSCorrelationID,客户端必须使用 synchronous Consumer.receive() 方法。

因此,一般规则是避免使用需要同步接收的设置。

14.4. 配置 JMS 事务

概述

CXF 3.0 在使用单向消息传递时,支持 CXF 端点上的本地 JMS 事务和 JTA 事务。

本地事务

只有在发生异常时,使用本地资源的事务才会回滚 JMS 消息。它们不直接协调其他资源,如数据库事务。

要设置本地事务,请根据需要配置端点,并将属性 sessionTrasnsacted 设置为 true

注意

有关事务和池的更多信息,请参阅红帽 JBoss Fuse 事务指南

JTA 事务

通过使用 JTA 事务,您可以协调任意数量的 XA 资源。如果为 JTA 事务配置了 CXF 端点,它会在调用服务实施前启动事务。如果没有异常,则事务将被提交。否则,它将被回滚。

在 JTA 事务中,使用 JMS 消息以及写入数据库的数据。发生异常时,两个资源都会回滚,因此消息被消耗,数据就会被写入数据库,或者信息被回滚,不会写入数据库。

配置 JTA 事务需要两个步骤:

  1. 定义事务管理器

    • bean 方法

      • 定义事务管理器

        <bean id="transactionManager"
           class="org.apache.geronimo.transaction.manager.GeronimoTransactionManager"/>
      • 在 JMS URI 中设置事务管理器的名称

        jms:queue:myqueue?jndiTransactionManager=TransactionManager

        这个示例找到了 ID TransactionManager 的 bean。

    • OSGi 参考方法

      • 使用 Blueprint 将事务管理器作为 OSGi 服务查找

        <reference id="TransactionManager" interface="javax.transaction.TransactionManager"/>
      • 在 JMS URI 中设置事务管理器的名称

        jms:jndi:myqueue?jndiTransactionManager=java:comp/env/TransactionManager

        本例在 JNDI 中查找事务管理器。

  2. 配置 JCA 池的连接工厂

    使用 Spring 定义 JCA 池的连接工厂:

    <bean id="xacf" class="org.apache.activemq.ActiveMQXAConnectionFactory">
      <property name="brokerURL" value="tcp://localhost:61616" />
    </bean>
    
    <bean id="ConnectionFactory" class="org.apache.activemq.jms.pool.JcaPooledConnectionFactory">
      <property name="transactionManager" ref="transactionManager" />
      <property name="connectionFactory" ref="xacf" />
    </bean>

    在本例中,第一个 bean 定义了一个 ActiveMQ XA 连接工厂,它被提供给 JcaPooledConnectionFactory。然后,JcaPooledConnectionFactory 作为默认的 bean 提供了 ID ConnectionFactory

    请注意,JcaPooledConnectionFactory 类似于普通的 ConnectionFactory。但是,打开新的连接和会话时,它会检查 XA 事务(如果找到)将 JMS 会话作为 XA 资源注册。这允许 JMS 会话参与 JMS 事务。

    重要

    对 JMS 传输直接设置 XA ConnectionFactory 无法正常工作!

14.5. 使用 WSDL 配置 JMS

14.5.1. JMS WSDL 扩展名称

用于定义 JMS 端点的 WSDL 扩展在命名空间 http://cxf.apache.org/transports/jms 中定义。要使用 JMS 扩展,您需要将 例 14.5 “JMS WSDL 扩展命名空间” 中显示的行添加到合同的定义元素中。

例 14.5. JMS WSDL 扩展命名空间

xmlns:jms="http://cxf.apache.org/transports/jms"

14.5.2. 基本 JMS 配置

概述

JMS 地址信息使用 jms:address 元素及其子项提供,即 jms:JMSNamingProperties 元素。jms:address 元素的属性指定识别 JMS 代理和目的地所需的信息。jms:JMSNamingProperties 元素指定用于连接 JNDI 服务的 Java 属性。

重要

使用 JMS 功能指定的信息将覆盖端点的 WSDL 文件中的信息。

指定 JMS 地址

JMS 端点的基本配置通过将 jms:address 元素用作 服务端口 元素的子项来完成。WSDL 中使用的 jms:address 元素与配置文件中使用的相同。其属性列在 表 14.2 “JMS 端点属性” 中。

表 14.2. JMS 端点属性

属性描述

destinationStyle

指定 JMS 目的地是否为 JMS 队列或 JMS 主题。

jndiConnectionFactoryName

指定连接到 JMS 目的地时要使用的 JMS 连接工厂的 JNDI 名称。

jmsDestinationName

指定将请求发送到的 JMS 目的地的名称。

jmsReplyDestinationName

指定发送回复的 JMS 目的地的 JMS 名称。此属性允许您使用用户定义的目的地来回复。详情请查看 第 14.6 节 “使用 Named Reply Destination”

jndiDestinationName

指定绑定到请求发送到的 JMS 目的地的 JNDI 名称。

jndiReplyDestinationName

指定与发送回复的 JMS 目的地的 JNDI 名称。此属性允许您使用用户定义的目的地来回复。详情请查看 第 14.6 节 “使用 Named Reply Destination”

connectionUserName

指定连接到 JMS 代理时使用的用户名。

connectionPassword

指定连接到 JMS 代理时使用的密码。

jms:address WSDL 元素使用 jms:JMSNamingProperties 子元素,以指定连接 JNDI 提供程序所需要的其他信息。

指定 JNDI 属性

为提高与 JMS 和 JNDI 提供程序的互操作性,jms:address 元素包含一个子元素( jms:JMSNamingProperties ),它允许您指定用于在连接 JNDI 提供程序时使用的属性的值。jms:JMSNamingProperties 元素具有两个属性,即 namevaluename 指定要设置的属性名称。value 属性指定指定的值。JMS:JMSNamingProperties 元素也可用于规范供应商特定属性。

以下是您可以设置的通用 JNDI 属性列表:

  1. java.naming.factory.initial
  2. java.naming.provider.url
  3. java.naming.factory.object
  4. java.naming.factory.state
  5. java.naming.factory.url.pkgs
  6. java.naming.dns.url
  7. java.naming.authoritative
  8. java.naming.batchsize
  9. java.naming.referral
  10. java.naming.security.protocol
  11. java.naming.security.authentication
  12. java.naming.security.principal
  13. java.naming.security.credentials
  14. java.naming.language
  15. java.naming.applet

有关这些属性中要使用的消息的更多详细信息,请检查您的 JNDI 供应商的文档,并查阅 Java API 参考材料。

示例

例 14.6 “JMS WSDL 端口规格” 显示 JMS WSDL 端口 规格的示例。

例 14.6. JMS WSDL 端口规格

<service name="JMSService">
  <port binding="tns:Greeter_SOAPBinding" name="SoapPort">
    <jms:address jndiConnectionFactoryName="ConnectionFactory"
                 jndiDestinationName="dynamicQueues/test.Celtix.jmstransport" >
      <jms:JMSNamingProperty name="java.naming.factory.initial"
                             value="org.activemq.jndi.ActiveMQInitialContextFactory" />
      <jms:JMSNamingProperty name="java.naming.provider.url"
                             value="tcp://localhost:61616" />
    </jms:address>
  </port>
</service>

14.5.3. JMS 客户端配置

概述

JMS 消费者端点指定它们所使用的消息类型。JMS 使用者端点可以使用 JMS ByteMessage 或 JMS TextMessage

在使用 ByteMessage 时,消费者端点使用 byte[] 作为数据存储在 JMS 邮件正文中的数据并检索数据。发送消息时,消息数据(包括任何格式信息)被打包成 字节[],并在将消息正文放置在线路上前将其放在消息正文中。收到消息时,使用者端点将尝试解包消息正文中存储的数据,就像将其打包在 字节[] 中一样。

在使用 text Message 时,使用者端点使用字符串作为来自消息正文的数据的方法。发送消息时,消息信息(包括任何格式的信息)将转换为字符串,并放入 JMS 消息正文。收到消息时,使用者端点将尝试解包在 JMS 消息正文中存储的数据,就像将其打包成字符串一样。

当原生 JMS 应用与 Apache CXF 消费者交互时,JMS 应用负责解释消息和格式化信息。例如,如果 Apache CXF 合同指定用于 JMS 端点的绑定是 SOAP,且消息将被打包为 text Message,接收 JMS 应用会得到一个包含所有 SOAP envelope 信息的文本信息。

指定消息类型

JMS 使用者端点接受的消息类型通过可选的 jms:client 元素进行配置。jms:client 元素是 WSDL 端口 元素的子项,并具有一条属性:

表 14.3. JMS 客户端 WSDL 扩展

messageType

指定消息数据如何打包为 JMS 消息。文本指定数据将打包为 text Message二进制文件 指定数据将打包为 ByteMessage

示例

例 14.7 “用于 JMS 消费者端点的 WSDL” 显示用于配置 JMS 消费者端点的 WSDL。

例 14.7. 用于 JMS 消费者端点的 WSDL

<service name="JMSService">
  <port binding="tns:Greeter_SOAPBinding" name="SoapPort">
    <jms:address jndiConnectionFactoryName="ConnectionFactory"
                 jndiDestinationName="dynamicQueues/test.Celtix.jmstransport" >
      <jms:JMSNamingProperty name="java.naming.factory.initial"
                             value="org.activemq.jndi.ActiveMQInitialContextFactory" />
      <jms:JMSNamingProperty name="java.naming.provider.url"
                             value="tcp://localhost:61616" />
    </jms:address>
    <jms:client messageType="binary" />
  </port>
</service>

14.5.4. JMS 提供程序配置

概述

JMS 提供程序端点具有许多可以配置的行为。它们是:

  • 如何关联消息
  • 使用持久订阅
  • 如果服务使用本地 JMS 事务
  • 端点使用的选择器

指定配置

提供商端点行为使用可选的 jms:server 元素进行配置。jms:server 元素是 WSDL wsdl:port 元素的子项,具有下列属性:

表 14.4. JMS 提供程序端点 WSDL 扩展

属性描述

useMessageIDAsCorrealationID

指定 JMS 是否将使用消息 ID 来关联消息。默认值为 false

durableSubscriberName

指定注册持久订阅的名称。

messageSelector

指定要使用的消息选择器的字符串值。有关使用指定选择器的语法的更多信息,请参阅 JMS 1.1 规格。

事务性

指定本地 JMS 代理是否围绕消息处理创建事务。默认值为 false[a]

[a] 目前,运行时不支持将 事务 属性设置为 true

示例

例 14.8 “用于 JMS 供应商端点的 WSDL” 显示用于配置 JMS 提供程序端点的 WSDL。

例 14.8. 用于 JMS 供应商端点的 WSDL

<service name="JMSService">
  <port binding="tns:Greeter_SOAPBinding" name="SoapPort">
    <jms:address jndiConnectionFactoryName="ConnectionFactory"
                 jndiDestinationName="dynamicQueues/test.Celtix.jmstransport" >
      <jms:JMSNamingProperty name="java.naming.factory.initial"
                             value="org.activemq.jndi.ActiveMQInitialContextFactory" />
      <jms:JMSNamingProperty name="java.naming.provider.url"
                             value="tcp://localhost:61616" />
    </jms:address>
    <jms:server messageSelector="cxf_message_selector"
                useMessageIDAsCorrelationID="true"
                transactional="true"
                durableSubscriberName="cxf_subscriber" />
  </port>
</service>

14.6. 使用 Named Reply Destination

概述

默认情况下,使用 JMS 的 Apache CXF 端点创建一个临时队列来回发送回复。如果要使用命名队列,您可以配置用于将回复作为端点 JMS 配置的一部分来发送回复的队列。

设置回复目的地名称

您可以使用端点的 JMS 配置中的 jmsReplyDestinationName 属性或 jndiReplyDestinationName 属性来指定回复目的地。客户端端点将侦听指定的目的地的回复,它将在所有传出请求的 ReplyTo 字段中指定 属性的值。服务端点将使用 jndiReplyDestinationName 属性的值,当请求的 ReplyTo 字段中没有指定目的地时,将放置回复的位置。

示例

例 14.9 “使用 Named Reply Queue 的 JMS Consumer 规格” 显示 JMS 客户端端点的配置。

例 14.9. 使用 Named Reply Queue 的 JMS Consumer 规格

<jms:conduit name="{http://cxf.apache.org/jms_endpt}HelloWorldJMSPort.jms-conduit">
    <jms:address destinationStyle="queue"
                 jndiConnectionFactoryName="myConnectionFactory"
                 jndiDestinationName="myDestination"
                 jndiReplyDestinationName="myReplyDestination" >
      <jms:JMSNamingProperty name="java.naming.factory.initial"
                             value="org.apache.cxf.transport.jms.MyInitialContextFactory" />
      <jms:JMSNamingProperty name="java.naming.provider.url"
                             value="tcp://localhost:61616" />
    </jms:address>
  </jms:conduit>

第 15 章 与 Apache ActiveMQ 集成

概述

如果您将 Apache ActiveMQ 用作 JMS 提供程序,则以特殊格式指定您的目的地的 JNDI 名称,可以动态为队列或主题创建 JNDI 绑定。这意味着 不需要使用 您的队列或主题的 JNDI 绑定来配置 JMS 供应商。

初始上下文工厂

将 Apache ActiveMQ 与 JNDI 集成的关键在于 ActiveMQInitialContextFactory 类。此类用于创建 JNDI InitialContext 实例,然后使用它访问 JMS 代理中的 JMS 目的地。

例 15.1 “SOAP/JMS WSDL 以连接到 Apache ActiveMQ” 显示 SOAP/JMS WSDL 扩展,以创建与 Apache ActiveMQ 集成的 JNDI InitialContext

例 15.1. SOAP/JMS WSDL 以连接到 Apache ActiveMQ

<soapjms:jndiInitialContextFactory>
  org.apache.activemq.jndi.ActiveMQInitialContextFactory
</soapjms:jndiInitialContextFactory>
<soapjms:jndiURL>tcp://localhost:61616</soapjms:jndiURL>

例 15.1 “SOAP/JMS WSDL 以连接到 Apache ActiveMQ” 中,Apache ActiveMQ 客户端连接到位于 tcp://localhost:61616 的代理端口。

查找连接工厂

除了创建 JNDI InitialContext 实例外,您必须指定绑定到 javax.jms.ConnectionFactory 实例的 JNDI 名称。对于 Apache ActiveMQ,InitialContext 实例中有一个预定义绑定,它会将 JNDI 名称 ConnectionFactory 映射到 ActiveMQConnectionFactory 实例。例 15.2 “用于指定 Apache ActiveMQ 连接工厂的 SOAP/JMS WSDL” 控制 SOAP/JMS 扩展元素,用于指定 Apache ActiveMQ 连接工厂。

例 15.2. 用于指定 Apache ActiveMQ 连接工厂的 SOAP/JMS WSDL

<soapjms:jndiConnectionFactoryName>
  ConnectionFactory
</soapjms:jndiConnectionFactoryName>

动态目的地的语法

要动态访问队列或主题,请使用以下格式将目的地的 JNDI 名称指定为 JNDI 复合名称:

dynamicQueues/QueueName
dynamicTopics/TopicName

QueueNameTopicName 是 Apache ActiveMQ 代理使用的名称。它们没有 抽象 JNDI 名称。

例 15.3 “带有动态创建队列的 WSDL 端口规格” 显示使用动态创建队列的 WSDL 端口。

例 15.3. 带有动态创建队列的 WSDL 端口规格

<service name="JMSService">
  <port binding="tns:GreeterBinding" name="JMSPort">
    <jms:address jndiConnectionFactoryName="ConnectionFactory"
                 jndiDestinationName="dynamicQueues/greeter.request.queue" >
      <jms:JMSNamingProperty name="java.naming.factory.initial"
                             value="org.activemq.jndi.ActiveMQInitialContextFactory" />
      <jms:JMSNamingProperty name="java.naming.provider.url"
                             value="tcp://localhost:61616" />
    </jms:address>
  </port>
</service>

当应用尝试打开 JMS 连接时,Apache ActiveMQ 将检查是否存在 JNDI 名称为 greeter.request.queue 的队列。如果不存在,它将创建一个新的队列,并将其绑定到 JNDI 名称 greeter.request.queue

第 16 章 conduits

摘要

不同的是实施出站连接的传输架构的低级别部分。其行为和生命周期可影响系统性能并处理负载。

概述

在 Apache CXF 运行时,管理客户端或出站传输详情。它们负责打开端口、建立出站连接、发送消息和侦听应用程序与单个外部端点之间的任何响应。如果应用程序连接到多个端点,它将为每个端点有一个双重实例。

每种传输类型使用 Conduit 接口实施自己的一致性。这允许应用程序级别功能和传输间的标准化接口。

通常,您只需要在配置客户端传输详情时考虑应用程序所使用的内容。运行时如何处理 conduits 的底层语义是,并非开发人员需要担心的。

但是,当了解 conduit 时,会非常有用:

  • 实施自定义传输
  • 管理有限资源的高级应用程序调整

conduit 生命周期

conduits 由客户端实施对象管理。创建之后,在客户端实施对象期间持续存在。conduit 的生命周期为:

  1. 创建客户端实现对象时,会获得对 ConduitSelector 对象的引用。
  2. 当客户端需要发送消息时,请求来自 conduit 选择器对 conduit 的引用。

    如果消息用于新端点,则 conduit 选择器会创建一个新的 conduit,并将其传递给客户端实施。否则,它会将客户端的引用传递给目标端点的 conduit。

  3. 在需要时发送信息。
  4. 当客户端实现对象被销毁时,与其关联的所有步骤都会被销毁。

conduit weight

conduit 对象的 weight 取决于传输实施。HTTP conduits 非常轻便的权重。JMS conduits 非常重,因为它们与 JMS Session 对象和一个或多个 JMSListenerContainer 对象关联。

部分 IV. 配置 Web 服务端点

本指南论述了如何在 Red Hat Fuse 中创建 Apache CXF 端点。

第 17 章 配置 JAX-WS 端点

摘要

使用三个 Spring 配置元素之一来配置 JAX-WS 端点。正确的元素取决于您配置的端点的类型以及您想要使用哪些功能。对于消费者,您可以使用 jaxws:client 元素。对于服务提供商,您可以使用 jaxws:endpoint 元素或 jaxws:server 元素。

用于定义端点的信息通常在端点的合同中定义。您可以使用配置元素来覆盖合同中的信息。您还可以使用配置元素提供合同中未提供的信息。

您必须使用配置元素激活一些高级功能,如 WS-RM。这可以通过为端点的配置元素提供子元素来实现。请注意,当处理使用 Java 优先方法开发的端点时,SEI 服务可能会因为端点的合同缺乏与要使用的绑定和传输有关的信息。

17.1. 配置服务供应商

17.1.1. 配置服务提供程序的元素

Apache CXF 有两个可用于配置服务供应商的元素:

两个元素之间的区别对于运行时主要是内部的。jaxws:endpoint 元素将属性注入 org.apache.cxf.jaxws.EndpointImpl 对象来支持服务端点。jaxws:server 元素将属性注入 org.apache.cxf.jaxws.support.support.JaxWsServerFactoryBean 对象来支持端点。EndpointImpl 对象将配置数据传递给 JaxWsServerFactoryBean 对象。JaxWsServerFactoryBean 对象用于创建实际服务对象。由于任一配置元素都会配置服务端点,您可以根据您首选的语法进行选择。

17.1.2. 使用 jaxws:endpoint Element

概述

jaxws:endpoint 元素是配置 JAX-WS 服务提供商的默认元素。其属性和子项指定实例化服务提供商所需的所有信息。许多属性映射到服务的合同中信息。子项用于配置拦截器和其他高级功能。

识别正在配置的端点

要使运行时将配置应用到正确的服务提供商,它必须能够识别它。识别服务提供商的基本方法是指定实施端点的类。这使用 jaxws:endpoint 元素的 implements or 属性来完成。

对于不同端点共享通用实现的实例,可以为每个端点提供不同的配置。有两种方法来区分配置中的特定端点:

  • serviceName 属性和 endpointName 属性的组合

    serviceName 属性指定定义该服务端点的 wsdl:service 元素。endpointName 属性指定定义服务端点的特定 wsdl:port 元素。这两个属性都使用 ns:name 的格式指定为 QNames。ns 是元素的命名空间,name 是元素的 name 属性的值。

    注意

    如果 wsdl:service 元素只有一个 wsdl:port 元素,可以省略 endpointName 属性。

  • name 属性

    name 属性指定定义服务端点的特定 wsdl:port 元素的 QName。QName 以 {ns}localPart格式提供nswsdl:port 元素的命名空间,localPartwsdl:port 元素的 name 属性的值。

属性

jaxws:endpoint 元素的属性配置端点的基本属性。这些属性包括端点的地址、实施端点的类以及托管端点的 总线

表 17.1 “使用 jaxws:endpoint Element 配置 JAX-WS 服务提供商的属性” 描述 jaxws:endpoint 元素的属性。

表 17.1. 使用 jaxws:endpoint Element 配置 JAX-WS 服务提供商的属性

属性描述

id

指定其他配置元素可用于引用端点的唯一标识符。

implementor

指定实施该服务的类。您可以使用类名称或 Spring bean 配置实施类类来指定实施类。此类必须在 classpath 上。

implementorClass

指定实施该服务的类。当提供给 implementor 属性的值作为使用 Spring AOP 包装的 bean 的引用时,此属性很有用。

address

指定 HTTP 端点的地址。这个值会覆盖服务合同中指定的值。

wsdlLocation

指定端点的 WSDL 合同的位置。WSDL 合同的位置相对于部署服务的文件夹。

endpointName

指定服务 wsdl:port 元素的 name 属性的值。它被指定为 QName,格式为 ns:name,其中 nswsdl:port 元素的命名空间。

serviceName

指定服务 wsdl:service 元素的 name 属性的值。它被指定为 QName,格式为 ns:name,其中 nswsdl:service 元素的命名空间。

publish

指定是否应该自动发布该服务。如果此项设为 false,则开发人员必须明确发布 第 31 章 发布服务 中描述的端点。

总线

指定 Spring Bean 的 ID,配置用于管理服务端点的总线。这在将多个端点配置为使用一组通用的功能时,这很有用。

bindingUri

指定服务使用的消息绑定 ID。第 23 章 Apache CXF Binding ID 中提供了有效绑定 ID 列表。

name

指定服务 wsdl:port 元素的字符串指定 QName。它使用 {ns}localPart 格式指定为 QName。nswsdl:port 元素的命名空间,localPartwsdl:port 元素的 name 属性的值。

abstract

指定 bean 是否为抽象 bean。abstract Bean 充当拥塞 Bean 定义且没有实例化的父项。默认值为 false。将其设置为 true 指示 bean 工厂不会实例化 bean。

dependent-on

指定在端点实例化前端点要实例化的 Bean 列表。

createdFromAPI

指定使用 Apache CXF API 创建的用户,如 Endpoint.publish()Service.getPort()

默认值为 false

将其设置为 true 执行以下操作:

  • 通过将 .jaxws-endpoint 附加到其 id 来修改 bean 的内部名称
  • 使 bean 摘要

publishedEndpointUrl

放置在生成的 WSDL 的 address 元素中的 URL。如果没有指定这个值,则使用 address 属性的值。当 "public" URL 与部署该服务的 URL 不同时,此属性很有用。

除了 表 17.1 “使用 jaxws:endpoint Element 配置 JAX-WS 服务提供商的属性” 中列出的属性,您可能需要使用多个 ns:shortName属性来 声明 endpointNameserviceName 属性使用的命名空间。

示例

例 17.1 “简单的 JAX-WS 端点配置” 显示 JAX-WS 端点的配置,用于指定发布端点的地址。这个示例假定您要对所有其他值使用默认值,或者实现在注解中指定了值。

例 17.1. 简单的 JAX-WS 端点配置

<beans ...
  xmlns:jaxws="http://cxf.apache.org/jaxws"
  ...
  schemaLocation="...
    http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
    ...">
  <jaxws:endpoint id="example"
                  implementor="org.apache.cxf.example.DemoImpl"
                  address="http://localhost:8080/demo" />
</beans>

例 17.2 “带有服务名称的 JAX-WS 端点配置” 显示 JAX-WS 端点的配置,其合同包含两个服务定义。在这种情况下,您必须指定要使用 serviceName 属性来实例化哪个服务定义。

例 17.2. 带有服务名称的 JAX-WS 端点配置

<beans ...
  xmlns:jaxws="http://cxf.apache.org/jaxws"
  ...
  schemaLocation="...
    http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
    ...">

  <jaxws:endpoint id="example2"
                  implementor="org.apache.cxf.example.DemoImpl"
                  serviceName="samp:demoService2"
                  xmlns:samp="http://org.apache.cxf/wsdl/example" />

</beans>

xmlns:samp 属性指定定义了 WSDL 服务 元素的命名空间。

例 17.3 “启用 HTTP/2 的 JAX-WS 端点配置” 显示 JAX-WS 端点的配置,该端点指定启用了 HTTP/2 的地址。

为 Apache CXF 配置 HTTP/2

在 Apache Karaf 上使用独立 Apache CXF Undertow 传输(http-undertow)时,支持 HTTP/2。要启用 HTTP/2 协议,您必须将 jaxws:endpoint 元素的 address 属性设置为绝对 URL,并将 org.apache.cxf.transports.http_undertow.EnableHttp2 属性设为 true

注意

这个 HTTP/2 的实现只支持使用普通 HTTP 或 HTTPS 的服务器端 HTTP/2 传输。

例 17.3. 启用 HTTP/2 的 JAX-WS 端点配置

<beans ...
  xmlns:jaxws="http://cxf.apache.org/jaxws"
  ...
  schemaLocation="...
  http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
  ...">

  <cxf:bus>
    <cxf:properties>
        <entry key="org.apache.cxf.transports.http_undertow.EnableHttp2" value="true"/>
    </cxf:properties>
  </cxf:bus>

  <jaxws:endpoint id="example3"
                implementor="org.apache.cxf.example.DemoImpl"
                address="http://localhost:8080/demo" />
  </jaxws:endpoint>

</beans>
注意

为了提高性能,红帽建议在 Apache Karaf 上使用 servlet 传输(pax-web-undertow),这样可启用对 web 容器的集中配置和调优,但 pax-web-undertow 不支持 HTTP/2 传输协议。

17.1.3. 使用 jaxws:server Element

概述

jaxws:server 元素是配置 JAX-WS 服务提供商的一个元素。它将配置信息注入到 org.apache.cxf.jaxws.support.JaxWsServerFactoryBean。这是 Apache CXF 特定对象。如果您使用纯 Spring 方法来构建服务,则不会强制使用 Apache CXF 特定 API 与服务交互。

jaxws:server 元素的属性和子项指定实例化服务提供商所需的所有信息。属性指定实例化端点所需的信息。子项用于配置拦截器和其他高级功能。

识别正在配置的端点

要使运行时将配置应用到正确的服务提供商,它必须能够识别它。识别服务提供商的基本方法是指定实施端点的类。这可以通过 jaxws:server 元素的 serviceBean 属性来完成。

对于不同端点共享通用实现的实例,可以为每个端点提供不同的配置。有两种方法来区分配置中的特定端点:

  • serviceName 属性和 endpointName 属性的组合

    serviceName 属性指定定义该服务端点的 wsdl:service 元素。endpointName 属性指定定义服务端点的特定 wsdl:port 元素。这两个属性都使用 ns:name 的格式指定为 QNames。ns 是元素的命名空间,name 是元素的 name 属性的值。

    注意

    如果 wsdl:service 元素只有一个 wsdl:port 元素,可以省略 endpointName 属性。

  • name 属性

    name 属性指定定义服务端点的特定 wsdl:port 元素的 QName。QName 以 {ns}localPart格式提供nswsdl:port 元素的命名空间,localPartwsdl:port 元素的 name 属性的值。

属性

jaxws:server 元素的属性配置端点的基本属性。这些属性包括端点的地址、实施端点的类以及托管端点的 总线

表 17.2 “使用 jaxws:server Element 配置 JAX-WS 服务提供商的属性” 描述 jaxws:server 元素的属性。

表 17.2. 使用 jaxws:server Element 配置 JAX-WS 服务提供商的属性

属性描述

id

指定其他配置元素可用于引用端点的唯一标识符。

serviceBean

指定实施该服务的类。您可以使用类名称或 Spring bean 配置实施类类来指定实施类。此类必须在 classpath 上。

serviceClass

指定实施该服务的类。当提供给 implementor 属性的值作为使用 Spring AOP 包装的 bean 的引用时,此属性很有用。

address

指定 HTTP 端点的地址。这个值将覆盖服务合同中指定的值。

wsdlLocation

指定端点的 WSDL 合同的位置。WSDL 合同的位置相对于部署服务的文件夹。

endpointName

指定服务 wsdl:port 元素的 name 属性的值。它被指定为 QName,格式为 ns:name,其中 nswsdl:port 元素的命名空间。

serviceName

指定服务 wsdl:service 元素的 name 属性的值。它被指定为 QName,格式为 ns:name,其中 nswsdl:service 元素的命名空间。

publish

指定是否应该自动发布该服务。如果此项设为 false,则开发人员必须明确发布 第 31 章 发布服务 中描述的端点。

总线

指定 Spring Bean 的 ID,配置用于管理服务端点的总线。这在将多个端点配置为使用一组通用的功能时,这很有用。

bindingId

指定服务使用的消息绑定 ID。第 23 章 Apache CXF Binding ID 中提供了有效绑定 ID 列表。

name

指定服务 wsdl:port 元素的字符串指定 QName。它被指定为 QName,格式为 {ns}localPart,其中 nswsdl:port 元素的命名空间,localPartwsdl:port 元素的 name 属性的值。

abstract

指定 bean 是否为抽象 bean。abstract Bean 充当拥塞 Bean 定义且没有实例化的父项。默认值为 false。将其设置为 true 指示 bean 工厂不会实例化 bean。

dependent-on

指定在端点实例化前端点要实例化的 Bean 列表。

createdFromAPI

指定使用 Apache CXF API 创建的用户,如 Endpoint.publish()Service.getPort()

默认值为 false

将其设置为 true 执行以下操作:

  • 通过将 .jaxws-endpoint 附加到其 id 来修改 bean 的内部名称
  • 使 bean 摘要

除了 表 17.2 “使用 jaxws:server Element 配置 JAX-WS 服务提供商的属性” 中列出的属性,您可能需要使用多个 ns:shortName属性来 声明 endpointNameserviceName 属性使用的命名空间。

示例

例 17.4 “简单的 JAX-WS 服务器配置” 显示 JAX-WS 端点的配置,用于指定发布端点的地址。

例 17.4. 简单的 JAX-WS 服务器配置

<beans ...
  xmlns:jaxws="http://cxf.apache.org/jaxws"
  ...
  schemaLocation="...
    http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
    ...">
  <jaxws:server id="exampleServer"
                  serviceBean="org.apache.cxf.example.DemoImpl"
                  address="http://localhost:8080/demo" />
</beans>

17.1.4. 为服务提供商添加功能

概述

jaxws:endpointjaxws:server 元素提供实例化服务提供商所需的基本配置信息。要向服务提供商添加功能或执行高级配置,您必须将子元素添加到配置中。

子元素允许您进行以下操作:

元素

表 17.3 “用于配置 JAX-WS 服务提供程序的元素” 描述 jaxws:endpoint 支持的子元素。

表 17.3. 用于配置 JAX-WS 服务提供程序的元素

元素描述

jaxws:handlers

指定用于处理消息的 JAX-WS Handler 实施列表。有关 JAX-WS Handler 实施的更多信息,请参阅 第 43 章 编写处理程序

jaxws:inInterceptors

指定处理入站请求的拦截器列表。更多信息请参阅 第 VII 部分 “开发 Apache CXF Interceptors”

jaxws:inFaultInterceptors

指定处理入站错误信息的拦截器列表。更多信息请参阅 第 VII 部分 “开发 Apache CXF Interceptors”

jaxws:outInterceptors

指定处理出站回复的拦截器列表。更多信息请参阅 第 VII 部分 “开发 Apache CXF Interceptors”

jaxws:outFaultInterceptors

指定处理出站错误信息的拦截器列表。更多信息请参阅 第 VII 部分 “开发 Apache CXF Interceptors”

jaxws:binding

指定 bean 配置端点使用的消息绑定。使用 org.apache.cxf.binding.Binding factory 接口的实现来配置消息绑定。[a]

jaxws:dataBinding [b]

指定实施端点使用的数据绑定的类。这使用嵌入式 bean 定义进行指定。

jaxws:executor

指定用于该服务的 Java 执行程序。这使用嵌入式 bean 定义进行指定。

jaxws:features

指定 Beans 列表,用于配置 Apache CXF 的高级功能。您可以提供 bean 引用列表或嵌入式 Bean 列表。

jaxws:invoker

指定服务使用的 org.apache.cxf.service.Invoker 接口的实施。 [c]

jaxws:properties

指定传递给端点的属性的 Spring 映射。这些属性可用于控制启用 MTOM 支持等功能。

jaxws:serviceFactory

指定 Bean 配置用于实例化该服务的 JaxWsServiceFactoryBean 对象。

[a] SOAP 绑定使用 soap: SOApBinding bean 进行配置。
[b] jaxws:endpoint 元素不支持 jaxws:dataBinding 元素。
[c] Invoker 实施控制如何调用服务。例如,它控制每个请求是否由服务实施的新实例处理,或在调用中保留状态。

17.1.5. 在 JAX-WS 端点上启用 Schema 验证

概述

您可以将 schema-validation-enabled 属性设置为在 jaxws:endpoint 元素上启用 schema 验证,或者在 jaxws:server 元素中启用 schema 验证。启用 schema 验证后,检查客户端和服务器间发送的消息,以符合 schema。默认情况下关闭 schema 验证,因为它对性能有显著影响。

示例

要在 JAX-WS 端点上启用架构验证,请在 jaxws:properties 子元素或 jaxws:server 元素中设置 schema-validation-enabled 属性。例如,要在 jaxws:endpoint 元素中启用 schema 验证:

<jaxws:endpoint name="{http://apache.org/hello_world_soap_http}SoapPort"
    wsdlLocation="wsdl/hello_world.wsdl"
    createdFromAPI="true">
    <jaxws:properties>
        <entry key="schema-validation-enabled" value="BOTH" />
    </jaxws:properties>
</jaxws:endpoint>

有关 schema-validation-enabled 属性的允许值列表,请参阅 第 24.3.4.7 节 “架构验证类型值”

17.2. 配置 Consumer 端点

概述

JAX-WS 消费者端点使用 jaxws:client 元素进行配置。元素的属性提供了创建消费者所需的基本信息。

要将其他功能(如 WS-RM)添加到添加到 jaxws:client 元素的使用者。子元素也用于配置端点的日志记录行为,并将其他属性注入到端点的实施中。

基本配置属性

表 17.4 “用于配置 JAX-WS Consumer 的属性” 中描述的属性提供了配置 JAX-WS 消费者所需的基本信息。您只需要为您要配置的特定属性提供值。大多数属性都有可识别的默认值,或者它们依赖于端点合同提供的信息。

表 17.4. 用于配置 JAX-WS Consumer 的属性

属性描述

address

指定消费者发出请求的端点的 HTTP 地址。这个值覆盖合同中设定的值。

bindingId

指定消费者使用的消息绑定 ID。第 23 章 Apache CXF Binding ID 中提供了有效绑定 ID 列表。

总线

指定 Spring bean 配置总线管理端点的 ID。

endpointName

指定消费者发出请求的服务的 wsdl:port 元素的 name 属性的值。它被指定为 QName,格式为 ns:name,其中 nswsdl:port 元素的命名空间。

serviceName

指定消费者发出请求的服务的 wsdl:service 元素的 name 属性的值。它被指定为 QName,格式为 ns:name,其中 nswsdl:service 元素的命名空间。

username

指定用于简单用户名/密码身份验证的用户名。

password

指定用于简单用户名/密码验证的密码。

serviceClass

指定服务端点接口(SEI)的名称。

wsdlLocation

指定端点的 WSDL 合同的位置。WSDL 合同的位置相对于部署客户端的文件夹。

name

指定消费者发出请求的服务的 wsdl:port 元素的字符串指定。它被指定为 QName,格式为 {ns}localPart,其中 nswsdl:port 元素的命名空间,localPartwsdl:port 元素的 name 属性的值。

abstract

指定 bean 是否为抽象 bean。abstract Bean 充当拥塞 Bean 定义且没有实例化的父项。默认值为 false。将其设置为 true 指示 bean 工厂不会实例化 bean。

dependent-on

指定在端点实例化前端点要实例化的 Bean 列表。

createdFromAPI

指定使用了 Apache CXF API(如 Service.getPort() )创建的用户。

默认值为 false

将其设置为 true 执行以下操作:

  • 通过将 .jaxws-client 附加到其 id 来修改 bean 的内部名称
  • 使 bean 摘要

除了 表 17.4 “用于配置 JAX-WS Consumer 的属性” 中列出的属性,可能需要使用多个 xmlns:shortName 属性来声明 endpointNameserviceName 属性使用的命名空间。

添加功能

要为消费者添加功能或执行高级配置,您必须将子元素添加到配置中。

子元素允许您进行以下操作:

表 17.5 “配置消费者端点的元素” 描述可用于配置 JAX-WS 消费者的子元素。

表 17.5. 配置消费者端点的元素

元素描述

jaxws:binding

指定 bean 配置端点使用的消息绑定。使用 org.apache.cxf.binding.Binding factory 接口的实现来配置消息绑定。[a]

jaxws:dataBinding

指定实施端点使用的数据绑定的类。您使用嵌入式 bean 定义来指定此值。实施 JAXB 数据源的类是 org.apache.cxf.jaxb.JAXBDataBinding

jaxws:features

指定 Beans 列表,用于配置 Apache CXF 的高级功能。您可以提供 bean 引用列表或嵌入式 Bean 列表。

jaxws:handlers

指定用于处理消息的 JAX-WS Handler 实施列表。有关 JAX-WS Handler 实现的更多信息,请参阅 第 43 章 编写处理程序

jaxws:inInterceptors

指定进程入站响应的拦截器列表。更多信息请参阅 第 VII 部分 “开发 Apache CXF Interceptors”

jaxws:inFaultInterceptors

指定处理入站错误信息的拦截器列表。更多信息请参阅 第 VII 部分 “开发 Apache CXF Interceptors”

jaxws:outInterceptors

指定处理出站请求的拦截器列表。更多信息请参阅 第 VII 部分 “开发 Apache CXF Interceptors”

jaxws:outFaultInterceptors

指定处理出站错误信息的拦截器列表。更多信息请参阅 第 VII 部分 “开发 Apache CXF Interceptors”

jaxws:properties

指定传递给端点的属性映射。

jaxws:conduitSelector

指定一个 org.apache.cxf.endpoint.ConduitSelector 实现,供客户端使用。ConduitSelector 实施将覆盖用来选择用于处理出站请求的 Conduit 对象的默认进程。

[a] SOAP 绑定使用 soap: SOApBinding bean 进行配置。

示例

例 17.5 “简单消费者配置” 显示了简单的使用者配置。

例 17.5. 简单消费者配置

<beans ...
  xmlns:jaxws="http://cxf.apache.org/jaxws"
  ...
  schemaLocation="...
    http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
    ...">
  <jaxws:client id="bookClient"
                serviceClass="org.apache.cxf.demo.BookClientImpl"
                address="http://localhost:8080/books"/>
  ...
</beans>

在 JAX-WS 消费者上启用架构验证

要在 JAX-WS 使用者上启用架构验证,请在 jaxws:properties 子元素中设置 schema-validation-enabled 属性,例如:

<jaxws:client name="{http://apache.org/hello_world_soap_http}SoapPort"
    createdFromAPI="true">
    <jaxws:properties>
        <entry key="schema-validation-enabled" value="BOTH" />
    </jaxws:properties>
</jaxws:client>

有关 schema-validation-enabled 属性的允许值列表,请参阅 第 24.3.4.7 节 “架构验证类型值”

第 18 章 配置 JAX-RS 端点

摘要

本章论述了如何在 Blueprint XML 和 Spring XML 中实例化和配置 JAX-RS 服务器端点,以及如何在 XML 中实例化和配置 JAX-RS 客户端端点(客户端代理 Bean)

18.1. 配置 JAX-RS 服务器端点

18.1.1. 定义 JAX-RS 服务器端点

基本服务器端点定义

要在 XML 中定义 JAX-RS 服务器端点,您需要至少指定以下内容:

  1. jaxrs:server 元素,用于定义 XML 中的端点。请注意,jaxrs: 命名空间前缀分别映射到 Blueprint 和 Spring 中的不同命名空间。
  2. 使用 jaxrs:server 元素的地址属性的 JAX-RS 服务的基本 URL。请注意,有两种不同的方法来指定地址 URL,这会影响端点的部署方式:

    • 作为相对 URL- 例如: /customers。在本例中,端点被部署到默认的 HTTP 容器中,通过将 CXF servlet 基本 URL 与指定的相对 URL 相结合,端点的基本 URL 会被隐式获得。

      例如,如果您将 JAX-RS 端点部署到 Fuse 容器,则指定的 /customers URL 将解析为 URL http://Hostname:8181/cxf/customers (假设容器使用默认的 8181 端口)。

    • 作为绝对 URL 10.10.10.2-sHistoryLimit,例如 http://0.0.0.0:8200/cxf/customers。在本例中,为 JAX-RS 端点打开一个新的 HTTP 侦听器端口(如果尚未打开)。例如,在 Fuse 上下文中,会隐式创建新的 Undertow 容器以托管 JAX-RS 端点。特殊的 IP 地址 0.0.0.0 充当通配符,匹配分配给当前主机的任何主机名(对于多设备主机机器很有用)。
  3. 一个或多个 JAX-RS 根资源类,提供 JAX-RS 服务的实施。指定资源类的最简单方法是在 jaxrs:serviceBeans 元素内列出它们。

蓝图示例

以下 Blueprint XML 示例演示了如何定义 JAX-RS 端点,该端点指定相对地址 /customers (因此将其部署到默认 HTTP 容器)并由 service.CustomerService 资源类实施:

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:jaxrs="http://cxf.apache.org/blueprint/jaxrs"
    xmlns:cxf="http://cxf.apache.org/blueprint/core"
    xsi:schemaLocation="
http://www.osgi.org/xmlns/blueprint/v1.0.0 https://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
http://cxf.apache.org/blueprint/jaxrs http://cxf.apache.org/schemas/blueprint/jaxrs.xsd
http://cxf.apache.org/blueprint/core http://cxf.apache.org/schemas/blueprint/core.xsd
">

    <cxf:bus>
        <cxf:features>
            <cxf:logging/>
        </cxf:features>
    </cxf:bus>

     <jaxrs:server id="customerService" address="/customers">
        <jaxrs:serviceBeans>
           <ref component-id="serviceBean" />
        </jaxrs:serviceBeans>
     </jaxrs:server>

     <bean id="serviceBean" class="service.CustomerService"/>
</blueprint>

蓝图 XML 命名空间

要在 Blueprint 中定义 JAX-RS 端点,通常需要以下 XML 命名空间:

Spring 示例

以下 Spring XML 示例演示了如何定义 JAX-RS 端点,用于指定相对地址 /customers (因此将其部署到默认 HTTP 容器)并由 服务实施。CustomerService 资源类:

<beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:jaxrs="http://cxf.apache.org/jaxrs"
      xsi:schemaLocation="
         http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
         http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd">

     <jaxrs:server id="customerService" address="/customers">
        <jaxrs:serviceBeans>
           <ref bean="serviceBean"/>
        </jaxrs:serviceBeans>
     </jaxrs:server>

     <bean id="serviceBean" class="service.CustomerService"/>
</beans>

Spring XML 命名空间

要在 Spring 中定义 JAX-RS 端点,通常需要以下 XML 命名空间:

Spring XML 中的自动发现

(仅) 明确指定 JAX-RS 根资源类,Spring XML 可让您配置自动发现,以便搜索特定 Java 软件包以获取资源类(由 @Path标注的类),并且所有发现的资源类都自动附加到端点。在这种情况下,您需要在 jaxrs:server 元素中仅指定 address 属性和 basePackages 属性。

例如,若要定义使用 a.b.c Java 软件包下的所有 JAX-RS 资源类的 JAX-RS 端点,您可以在 Spring XML 中定义端点,如下所示:

<jaxrs:server address="/customers" basePackages="a.b.c"/>

自动发现机制还会发现并安装到端点,在其在指定的 Java 软件包下找到的任何 JAX-RS 提供程序类。

Spring XML 中的生命周期管理

(仅限 Spring XML) 通过设置 bean 元素上的 scope 属性来控制 Bean 的生命周期。Spring 支持以下范围值:

单例
(默认) 创建一个单个 bean 实例,该实例在 Spring 容器的整个生命周期中使用。
prototype
每次将 bean 注入到另一个 bean 或 bean 获取 bean 时,或通过调用 bean registry 上的 getBean() 来新建一个 bean 实例。
Request(请求)
(仅适用于 Web 感知型容器) 为 Bean 上调用的每个请求创建一个新的 bean 实例。
session
(只在一个 Web 感知容器中可用) 为单个 HTTP 会话生命周期创建一个新 Bean。
globalSession
(只在一个 Web 感知容器中可用) 为在 portlet 之间共享的单个 HTTP 会话的生命周期创建一个新 Bean。

如需有关 Spring 范围的更多详细信息,请参阅有关 Bean 范围的 Spring 框架文档。

请注意,如果您通过 jaxrs:serviceBeans 元素指定 JAX-RS 资源 Bean,Spring 范围 无法正常工作。如果您在此例中指定 resource Bean 上的 scope 属性,则 scope 属性将有效忽略。

要让 bean 范围在 JAX-RS 服务器端点内正常工作,您需要一个由服务工厂提供的间接级别。配置 bean 范围的最简单方法是使用 jaxrs:server 元素上的 beanNames 属性来指定 resourceanNames 属性,如下所示:

<beans ... >
  <jaxrs:server id="customerService" address="/service1"
    beanNames="customerBean1 customerBean2"/>

  <bean id="customerBean1" class="demo.jaxrs.server.CustomerRootResource1" scope="prototype"/>
  <bean id="customerBean2" class="demo.jaxrs.server.CustomerRootResource2"  scope="prototype"/>
</beans>

上一示例配置两个资源 Bean,即 customerBean1customerBean2beanNames 属性指定为空格分隔的资源 bean ID 列表。

为了获得灵活性,您可以 显式 定义服务工厂对象的选项,当您使用 jaxrs:serviceFactories 元素配置 JAX-RS 服务器端点时。这种更详细的方法有优势,您可以将默认服务工厂实施替换为您的自定义实施,从而让您最终掌控 bean 生命周期。以下示例演示了如何使用此方法配置两个资源 Bean、customerBean1customerBean2

<beans ... >
  <jaxrs:server id="customerService" address="/service1">
    <jaxrs:serviceFactories>
      <ref bean="sfactory1" />
      <ref bean="sfactory2" />
    </jaxrs:serviceFactories>
  </jaxrs:server>

  <bean id="sfactory1" class="org.apache.cxf.jaxrs.spring.SpringResourceFactory">
     <property name="beanId" value="customerBean1"/>
  </bean>
  <bean id="sfactory2" class="org.apache.cxf.jaxrs.spring.SpringResourceFactory">
     <property name="beanId" value="customerBean2"/>
  </bean>

  <bean id="customerBean1" class="demo.jaxrs.server.CustomerRootResource1" scope="prototype"/>
  <bean id="customerBean2" class="demo.jaxrs.server.CustomerRootResource2"  scope="prototype"/>
</beans>
注意

如果您指定了非单例生命周期,则通常最好实施和注册 org.apache.cxf.service.Invoker bean(其中,可以通过引用来自 jaxrs:server/jaxrs:invoker 元素来注册实例)。

附加 WADL 文档

您可以使用 jaxrs:server 元素上的 docLocation 属性,将 WADL 文档与 JAX-RS 服务器端点关联。例如:

<jaxrs:server address="/rest" docLocation="wadl/bookStore.wadl">
   <jaxrs:serviceBeans>
      <bean class="org.bar.generated.BookStore"/>
   </jaxrs:serviceBeans>
</jaxrs:server>

模式验证

如果您有一些外部 XML 模式,用于描述 JAX-B 格式的消息内容,您可以通过 jaxrs:schemaLocations 将这些外部模式与 JAX-RS 服务器端点关联。

例如,如果您已将服务器端点与 WADL 文档相关联,并且您希望在传入消息上启用 schema 验证,您可以按如下方式指定相关的 XML 架构文件:

<jaxrs:server address="/rest"
              docLocation="wadl/bookStore.wadl">
   <jaxrs:serviceBeans>
     <bean class="org.bar.generated.BookStore"/>
   </jaxrs:serviceBeans>
   <jaxrs:schemaLocations>
     <jaxrs:schemaLocation>classpath:/schemas/a.xsd</jaxrs:schemaLocation>
     <jaxrs:schemaLocation>classpath:/schemas/b.xsd</jaxrs:schemaLocation>
   </jaxrs:schemaLocations>
</jaxrs:server>

或者,如果您要将所有模式文件( *.xsd )包含在给定目录中,您可以只指定目录名称,如下所示:

<jaxrs:server address="/rest"
              docLocation="wadl/bookStore.wadl">
   <jaxrs:serviceBeans>
     <bean class="org.bar.generated.BookStore"/>
   </jaxrs:serviceBeans>
   <jaxrs:schemaLocations>
     <jaxrs:schemaLocation>classpath:/schemas/</jaxrs:schemaLocation>
   </jaxrs:schemaLocations>
</jaxrs:server>

以这种方式指定架构对于需要访问 JAX-B 模式的任何种类的功能通常有用。

指定数据绑定

您可以使用 jaxrs:dataBinding 元素指定在请求和回复消息中编码消息正文的数据绑定。例如,若要指定 JAX-B 数据的绑定,您可以配置 JAX-RS 端点,如下所示:

<jaxrs:server id="jaxbbook" address="/jaxb">
  <jaxrs:serviceBeans>
    <ref bean="serviceBean" />
  </jaxrs:serviceBeans>
  <jaxrs:dataBinding>
    <bean class="org.apache.cxf.jaxb.JAXBDataBinding"/>
  </jaxrs:dataBinding>
</jaxrs:server>>

或者指定 Aegis 数据的绑定,您可以按照如下所示配置 JAX-RS 端点:

<jaxrs:server id="aegisbook" address="/aegis">
  <jaxrs:serviceBeans>
    <ref bean="serviceBean" />
  </jaxrs:serviceBeans>
  <jaxrs:dataBinding>
    <bean class="org.apache.cxf.aegis.databinding.AegisDatabinding">
      <property name="aegisContext">
        <bean class="org.apache.cxf.aegis.AegisContext">
          <property name="writeXsiTypes" value="true"/>
        </bean>
      </property>
    </bean>
  </jaxrs:dataBinding>
</jaxrs:server>

使用 JMS 传输

可以将 JAX-RS 配置为将 JMS 消息库用作传输协议,而不使用 HTTP。由于 JMS 本身 不是 传输协议,因此实际的消息传递协议取决于您配置的特定 JMS 实施。

例如,以下 Spring XML 示例演示了如何配置 JAX-RS 服务器端点以使用 JMS 传输协议:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:jms="http://cxf.apache.org/transports/jms"
       xmlns:jaxrs="http://cxf.apache.org/jaxrs"
       xsi:schemaLocation="
http://cxf.apache.org/transports/jms http://cxf.apache.org/schemas/configuration/jms.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd">

    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
    <bean id="ConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
        <property name="brokerURL" value="tcp://localhost:${testutil.ports.EmbeddedJMSBrokerLauncher}" />
    </bean>

    <jaxrs:server xmlns:s="http://books.com"
    	serviceName="s:BookService"
    	transportId= "http://cxf.apache.org/transports/jms"
    	address="jms:queue:test.jmstransport.text?replyToName=test.jmstransport.response">
        <jaxrs:serviceBeans>
            <bean class="org.apache.cxf.systest.jaxrs.JMSBookStore"/>
        </jaxrs:serviceBeans>
    </jaxrs:server>

</beans>

请注意,以下有关上例的几点:

  • JMS 实施- JMS 实施由 ConnectionFactory bean 提供,后者实例化 Apache ActiveMQ 连接工厂对象。在实例化连接工厂后,它会作为默认的 JMS 实现层自动安装。
  • JMS conduit 或 destination 对象-Apache CXF 隐式实例化 JMS conduit 对象(代表 JMS 消费者)或 JMS 目标对象(代表 JMS 提供程序)。这个对象必须由 QName 唯一标识,它通过 setttings xmlns:s="http://books.com" 定义(定义命名空间前缀)和 serviceName="s:BookService"( 定义 QName)。
  • 传输 ID- 要选择 JMS 传输,transportId 属性必须设置为 http://cxf.apache.org/transports/jms
  • JMS 地址- jaxrs:server/@address 属性使用标准化语法来指定要发送到的 JMS 队列或 JMS 主题。有关此语法的详情,请参考 https://tools.ietf.org/id/draft-merrick-jms-uri-06.txt

扩展映射和语言映射

可以配置 JAX-RS 服务器端点,使它自动将文件后缀(在 URL 中应用)映射到 MIME 内容类型标头,并将语言后缀映射到语言类型标头。例如,考虑以下形式的 HTTP 请求:

GET /resource.xml

您可以配置 JAX-RS 服务器端点,以自动映射 .xml 后缀,如下所示:

<jaxrs:server id="customerService" address="/">
  <jaxrs:serviceBeans>
    <bean class="org.apache.cxf.jaxrs.systests.CustomerService" />
  </jaxrs:serviceBeans>
  <jaxrs:extensionMappings>
    <entry key="json" value="application/json"/>
    <entry key="xml" value="application/xml"/>
  </jaxrs:extensionMappings>
</jaxrs:server>

当上述服务器端点收到 HTTP 请求时,它会自动创建类型为 application/xml 的新内容类型标头,并从资源 URL 剥离 .xml 后缀。

对于语言映射,请考虑以下格式的 HTTP 请求:

GET /resource.en

您可以配置 JAX-RS 服务器端点,以自动映射 .en 后缀,如下所示:

<jaxrs:server id="customerService" address="/">
  <jaxrs:serviceBeans>
    <bean class="org.apache.cxf.jaxrs.systests.CustomerService" />
  </jaxrs:serviceBeans>
  <jaxrs:languageMappings>
     <entry key="en" value="en-gb"/>
  </jaxrs:languageMappings>
</jaxrs:server>

当上述服务器端点收到 HTTP 请求时,它会自动创建一个新的接受语言标头,值为 en-gb,并从资源 URL 剥离 .en 后缀。

18.1.2. jaxrs:server 属性

属性

表 18.1 “JAX-RS 服务器端点属性” 描述 jaxrs:server 元素中可用的属性。

表 18.1. JAX-RS 服务器端点属性

属性描述

id

指定其他配置元素可用于引用端点的唯一标识符。

address

指定 HTTP 端点的地址。这个值将覆盖服务合同中指定的值。

basePackages

(仅限 Spring) 启用自动发现功能,方法是指定以逗号分隔的 Java 软件包列表,这些列表用于发现 JAX-RS 根资源类和/或 JAX-RS 提供程序类。

beanNames

指定 JAX-RS root 资源 Bean ID 的以空格分开的列表。在 Spring XML 上下文中,可以通过设置 root 资源 bean 元素上的 scope 属性来定义根资源 Bean 的生命周期。

bindingId

指定服务使用的消息绑定 ID。第 23 章 Apache CXF Binding ID 中提供了有效绑定 ID 列表。

总线

指定 Spring Bean 的 ID,配置用于管理服务端点的总线。这在将多个端点配置为使用一组通用的功能时,这很有用。

docLocation

指定外部 WADL 文档的位置。

modelRef

将模型 schema 指定为类路径资源(例如,classpath :/path/to/model.xml的 URL)。有关如何定义 JAX-RS 模型架构的详细信息,请参阅 第 18.3 节 “使用模型架构定义 REST 服务”

publish

指定是否应该自动发布该服务。如果设置为 false,则开发人员必须明确发布端点。

publishedEndpointUrl

指定 URL 基础地址,该地址将插入到自动生成的 WADL 接口的 wadl:resources/@base 属性中。

serviceAnnotation

(仅限 Spring) 指定 Spring 中自动发现的服务注解类名称。与 basePackages 属性结合使用时,此选项将限制自动发现类的集合,使其 仅包含 此注解类型所标注的类。猜!这是否正确?

serviceClass

指定 JAX-RS 根资源类的名称(实施 JAX-RS 服务)。在这种情况下,类由 Apache CXF 进行实例化,而不是由 Blueprint 或 Spring 进行实例化。如果要在 Blueprint 或 Spring 中实例化类,请使用 jaxrs:serviceBeans 子元素。

serviceName

指定在使用 JMS 传输的特殊情况下,为 JAX-RS 端点指定服务 QName(使用 ns:name)。详情请查看 “使用 JMS 传输”一节

staticSubresourceResolution

如果为 true,则禁用静态子资源的动态解析。默认为 false

transportId

用于选择非标准传输层(替换 HTTP)。特别是,您可以通过将此属性设置为 http://cxf.apache.org/transports/jms 来选择 JMS 传输。详情请查看 “使用 JMS 传输”一节

abstract

(仅限 Spring) 指定 bean 是否为抽象 bean。abstract Bean 充当拥塞 Bean 定义且没有实例化的父项。默认值为 false。将其设置为 true 指示 bean 工厂不会实例化 bean。

dependent-on

(Spring only) 指定端点在端点实例化之前要实例化的 Bean 列表,然后可以实例化该端点。

18.1.3. jaxrs:server Child Elements

子元素

表 18.2 “JAX-RS 服务器端点子元素” 描述 jaxrs:server 元素的子元素。

表 18.2. JAX-RS 服务器端点子元素

元素描述

jaxrs:executor

指定用于该服务的 Java 执行程序 (线程池实施)。这使用嵌入式 bean 定义进行指定。

jaxrs:features

指定 Beans 列表,用于配置 Apache CXF 的高级功能。您可以提供 bean 引用列表或嵌入式 Bean 列表。

jaxrs:binding

未使用.

jaxrs:dataBinding

指定实施端点使用的数据绑定的类。这使用嵌入式 bean 定义进行指定。如需了解更多详细信息,请参阅 “指定数据绑定”一节

jaxrs:inInterceptors

指定处理入站请求的拦截器列表。更多信息请参阅 第 VII 部分 “开发 Apache CXF Interceptors”

jaxrs:inFaultInterceptors

指定处理入站错误信息的拦截器列表。更多信息请参阅 第 VII 部分 “开发 Apache CXF Interceptors”

jaxrs:outInterceptors

指定处理出站回复的拦截器列表。更多信息请参阅 第 VII 部分 “开发 Apache CXF Interceptors”

jaxrs:outFaultInterceptors

指定处理出站错误信息的拦截器列表。更多信息请参阅 第 VII 部分 “开发 Apache CXF Interceptors”

jaxrs:invoker

指定服务使用的 org.apache.cxf.service.Invoker 接口的实施。[a]

jaxrs:serviceFactories

为您提供对与此端点关联的 JAX-RS 根资源的生命周期的最大控制程度。此元素的子项(必须是 org.apache.cxf.jaxrs.lifecycle.ResourceProvider 类型的实例)用于创建 JAX-RS 根资源实例。

jaxrs:properties

指定传递给端点的属性的 Spring 映射。这些属性可用于控制启用 MTOM 支持等功能。

jaxrs:serviceBeans

此元素的子项是(an 元素)的实例或引用(ref 元素)JAX-RS 根资源。请注意,如果 bean 元素中存在 scope 属性 (仅限 Spring), 则忽略。

jaxrs:modelBeans

由一个或多个 org.apache.cxf.jaxrs.model.UserResource Bean 组成,它们是资源模型的基本元素(与 jaxrs:resource 元素)的引用列表。详情请查看 第 18.3 节 “使用模型架构定义 REST 服务”

jaxrs:model

在此端点中直接定义资源模型(即,这个 jaxrs:model 元素可以包含一个或多个 jaxrs:resource 元素)。详情请查看 第 18.3 节 “使用模型架构定义 REST 服务”

jaxrs:providers

使您能够使用此端点注册一个或多个自定义 JAX-RS 提供程序。此元素的子项是(an 元素)的实例或引用(ref 元素)JAX-RS 提供程序。

jaxrs:extensionMappings

当 REST 调用的 URL 以文件扩展结尾时,您可以使用此元素将其与特定内容类型关联。例如,.xml 文件扩展名可以与 application/xml 内容类型关联。详情请查看 “扩展映射和语言映射”一节

jaxrs:languageMappings

当 REST 调用的 URL 以语言后缀结尾时,您可以使用此元素将这个元素映射到特定的语言。例如,.en 语言后缀可以与 en-GB 语言关联。详情请查看 “扩展映射和语言映射”一节

jaxrs:schemaLocations

指定验证 XML 消息内容的一个或多个 XML 模式。此元素可以包含一个或多个 jaxrs:schemaLocation 元素,各自指定 XML 架构文件的位置(通常是 类路径 URL)。详情请查看 “模式验证”一节

jaxrs:resourceComparator

可让您注册自定义资源比较器,它实施用于匹配特定资源类或方法的传入 URL 路径的算法。

jaxrs:resourceClasses

如果要从类名称创建多个资源,则只使用 jaxrs:server/@serviceClass 属性(blueprint) 而不是使用 jaxrs:server/@serviceClass 属性。jaxrs:resourceClasses 的子项必须是将 name 属性设置为资源名称 的类 元素。在这种情况下,类由 Apache CXF 进行实例化,而不是由 Blueprint 或 Spring 进行实例化。

[a] Invoker 实施控制如何调用服务。例如,它控制每个请求是否由服务实施的新实例处理,或在调用中保留状态。

18.2. 配置 JAX-RS 客户端端点

18.2.1. 定义 JAX-RS 客户端端点

注入客户端代理

在 XML 语言(Blueprint XML 或 Spring XML)中实例化客户端代理的主要点是将其注入另一个 bean,然后使用客户端代理调用 REST 服务。要在 XML 中创建客户端代理 bean,请使用 jaxrs:client 元素。

命名空间

JAX-RS 客户端端点使用服务器端点 的不同 XML 命名空间来定义。下表显示了用于 XML 语言的命名空间:

XML 语言客户端端点的命名空间

蓝图(Blueprint)

http://cxf.apache.org/blueprint/jaxrs-client

Spring

http://cxf.apache.org/jaxrs-client

基本客户端端点定义

以下示例演示了如何在 Blueprint XML 或 Spring XML 中创建客户端代理:

<jaxrs:client id="restClient"
       address="http://localhost:8080/test/services/rest"
       serviceClass="org.apache.cxf.systest.jaxrs.BookStoreJaxrsJaxws"/>

您必须设置以下属性来定义基本客户端端点:

id
客户端代理的 bean ID 可用于将客户端代理注入到 XML 配置中的其他 Bean 中。
address
address 属性指定 REST 调用的基本 URL。
serviceClass
serviceClass 属性指定根资源类(由 @Path无关)来提供 REST 服务的描述。实际上,这是 服务器 类,但不直接由客户端使用。指定的类仅用于其元数据(通过 Java 反射和 JAX-RS 注释),用于动态构建客户端代理。

指定标头

您可以使用 jaxrs:headers 子元素将 HTTP 标头添加到客户端代理调用中,如下所示:

<jaxrs:client id="restClient"
       address="http://localhost:8080/test/services/rest"
       serviceClass="org.apache.cxf.systest.jaxrs.BookStoreJaxrsJaxws"
       inheritHeaders="true">
       <jaxrs:headers>
           <entry key="Accept" value="text/xml"/>
       </jaxrs:headers>
</jaxrs:client>

18.2.2. jaxrs:client 属性

属性

表 18.3 “JAX-RS 客户端端点属性” 描述 jaxrs:client 元素中可用的属性。

表 18.3. JAX-RS 客户端端点属性

属性描述

address

指定消费者发出请求的端点的 HTTP 地址。这个值覆盖合同中设定的值。

bindingId

指定消费者使用的消息绑定 ID。第 23 章 Apache CXF Binding ID 中提供了有效绑定 ID 列表。

总线

指定 Spring bean 配置总线管理端点的 ID。

inheritHeaders

如果从此代理创建子资源代理,则指定是否会继承为此代理设置的标头。默认为 false

username

指定用于简单用户名/密码身份验证的用户名。

password

指定用于简单用户名/密码验证的密码。

modelRef

将模型 schema 指定为类路径资源(例如,classpath :/path/to/model.xml的 URL)。有关如何定义 JAX-RS 模型架构的详细信息,请参阅 第 18.3 节 “使用模型架构定义 REST 服务”

serviceClass

指定服务接口的名称或资源类(通过 @PATH标注),重新利用 JAX-RS 服务器实施。在这种情况下,指定的类 不会 直接调用(实际上是一个服务器类)。指定的类仅用于其元数据(通过 Java 反射和 JAX-RS 注释),用于动态构建客户端代理。

serviceName

指定在使用 JMS 传输的特殊情况下,为 JAX-RS 端点指定服务 QName(使用 ns:name)。详情请查看 “使用 JMS 传输”一节

threadSafe

指定客户端代理是否为 thread-safe。默认为 false

transportId

用于选择非标准传输层(替换 HTTP)。特别是,您可以通过将此属性设置为 http://cxf.apache.org/transports/jms 来选择 JMS 传输。详情请查看 “使用 JMS 传输”一节

abstract

(仅限 Spring) 指定 bean 是否为抽象 bean。abstract Bean 充当拥塞 Bean 定义且没有实例化的父项。默认值为 false。将其设置为 true 指示 bean 工厂不会实例化 bean。

dependent-on

(Spring only) 指定端点在实例化前需要被实例化的 Bean 列表,然后才能实例化它。

18.2.3. jaxrs:client Child Elements

子元素

表 18.4 “JAX-RS 客户端端点子元素” 描述 jaxrs:client 元素的子元素。

表 18.4. JAX-RS 客户端端点子元素

元素描述

jaxrs:executor

 

jaxrs:features

指定 Beans 列表,用于配置 Apache CXF 的高级功能。您可以提供 bean 引用列表或嵌入式 Bean 列表。

jaxrs:binding

未使用.

jaxrs:dataBinding

指定实施端点使用的数据绑定的类。这使用嵌入式 bean 定义进行指定。如需了解更多详细信息,请参阅 “指定数据绑定”一节

jaxrs:inInterceptors

指定进程入站响应的拦截器列表。更多信息请参阅 第 VII 部分 “开发 Apache CXF Interceptors”

jaxrs:inFaultInterceptors

指定处理入站错误信息的拦截器列表。更多信息请参阅 第 VII 部分 “开发 Apache CXF Interceptors”

jaxrs:outInterceptors

指定处理出站请求的拦截器列表。更多信息请参阅 第 VII 部分 “开发 Apache CXF Interceptors”

jaxrs:outFaultInterceptors

指定处理出站错误信息的拦截器列表。更多信息请参阅 第 VII 部分 “开发 Apache CXF Interceptors”

jaxrs:properties

指定传递给端点的属性映射。

jaxrs:providers

使您能够使用此端点注册一个或多个自定义 JAX-RS 提供程序。此元素的子项是(an 元素)的实例或引用(ref 元素)JAX-RS 提供程序。

jaxrs:modelBeans

由一个或多个 org.apache.cxf.jaxrs.model.UserResource Bean 组成,它们是资源模型的基本元素(与 jaxrs:resource 元素)的引用列表。详情请查看 第 18.3 节 “使用模型架构定义 REST 服务”

jaxrs:model

在此端点中直接定义资源模型(即 jaxrs:model 元素包含一个或多个 jaxrs:resource 元素)。详情请查看 第 18.3 节 “使用模型架构定义 REST 服务”

jaxrs:headers

用于设置传出消息上的标头。详情请查看 “指定标头”一节

jaxrs:schemaLocations

指定验证 XML 消息内容的一个或多个 XML 模式。此元素可以包含一个或多个 jaxrs:schemaLocation 元素,各自指定 XML 架构文件的位置(通常是 类路径 URL)。详情请查看 “模式验证”一节

18.3. 使用模型架构定义 REST 服务

没有注解的 RESTful 服务

借助 JAX-RS 模型模式,可以在不 注解 Java 类的情况下定义 RESTful 服务。也就是说,不使用 @Path@PathParam@Consumes、@Consumes、@Produces 等等,直接发送到 Java 类(或接口),您可以提供单独的 XML 文件中的所有相关 REST 元数据。例如,在无法修改实现该服务的 Java 源时,这很有用。

模型 schema 示例

例 18.1 “JAX-RS 模型架构示例” 显示了一个模型架构示例,它定义了 BookStoreNoAnnotations root 资源类的服务元数据。

例 18.1. JAX-RS 模型架构示例

<model xmlns="http://cxf.apache.org/jaxrs">
  <resource name="org.apache.cxf.systest.jaxrs.BookStoreNoAnnotations" path="bookstore"
    produces="application/json" consumes="application/json">
    <operation name="getBook" verb="GET" path="/books/{id}" produces="application/xml">
       <param name="id" type="PATH"/>
    </operation>
    <operation name="getBookChapter" path="/books/{id}/chapter">
       <param name="id" type="PATH"/>
    </operation>
    <operation name="updateBook" verb="PUT">
       <param name="book" type="REQUEST_BODY"/>
    </operation>
  </resource>
  <resource name="org.apache.cxf.systest.jaxrs.ChapterNoAnnotations">
    <operation name="getItself" verb="GET"/>
    <operation name="updateChapter" verb="PUT" consumes="application/xml">
        <param name="content" type="REQUEST_BODY"/>
    </operation>
  </resource>
</model>

命名空间

用于定义模型模式的 XML 命名空间取决于您在 Blueprint XML 中定义对应的 JAX-RS 端点还是在 Spring XML 中定义。下表显示了用于 XML 语言的命名空间:

XML 语言命名空间

蓝图(Blueprint)

http://cxf.apache.org/blueprint/jaxrs

Spring

http://cxf.apache.org/jaxrs

如何将模型模式附加到端点

要在端点上定义和附加模型模式,请执行以下步骤:

  1. 使用您选择的注入平台(Blueprint XML 或 Spring XML)的适当 XML 命名空间定义模型架构。
  2. 将模型模式文件添加到您的项目的资源,以便架构文件可在最终软件包(JAR、WAR 或 OSGi 捆绑包文件)上提供。

    注意

    另外,还可以使用端点的 jaxrs:model 子元素将模型模式直接嵌入到 JAX-RS 端点中。

  3. 将端点配置为使用模型模式,方法是将端点的 modelRef 属性设置为 classpath 上模型架构的位置(使用 classpath URL)。
  4. 如有必要,使用 jaxrs:serviceBeans 元素明确实例化根资源。如果模型模式直接引用根资源类(而不是引用基本接口),您可以跳过这一步。

引用类的模型架构配置

如果模型架构直接应用到根资源类,则不需要使用 jaxrs:serviceBeans 元素定义任何根资源anan,因为模型架构会自动实例化根资源 Bean。

例如,如果 customer-resources.xml 是一个模型的 schema,它将元数据与客户资源类相关联,您可以按照如下所示 实例化客户服务端点:

<jaxrs:server id="customerService"
              address="/customers"
              modelRef="classpath:/org/example/schemas/customer-resources.xml" />

配置模型架构引用接口

如果模型架构适用于 Java 接口(它是根资源的基本接口),则必须使用端点中的 jaxrs:serviceBeans 元素实例化根资源类。

例如,如果 customer-interfaces.xml 是一个模型 schema,它将元数据与客户接口相关联,您可以按照如下所示 实例化客户服务端点:

<jaxrs:server id="customerService"
              address="/customers"
              modelRef="classpath:/org/example/schemas/customer-interfaces.xml">
    <jaxrs:serviceBeans>
       <ref component-id="serviceBean" />
    </jaxrs:serviceBeans>
</jaxrs:server>

<bean id="serviceBean" class="service.CustomerService"/>

模型架构参考

模型模式使用以下 XML 元素定义:

model
模型架构的根元素。如果您需要引用模型模式(例如,使用 modelRef 属性的 JAX-RS 端点中),您应当设置此元素上的 id 属性。
model/resource

资源 元素用于将元数据与特定的根资源类(或对应的接口)关联。您可以在 resource 元素上定义以下属性:

属性描述 +

name

将这个资源模型应用到的资源类(或对应接口)的名称。

+

path

映射到此资源的 REST URL 路径的组件。

+

使用

指定此资源使用的内容类型(Internet 介质类型),如 application/xmlapplication/json

+

produces

指定此资源生成的内容类型(互联网介质类型),如 application/xmlapplication/json

+

model/resource/operation

operation 元素用于将元数据与 Java 方法关联。您可以在 operation 元素上定义以下属性:

属性描述 +

name

此元素应用到的 Java 方法的名称。

+

path

映射到此方法的 REST URL 路径的组件。此属性值可以包括参数引用,例如: path="/books/{id}/ preceding",其中 {id} 会从路径中提取 id 参数的值。

+

verb

指定映射到此方法的 HTTP 动词。通常, : GETPOSTPUTDELETE.如果没有指定 HTTP 动词,则假设 Java 方法是一个 子资源定位器,它会返回一个对子资源对象的引用(其中子资源类还必须使用 资源元素提供元数据 )。

+

使用

指定此操作使用的内容类型(Internet 介质类型),如 application/xmlapplication/json

+

produces

指定此操作生成的内容类型(互联网介质类型),如 application/xmlapplication/json

+

Oneway

如果为 true,将操作配置为 单向,即不需要回复信息。默认值为 false

+

model/resource/operation/param

param 元素用于从 REST URL 中提取值,并将其注入到其中一个方法参数中。您可以在 param 元素上定义以下属性:

属性描述 +

name

此元素应用到的 Java 方法参数的名称。

+

type

指定从 REST URL 或消息中提取参数值的方式。可以将其设置为以下值之一: PATHQUERYMATRIX、HEAHER、COOKIEFORMCONTEXTREQUEST_BODY

+

defaultValue

要注入到参数的默认值,因为无法从 REST URL 或消息中提取值。

+

编码

如果为 true,则参数值以其 URI 编码形式注入(即,使用 %n 编码代码)。默认为 false。例如,当从 URL 路径中提取参数时,/name/Joe%20Bloggs 将被编码设为 true,该参数会作为 Joe%20Bloggs 注入到;否则,参数将作为 Joe Bloggs 注入。

+

第 19 章 Apache CXF Logging

摘要

本章论述了如何在 Apache CXF 运行时配置日志。

19.1. Apache CXF 日志概述

概述

Apache CXF 使用 Java 日志记录实用程序 java.util.logging。日志记录配置在一个日志配置文件中,该文件使用标准的 java.util.Properties 格式编写。要在应用上运行日志记录,您可以以编程方式指定日志记录,或者在启动应用程序时在命令中定义指向日志记录配置文件的属性。

默认属性文件

Apache CXF 附带默认的 logging.properties 文件,该文件位于您的 InstallDir/etc 目录中。此文件为日志消息和发布的消息级别配置输出目的地。默认配置会将日志记录器设置为打印带有 WARNING 级别标记的消息到控制台。您可以使用默认文件而无需更改任何配置设置,也可以更改配置设置以适应特定的应用程序。

日志记录功能

Apache CXF 包括日志记录功能,可插入您的客户端或您的服务以启用日志记录。例 19.1 “配置来启用日志记录” 显示启用日志记录功能的配置。

例 19.1. 配置来启用日志记录

<jaxws:endpoint...>
  <jaxws:features>
    <bean class="org.apache.cxf.feature.LoggingFeature"/>
  </jaxws:features>
</jaxws:endpoint>

更多信息请参阅 第 19.6 节 “记录消息内容”

从哪里开始?

要运行一个简单的日志记录示例,请按照 第 19.2 节 “使用日志记录的简单示例” 中介绍的说明。

如需有关在 Apache CXF 中登录的更多信息,请阅读整个章节。

有关 java.util.logging 的更多信息

java.util.logging 实用程序是最常用的 Java 日志框架之一。在线提供了很多可用的信息,用于描述如何使用和扩展此框架。但作为起点,以下文档提供了 java.util.logging 的良好概述:

19.2. 使用日志记录的简单示例

更改日志级别和输出目的地

要更改 wsdl_first 示例应用程序中日志消息的日志级别和输出目的地,请完成以下步骤:

  1. 使用 InstallDir/samples/wsdl_first 目录中的 README.txt 文件的 java 部分,运行 demo 运行示例服务器。请注意,server start 命令指定默认的 logging.properties 文件,如下所示:

    平台命令 +

    Windows

    启动 java -Djava.util.logging.config.file=%CXF_HOME%\etc\logging.properties demo.hw.server.Server

    +

    UNIX

    java -Djava.util.logging.config.file=$CXF_HOME/etc/logging.properties demo.hw.server.Server &

    +

    默认的 logging.properties 文件位于 InstallDir/etc 目录中。它将 Apache CXF loggers 配置为向控制台打印 WARNING 级别日志消息。因此,您会看到到控制台的很少输出。

  2. README.txt 文件中所述,停止服务器。
  3. 复制默认的 logging.properties 文件,将其命名为 mylogging.properties 文件,并将它保存为与默认 logging.properties 文件相同的目录中。
  4. 通过编辑以下配置行,将 mylogging.properties 文件中的控制台日志记录级别和控制台日志记录级别改为 INFO

    .level= INFO
    java.util.logging.ConsoleHandler.level = INFO
  5. 使用以下命令重启服务器:

    平台命令 +

    Windows

    启动 java -Djava.util.logging.config.file=%CXF_HOME%\etc\mylogging.properties demo.hw.server.Server

    +

    UNIX

    java -Djava.util.logging.config.file=$CXF_HOME/etc/mylogging.properties demo.hw.server.Server &

    +

    由于您已将全局日志和控制台日志记录器配置为记录级别 INFO 的消息,因此您会看到更多日志消息打印到控制台。

19.3. 默认日志记录配置文件

19.3.1. 日志配置概述

默认日志记录配置文件 logging.properties 位于 InstallDir/etc 目录中。它将 Apache CXF loggers 配置为向控制台打印 WARNING 级别的消息。如果此级别的日志记录适用于您的应用程序,在使用前不必对该文件进行任何更改。但是,您可以在日志消息中更改详细级别。例如,您可以把日志消息发送到控制台,或更改为文件或两者。另外,您可以在独立软件包的级别上指定日志记录。

注意

本节讨论在默认的 logging.properties 文件中显示的配置属性。然而,还有许多其他 java.util.logging 配置属性可以设置。有关 java.util.logging API 的更多信息,请参见 java.util.logging javadoc,网址为: http://download.oracle.com/javase/1.5/docs/api/java/util/logging/package-summary.html

19.3.2. 配置日志输出

概述

Java 日志记录实用程序 java.util.logging 使用处理程序类输出日志消息。表 19.1 “Java.util.logging Handler Classes” 显示在默认的 logging.properties 文件中配置的处理程序。

表 19.1. Java.util.logging Handler Classes

处理器类输出到

ConsoleHandler

将日志信息输出到控制台

FileHandler

输出日志消息到文件中

重要

处理程序类必须在系统类路径上,才能在启动时由 Java 虚拟机安装。设置 Apache CXF 环境时会完成此操作。

配置控制台处理程序

例 19.2 “配置控制台处理程序” 显示配置控制台日志记录器的代码。

例 19.2. 配置控制台处理程序

handlers= java.util.logging.ConsoleHandler

控制台处理程序也支持 例 19.3 “控制台处理程序属性” 中显示的配置属性。

例 19.3. 控制台处理程序属性

java.util.logging.ConsoleHandler.level = WARNING
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter

例 19.3 “控制台处理程序属性” 中显示的配置属性可以解释如下:

控制台处理程序支持单独的日志级别配置属性。这可让您将打印的日志信息限制为控制台,而全局日志记录设置可能会不同(请参阅 第 19.3.3 节 “配置日志记录级别”)。默认设置为 WARNING

指定 console handler 类用于格式化日志消息的 java.util.logging formatter 类。默认设置为 java.util.logging.SimpleFormatter

配置文件处理程序

例 19.4 “配置文件处理程序” 显示配置文件处理程序的代码。

例 19.4. 配置文件处理程序

handlers= java.util.logging.FileHandler

文件处理程序也支持 例 19.5 “文件处理程序配置属性” 中显示的配置属性。

例 19.5. 文件处理程序配置属性

java.util.logging.FileHandler.pattern = %h/java%u.log
java.util.logging.FileHandler.limit = 50000
java.util.logging.FileHandler.count = 1
java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter

例 19.5 “文件处理程序配置属性” 中显示的配置属性可以解释如下:

指定输出文件的位置和模式。默认设置为您的主目录。

以字节为单位,日志记录器写入任何一个文件的最大数量。默认设置为 50000。如果将其设置为零,则日志记录器写入任何一个文件的数量没有限制。

指定循环要循环多少个输出文件。默认设置为 1

指定文件处理器类格式化日志消息的 java.util.logging formatter 类。默认设置为 java.util.logging.XMLFormatter

配置控制台处理程序和文件处理程序

您可以通过指定控制台处理程序和文件处理程序(以逗号分隔)来设置日志记录工具,以将日志消息输出到控制台和文件处理程序,如 配置两个控制台日志和文件 所示。

配置两个控制台日志和文件

Logging

handlers= java.util.logging.FileHandler, java.util.logging.ConsoleHandler

19.3.3. 配置日志记录级别

日志级别

java.util.logging 框架支持以下日志级别,从最小到详细值:

  • 严重
  • WARNING
  • INFO
  • CONFIG
  • FINE
  • FINER
  • FINEST

配置全局日志记录级别

要配置在所有日志记录器中记录的事件类型,请配置全局日志记录级别,如 例 19.6 “配置全局日志记录级别” 所示。

例 19.6. 配置全局日志记录级别

.level= WARNING

在独立软件包中配置日志记录

level

java.util.logging 框架支持在单个软件包的级别上配置日志记录。例如: 例 19.7 “在软件包级别配置日志记录” 中显示的代码行在 com.xyz.foo 软件包中的类中配置 SEVERE 级别的日志。

例 19.7. 在软件包级别配置日志记录

com.xyz.foo.level = SEVERE

19.4. 通过命令行启用日志记录

概述

您可以在启动应用程序时定义 java.util.logging.config.file 属性在应用程序上运行日志记录实用程序。您可以指定默认的 logging.properties 文件,或者指定应用程序独有的 logging.properties 文件。

在应用程序中指定日志配置文件

start-up

要在应用程序启动时指定日志,请在启动应用程序时添加 例 19.8 “在命令行上启动日志记录的标记” 中显示的标记。

例 19.8. 在命令行上启动日志记录的标记

-Djava.util.logging.config.file=myfile

19.5. 为 subsystem 和 Services 日志记录

概述

您可以使用 “在独立软件包中配置日志记录”一节 中描述的 com.xyz.foo.level 配置属性来为指定的 Apache CXF 日志记录子系统设置精细的日志记录。

Apache CXF 日志记录子系统

表 19.2 “Apache CXF Logging 子系统” 显示可用 Apache CXF 日志记录子系统列表。

表 19.2. Apache CXF Logging 子系统

子系统描述

org.apache.cxf.aegis

Aegis binding

org.apache.cxf.binding.coloc

colocated binding

org.apache.cxf.binding.http

HTTP 绑定

org.apache.cxf.binding.jbi

JBI 绑定

org.apache.cxf.binding.object

Java 对象绑定

org.apache.cxf.binding.soap

SOAP 绑定

org.apache.cxf.binding.xml

XML 绑定

org.apache.cxf.bus

Apache CXF 总线

org.apache.cxf.configuration

配置框架

org.apache.cxf.endpoint

服务器和客户端端点

org.apache.cxf.interceptor

拦截器

org.apache.cxf.jaxws

用于 JAX-WS 风格的消息交换的前端、JAX-WS 处理程序处理以及与 JAX-WS 和配置相关的拦截器

org.apache.cxf.jbi

JBI 容器集成类

org.apache.cxf.jca

JCA 容器集成类

org.apache.cxf.js

JavaScript 前端

org.apache.cxf.transport.http

HTTP 传输

org.apache.cxf.transport.https

使用 HTTPS 保护 HTTP 传输的安全版本

org.apache.cxf.transport.jbi

JBI 传输

org.apache.cxf.transport.jms

JMS 传输

org.apache.cxf.transport.local

使用本地文件系统的传输实现

org.apache.cxf.transport.servlet

HTTP 传输和 servlet 实现,用于将 JAX-WS 端点加载到 servlet 容器中

org.apache.cxf.ws.addressing

WS-寻址实施

org.apache.cxf.ws.policy

ws-Policy 的实现

org.apache.cxf.ws.rm

ws-ReliableMessaging(WS-RM)实施

org.apache.cxf.ws.security.wss4j

WSS4J 安全实施

示例

WS-Addressing 示例包含在 InstallDir/samples/ws_addressing 目录中。日志记录在位于该目录中的 logging.properties 文件中配置。配置的相关行显示在 例 19.9 “为 WS-Addressing 配置日志记录” 中。

例 19.9. 为 WS-Addressing 配置日志记录

java.util.logging.ConsoleHandler.formatter = demos.ws_addressing.common.ConciseFormatter
...
org.apache.cxf.ws.addressing.soap.MAPCodec.level = INFO

例 19.9 “为 WS-Addressing 配置日志记录” 中的配置启用跳过与 WS-Addressing 标头相关的日志消息,并以简洁的形式将它们显示到控制台中。

有关运行此示例的详情,请查看 InstallDir/samples/ws_addressing 目录中的 README.txt 文件。

19.6. 记录消息内容

概述

您可以记录在服务和消费者之间发送的消息内容。例如,您可能要记录在服务和消费者之间发送的 SOAP 消息的内容。

配置消息内容日志

要记录在服务和消费者之间发送的信息,反之亦然,请完成以下步骤:

将日志记录功能添加到端点

添加日志记录功能,您的端点的配置功能,如 例 19.10 “在端点配置中添加日志” 所示。

例 19.10. 在端点配置中添加日志

<jaxws:endpoint ...>
  <jaxws:features>
    <bean class="org.apache.cxf.feature.LoggingFeature"/>
  </jaxws:features>
</jaxws:endpoint>

例 19.10 “在端点配置中添加日志” 中显示的 XML 示例启用 SOAP 消息的日志记录。

在消费者中添加日志记录功能

添加日志记录功能,为您的客户端配置添加功能,如 例 19.11 “在客户端配置中添加日志” 所示。

例 19.11. 在客户端配置中添加日志

<jaxws:client ...>
   <jaxws:features>
      <bean class="org.apache.cxf.feature.LoggingFeature"/>
    </jaxws:features>
</jaxws:client>

例 19.11 “在客户端配置中添加日志” 中显示的 XML 示例启用 SOAP 消息的日志记录。

将 logging 设置为 log INFO 级别信息

确保与您的服务关联的 logging.properties 文件配置为记录 INFO 级别的信息,如 例 19.12 “将日志级别设置为 INFO” 所示。

例 19.12. 将日志级别设置为 INFO

.level= INFO
java.util.logging.ConsoleHandler.level = INFO

记录 SOAP 信息

要查看 SOAP 消息的日志,请修改位于 InstallDir/samples/wsdl_first 目录中的 wsdl_first 示例应用程序,如下所示:

  1. 例 19.13 “日志 SOAP 消息的端点配置” 中显示的 jaxws:features 元素添加到 wsdl_first 示例目录中的 cxf.xml 配置文件:

    例 19.13. 日志 SOAP 消息的端点配置

    <jaxws:endpoint name="{http://apache.org/hello_world_soap_http}SoapPort"
                    createdFromAPI="true">
      <jaxws:properties>
        <entry key="schema-validation-enabled" value="true" />
      </jaxws:properties>
      <jaxws:features>
        <bean class="org.apache.cxf.feature.LoggingFeature"/>
      </jaxws:features>
    </jaxws:endpoint>
  2. 这个示例使用默认的 logging.properties 文件,该文件位于 InstallDir/etc 目录中。制作此文件的副本,并将其命名为 mylogging.properties
  3. mylogging.properties 文件中,通过编辑 .leveljava.util.logging.ConsoleHandler.level 配置属性将日志记录级别更改为 INFO

    .level= INFO
    java.util.logging.ConsoleHandler.level = INFO
  4. 使用 cxf.xml 文件和 mylogging.properties 文件中的新配置设置启动服务器,如下所示:

    平台命令 +

    Windows

    启动 java -Djava.util.logging.config.file=%CXF_HOME%\etc\mylogging.properties demo.hw.server.Server

    +

    UNIX

    java -Djava.util.logging.config.file=$CXF_HOME/etc/mylogging.properties demo.hw.server.Server &

    +

  5. 使用以下命令启动 hello world 客户端:

    平台命令 +

    Windows

    java -Djava.util.logging.config.file=%CXF_HOME%\etc\mylogging.properties demo.hw.client.Client .\wsdl\hello_world.wsdl

    +

    UNIX

    java -Djava.util.logging.config.file=$CXF_HOME/etc/mylogging.properties demo.hw.client.Client ./wsdl/hello_world.wsdl

    +

SOAP 信息被记录到控制台。

第 20 章 部署 WS-Addressing

摘要

Apache CXF 支持 WS-WS 应用程序寻址。本章论述了如何在 Apache CXF 运行时环境中部署 WS-Addressing。

20.1. WS-Addressing 简介

概述

WS-寻址是一个规范,它允许服务以传输中立的方式沟通寻址信息。它由两个部分组成:

  • 用于将引用发送到 Web 服务端点的结构
  • 组消息地址属性(MAP),用于将寻址信息与特定消息关联

支持的规格

Apache CXF 支持 WS-Addressing 2004/08 规格和 WS-Addressing 2005/03 规范。

更多信息

有关 WS-Addressing 的详情,请参考 2004/08 提交地址 http://www.w3.org/Submission/ws-addressing/

20.2. WS-Addressing Interceptors

概述

在 Apache CXF 中,WS-Addressing 功能作为拦截器实现。Apache CXF 运行时使用拦截器截获并使用正在发送和接收的原始消息。当传输收到消息时,它会创建一个消息对象,并通过拦截器链发送该消息。如果将 WS-Addressing 拦截器添加到应用程序的拦截器链中,则会处理消息中包含的任何 WS-Addressing 信息。

WS-Addressing Interceptors

WS-Addressing 实施由两个拦截器组成,如 表 20.1 “WS-Addressing Interceptors” 所述。

表 20.1. WS-Addressing Interceptors

拦截器描述

org.apache.cxf.ws.addressing.MAPAggregator

负责聚合用于传入消息地址属性(MAPs)的逻辑拦截器。

org.apache.cxf.ws.addressing.soap.MAPCodec

负责编码和解码消息地址属性(MAPs)作为 SOAP 标头的特定于协议的拦截器。

20.3. 启用 WS-Addressing

概述

要启用 WS-Addressing 拦截器,必须将 WS-Addressing 拦截器添加到入站和出站拦截器链中。这可以通过以下之一完成:

  • Apache CXF 功能
  • RMAssertion 和 WS-Policy Framework
  • 在 WS-Addressing 功能中使用 Policy Assertion

将 WS-Addressing 添加为功能

通过在客户端和服务器配置中添加 WS-Addressing 功能来启用 WS-Addressing,如 例 20.1 “client.xml 并为客户端配置添加 WS-Addressing 功能”例 20.2 “server.xml 并添加到服务器配置的 WS-Addressing 功能” 所示。

例 20.1. client.xml 并为客户端配置添加 WS-Addressing 功能

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:jaxws="http://cxf.apache.org/jaxws"
       xmlns:wsa="http://cxf.apache.org/ws/addressing"
       xsi:schemaLocation="
          http://www.springframework.org/schema/beans
          http://www.springframework.org/schema/beans/spring-beans.xsd
          http://cxf.apache.org/ws/addressing
          http://cxf.apache.org/schemas/ws-addr-conf.xsd">

    <jaxws:client ...>
        <jaxws:features>
            <wsa:addressing/>
        </jaxws:features>
    </jaxws:client>
</beans>

例 20.2. server.xml 并添加到服务器配置的 WS-Addressing 功能

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:jaxws="http://cxf.apache.org/jaxws"
       xmlns:wsa="http://cxf.apache.org/ws/addressing"
       xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <jaxws:endpoint ...>
        <jaxws:features>
            <wsa:addressing/>
        </jaxws:features>
    </jaxws:endpoint>
</beans>

20.4. 配置 WS-Addressing 属性

概述

Apache CXF WS-Addressing 功能元素在命名空间 http://cxf.apache.org/ws/addressing 中定义。它支持 表 20.2 “WS-Addressing 属性” 描述的两个属性。

表 20.2. WS-Addressing 属性

属性名称

allowDuplicates

确定是否容许重复的 MessageID 的布尔值。默认设置为 true

usingAddressingAdvisory

指示 WSDL 中是否存在 使用Addressing 元素的布尔值 ; 也就是说,它不会阻止 WS-Addressing 标头的编码。

配置 WS-Addressing 属性

通过添加属性以及您想要将其设置为服务器或者客户端配置文件中的 WS-Addressing 功能来配置 WS-Addressing 属性。例如,以下配置提取服务器端点上的 allowDuplicates 属性设为 false

<beans ... xmlns:wsa="http://cxf.apache.org/ws/addressing" ...>
    <jaxws:endpoint ...>
        <jaxws:features>
            <wsa:addressing allowDuplicates="false"/>
        </jaxws:features>
    </jaxws:endpoint>
</beans>

使用嵌入在功能中的 WS-Policy 断言

例 20.3 “使用策略配置 WS-Addressing” 中,寻址策略断言,以启用非匿名响应,并嵌入到 policies 元素中。

例 20.3. 使用策略配置 WS-Addressing

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:wsa="http://cxf.apache.org/ws/addressing"
        xmlns:wsp="http://www.w3.org/2006/07/ws-policy"
        xmlns:policy="http://cxf.apache.org/policy-config"
        xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
        xmlns:jaxws="http://cxf.apache.org/jaxws"
        xsi:schemaLocation="
http://www.w3.org/2006/07/ws-policy http://www.w3.org/2006/07/ws-policy.xsd
http://cxf.apache.org/ws/addressing http://cxf.apache.org/schema/ws/addressing.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <jaxws:endpoint name="{http://cxf.apache.org/greeter_control}GreeterPort"
                    createdFromAPI="true">
        <jaxws:features>
            <policy:policies>
                <wsp:Policy xmlns:wsam="http://www.w3.org/2007/02/addressing/metadata">
                    <wsam:Addressing>
                        <wsp:Policy>
                            <wsam:NonAnonymousResponses/>
                        </wsp:Policy>
                    </wsam:Addressing>
                </wsp:Policy>
            <policy:policies>
        </jaxws:features>
    </jaxws:endpoint>
</beans>

第 21 章 启用可靠消息

摘要

Apache CXF 支持 WS-可靠消息传递(WS-RM)。本章论述了如何在 Apache CXF 中启用和配置 WS-RM。

21.1. WS-RM 简介

概述

WS-ReliableMessaging(WS-RM)是一种保证在分布式环境中可靠地传输消息的协议。它可让消息在软件、系统或网络故障的分布式应用程序之间可靠地交付。

例如,可以使用 WS-RM 来确保在网络上以正确方式传送正确的消息。

WS-RM 的工作原理

WS-RM 确保在来源和目的地端点之间可靠传递消息。源是消息的初始发送者,目的地是最终接收器,如 图 21.1 “Web 服务可靠消息” 所示。

图 21.1. Web 服务可靠消息

可靠的消息交换

可以描述 WS-RM 消息的流,如下所示:

  1. RM 源会向 RM 目标发送 CreateSequence 协议消息。它包含接收确认的端点的引用( wsrm:AcksTo 端点)。
  2. RM 目标将 CreateSequenceResponse 协议消息发回到 RM 源。此消息包含 RM 序列会话的序列 ID。
  3. RM 源为应用程序源发送的每个消息添加一个 RM Sequence 标头。此标头包含序列 ID 和唯一的消息 ID。
  4. RM 源会将每个消息传输到 RM 目的地。
  5. RM 目标通过发送包含 RM SequenceAcknowledgement 标头的消息,确认来自 RM 源的收据。
  6. RM 目的地以精确的方式向应用目的地传递消息。
  7. RM 源重新传输一个尚未收到确认的消息。

    第一个重新传输尝试是在基本重新传输间隔后进行的。默认情况下,以 exponential-off 间隔或以固定间隔形式进行重新传输尝试。如需了解更多详细信息,请参阅 第 21.5 节 “配置 WS-RM”

整个过程会针对请求和响应消息进行对称进行的。也就是说,当响应消息时,服务器充当 RM 源,客户端充当 RM 目的地。

WS-RM 交付保证

WS-RM 可保证分布式环境中可靠的消息发送,无论所使用的传输协议如何。如果无法进行可靠交付,则源或目标端点会记录错误。

支持的规格

Apache CXF 支持 WS-RM 规范的以下版本:

WS-ReliableMessaging 1.0

(默认) Correspon ds 到 2005 年 2 月提交版本,现已过期。然而,出于向后兼容性的原因,这个版本被用作默认值。

WS-RM 版本 1.0 使用以下命名空间:

http://schemas.xmlsoap.org/ws/2005/02/rm/

此版本的 WS-RM 可与以下 WS-Addressing 版本一起使用:

http://schemas.xmlsoap.org/ws/2004/08/addressing (default)
http://www.w3.org/2005/08/addressing

为了遵守 2005 年 2 月版本的 WS-RM,您很难使用第一个 WS-Addressing 版本(这是 Apache CXF 中的默认设置)。但大多数其他 Web 服务实施已切换到较新的 WS-Addressing 规格,因此 Apache CXF 允许您选择 WS-A 版本以促进互操作性(请参阅 第 21.4 节 “运行时控制”)。

WS-ReliableMessaging 1.1/1.2

对应于官方 1.1/1.2 Web 服务可靠消息 规范。

WS-RM 版本 1.1 和 1.2 版本使用以下命名空间:

http://docs.oasis-open.org/ws-rx/wsrm/200702

WS-RM 的 1.1 和 1.2 版本使用以下 WS-Addressing 版本:

http://www.w3.org/2005/08/addressing

选择 WS-RM 版本

您可以选择要使用的 WS-RM 规格版本,如下所示:

服务器端
在供应商方面,Apache CXF 适应了客户端使用哪个版本的 WS-回复和相应的响应。
客户端
在客户端客户端上,WS-RM 版本由您在客户端配置中使用的命名空间决定(请参阅 第 21.5 节 “配置 WS-RM”),或在运行时覆盖 WS-RM 版本,使用运行时控制选项(请参阅 第 21.4 节 “运行时控制”)。

21.2. ws-RM Interceptors

概述

在 Apache CXF 中,WS-RM 功能作为拦截器实施。Apache CXF 运行时使用拦截器截获并使用正在发送和接收的原始消息。当传输收到消息时,它会创建一个消息对象,并通过拦截器链发送该消息。如果应用程序拦截器链包含 WS-RM 拦截器,则应用程序可以参与可靠的消息传递会话。WS-RM 拦截器处理消息块的集合和聚合。它们还处理所有确认和重新传输逻辑。

Apache CXF WS-RM Interceptors

Apache CXF WS-RM 实现由四个拦截器组成,在 表 21.1 “Apache CXF WS-ReliableMessaging Interceptors” 中描述。

表 21.1. Apache CXF WS-ReliableMessaging Interceptors

拦截器描述

org.apache.cxf.ws.rm.RMOutInterceptor

涉及为外发消息提供可靠性保证的逻辑方面。

负责发送 CreateSequence 请求并等待它们的 CreateSequenceResponse 响应。

此外,还负责聚合序列属性-ID 和消息编号(用于应用消息)。

org.apache.cxf.ws.rm.RMInInterceptor

负责截获和处理 RM 协议消息和 序列 消息,这些消息由应用程序消息提供支持。

org.apache.cxf.ws.rm.RMCaptureInInterceptor

为持久性存储缓存传入的信息。

org.apache.cxf.ws.rm.RMDeliveryInterceptor

有助于向应用程序传输消息。

org.apache.cxf.ws.rm.soap.RMSoapInterceptor

负责将可靠性属性编码并解码为 SOAP 标头。

org.apache.cxf.ws.rm.RetransmissionInterceptor

负责创建应用程序消息的副本以备将来重新发送。

启用 WS-RM

拦截器链中存在 WS-RM 拦截器可确保在需要时交换 WS-RM 协议消息。例如,在出站拦截器链中截获第一个应用程序消息时,RMOutInterceptor 会发送 CreateSequenceptor 请求,并等待处理原始应用程序消息,直到它收到 CreateSequence Response 响应。此外,WS-RM 拦截器将序列标头添加到应用程序消息中,并在目的地一侧从消息中提取它们。不需要对您的应用程序代码进行任何更改,以便可靠地交换消息。

有关如何启用 WS-RM 的更多信息,请参阅 第 21.3 节 “启用 WS-RM”

配置 WS-RM 属性

通过配置,您可以控制操作序列以及可靠交换的其他方面。例如,默认情况下,Apache CXF 尝试最大限度地提高序列生命周期,从而减少了带外 WS-RM 协议消息的开销。要强制每个应用程序消息使用单独的序列,请配置 WS-RM 源序列终止策略(将最大序列长度设置为 1)。

有关配置 WS-RM 行为的详情请参考 第 21.5 节 “配置 WS-RM”

21.3. 启用 WS-RM

概述

要启用可靠的消息传递,WS-RM 拦截器必须添加到入站和出站消息和故障的拦截器链中。由于 WS-RM 拦截器使用 WS-Addressing,所以 WS-Addressing 拦截器也必须存在于拦截器链中。

您可以通过以下两种方式之一来确保存在这些拦截器:

  • 通过使用 Spring Bean,把它们添加到 assign 链中,以 显式
  • 隐式,使用 WS-Policy 断言,导致 Apache CXF 运行时代表您透明地添加拦截器。

Spring Bean:显式添加拦截器

要启用 WS-RM 和 WS-Addressing 拦截器到 Apache CXF 总线,或使用 Spring bean 配置添加到消费者或服务端点。这是在 InstallDir/samples/ws_rm 目录中的 WS-RM 示例中采用的方法。配置文件 ws-rm.cxf 显示了 WS-RM 和 WS-Addressing 拦截器作为 Spring Bean(请参阅 例 21.1 “使用 Spring Beans 启用 WS-RM”

例 21.1. 使用 Spring Beans 启用 WS-RM

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/
   beans http://www.springframework.org/schema/beans/spring-beans.xsd">
   <bean id="mapAggregator" class="org.apache.cxf.ws.addressing.MAPAggregator"/>
   <bean id="mapCodec" class="org.apache.cxf.ws.addressing.soap.MAPCodec"/>
   <bean id="rmLogicalOut" class="org.apache.cxf.ws.rm.RMOutInterceptor">
        <property name="bus" ref="cxf"/>
   </bean>
   <bean id="rmLogicalIn" class="org.apache.cxf.ws.rm.RMInInterceptor">
        <property name="bus" ref="cxf"/>
   </bean>
   <bean id="rmCodec" class="org.apache.cxf.ws.rm.soap.RMSoapInterceptor"/>
   <bean id="cxf" class="org.apache.cxf.bus.CXFBusImpl">
        <property name="inInterceptors">
            <list>
                <ref bean="mapAggregator"/>
                <ref bean="mapCodec"/>
                <ref bean="rmLogicalIn"/>
                <ref bean="rmCodec"/>
            </list>
        </property>
        <property name="inFaultInterceptors">
            <list>
                <ref bean="mapAggregator"/>
                <ref bean="mapCodec"/>
                <ref bean="rmLogicalIn"/>
                <ref bean="rmCodec"/>
            </list>
        </property>
        <property name="outInterceptors">
            <list>
                <ref bean="mapAggregator"/>
                <ref bean="mapCodec"/>
                <ref bean="rmLogicalOut"/>
                <ref bean="rmCodec"/>
            </list>
        </property>
        <property name="outFaultInterceptors">
            <list>
                <ref bean="mapAggregator">
                <ref bean="mapCodec"/>
                <ref bean="rmLogicalOut"/>
                <ref bean="rmCodec"/>
            </list>
        </property>
    </bean>
</beans>

例 21.1 “使用 Spring Beans 启用 WS-RM” 中显示的代码可以按照以下方式解释:

Apache CXF 配置文件是一个 Spring XML 文件。您必须包含一个打开的 Spring Bean 元素,用于声明由 Bean 元素封装的子元素的命名空间和架构文件。

配置每个 WS-Addressing interceptors-MAPAggregatorMAPCodec。有关 WS-Addressing 的详情,请参考 第 20 章 部署 WS-Addressing

配置每个 WS-RM 拦截器-RMOutInterceptorRMInInterceptorRMSoapInterceptor

将 WS-Addressing 和 WS-RM 拦截器添加到入站消息的拦截器链中。

将 WS-Addressing 和 WS-RM 拦截器添加到入站故障的拦截器链中。

将 WS-Addressing 和 WS-RM 拦截器添加到出站消息的拦截器链中。

将 WS-Addressing 和 WS-RM 拦截器添加到出站故障的拦截器链中。

WS-Policy 框架:隐式添加拦截器

WS-Policy 框架提供了您可使用 WS-Policy 的基础架构和 API。它符合 2006 年 11 月发布的 Web 服务策略 1.5-FrameworkWeb 服务策略 1.5-Attachment 规格。

要使用 Apache CXF WS-Policy 框架启用 WS-RM,请执行以下操作:

  1. 在您的客户端和服务器端点中添加策略功能。例 21.2 “使用 WS-Policy 配置 WS-RM” 显示在 jaxws:feature 元素内嵌套的参考。referencean 指定 AddressingPolicy,它定义为同一配置文件内的独立元素。

    例 21.2. 使用 WS-Policy 配置 WS-RM

    <jaxws:client>
        <jaxws:features>
          <ref bean="AddressingPolicy"/>
        </jaxws:features>
    </jaxws:client>
    <wsp:Policy wsu:Id="AddressingPolicy" xmlns:wsam="http://www.w3.org/2007/02/addressing/metadata">
        <wsam:Addressing>
          <wsp:Policy>
            <wsam:NonAnonymousResponses/>
          </wsp:Policy>
        </wsam:Addressing>
    </wsp:Policy>
  2. wsdl:service 元素或任何其他 WSDL 元素添加可靠的消息传递策略,它们可用作策略或策略参考元素附加到 WSDL 文件的附件点,如 例 21.3 “在您的 WSDL 文件中添加 RM 策略” 所示。

    例 21.3. 在您的 WSDL 文件中添加 RM 策略

    <wsp:Policy wsu:Id="RM"
       xmlns:wsp="http://www.w3.org/2006/07/ws-policy"
       xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
        <wsam:Addressing xmlns:wsam="http://www.w3.org/2007/02/addressing/metadata">
            <wsp:Policy/>
        </wsam:Addressing>
        <wsrmp:RMAssertion xmlns:wsrmp="http://schemas.xmlsoap.org/ws/2005/02/rm/policy">
            <wsrmp:BaseRetransmissionInterval Milliseconds="10000"/>
        </wsrmp:RMAssertion>
    </wsp:Policy>
    ...
    <wsdl:service name="ReliableGreeterService">
        <wsdl:port binding="tns:GreeterSOAPBinding" name="GreeterPort">
            <soap:address location="http://localhost:9020/SoapContext/GreeterPort"/>
            <wsp:PolicyReference URI="#RM" xmlns:wsp="http://www.w3.org/2006/07/ws-policy"/>
        </wsdl:port>
    </wsdl:service>

21.4. 运行时控制

概述

可以在客户端代码中设置多个消息上下文属性值,以便在运行时控制 WS-RM,且由 org.apache.cxf.rm.rm.RMManager 类中的公共常量定义的关键值。

运行时控制选项

下表列出了 org.apache.cxf.ws.rm.RMManager 类定义的密钥。

描述

WSRM_VERSION_PROPERTY

字符串 WS-RM 版本命名空间(http://schemas.xmlsoap.org/ws/2005/02/rm/http://docs.oasis-open.org/ws-rx/wsrm/200702)。

WSRM_WSA_VERSION_PROPERTY

字符串 WS-Addressing 版本命名空间(http://schemas.xmlsoap.org/ws/2004/08/addressinghttp://www.w3.org/2005/08/addressing)- 除非您使用 http://schemas.xmlsoap.org/ws/2005/02/rm/ RM 命名空间,否则此属性将被忽略。

WSRM_LAST_MESSAGE_PROPERTY

布尔值为 true,用于告知 WS-RM 代码是要发送的最后一个消息,允许代码关闭 WS-RM 序列和释放资源(自 CXF 的 3.0.0 版本起,WS-RM 默认关闭 RM 序列)。

WSRM_INACTIVITY_TIMEOUT_PROPERTY

长期不活跃超时(以毫秒为单位)。

WSRM_RETRANSMISSION_INTERVAL_PROPERTY

以毫秒为单位进行较长的基本重新传输间隔。

WSRM_EXPONENTIAL_BACKOFF_PROPERTY

布尔值 exponential back-off 标记。

WSRM_ACKNOWLEDGEMENT_INTERVAL_PROPERTY

长期确认间隔(以毫秒为单位)。

通过 JMX 控制 WS-RM

您还可以使用 Apache CXF 的 JMX 管理功能监控和控制 WS-RM 的许多方面。JMX 操作的完整列表由 org.apache.cxf.ws.rm.ManagedRMManagerorg.apache.cxf.ws.rm.ManagedRMEndpoint 定义,但这些操作包括查看当前的 RM 状态到各个消息级别。您还可以使用 JXM 关闭或终止 WS-RM 序列,并接收之前由远程 RM 端点确认时发出的通知。

JMX 控制示例

例如,如果您的客户端配置中启用了 JMX 服务器,您可以使用以下代码跟踪接收的最后确认号:

// Java
private static class AcknowledgementListener implements NotificationListener {
    private volatile long lastAcknowledgement;

    @Override
    public void handleNotification(Notification notification, Object handback) {
        if (notification instanceof AcknowledgementNotification) {
            AcknowledgementNotification ack = (AcknowledgementNotification)notification;
            lastAcknowledgement = ack.getMessageNumber();
        }
    }

    // initialize client
...
    // attach to JMX bean for notifications
    //  NOTE: you must have sent at least one message to initialize RM before executing this code
    Endpoint ep = ClientProxy.getClient(client).getEndpoint();
    InstrumentationManager im = bus.getExtension(InstrumentationManager.class);
    MBeanServer mbs = im.getMBeanServer();
    RMManager clientManager = bus.getExtension(RMManager.class);
    ObjectName name = RMUtils.getManagedObjectName(clientManager, ep);
    System.out.println("Looking for endpoint name " + name);
    AcknowledgementListener listener = new AcknowledgementListener();
    mbs.addNotificationListener(name, listener, null, null);

    // send messages using RM with acknowledgement status reported to listener
...

21.5. 配置 WS-RM

21.5.1. 配置 Apache CXF 特定 WS-RM 属性

概述

要配置特定于 Apache CXF 的属性,请使用 rmManager Spring bean。在您的配置文件中添加以下内容:

例 21.4 “配置 Apache CXF 特定 WS-RM 属性” 显示了一个简单的示例。

例 21.4. 配置 Apache CXF 特定 WS-RM 属性

&lt;beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:wsrm-mgr="http://cxf.apache.org/ws/rm/manager"
      xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
 http://cxf.apache.org/ws/rm/manager http://cxf.apache.org/schemas/configuration/wsrm-manager.xsd"&gt;
...
&lt;wsrm-mgr:rmManager&gt;
&lt;!--
  ...Your configuration goes here
--&gt;
&lt;/wsrm-mgr:rmManager&gt;

rmManager Spring bean 的子项

表 21.2 “rmManager Spring Bean 的子项” 显示 http://cxf.apache.org/ws/rm/manager 命名空间中定义的 rmManager Spring bean 的子元素。

表 21.2. rmManager Spring Bean 的子项

元素描述

RMAsertion

类型为 RMA sertion 的元素

deliveryAssurance

Type DeliveryAsuranceType 的一个元素,用于描述应应用的交付保证

sourcePolicy

允许您配置 RM 源详情的 SourcePolicyType 的一个元素

destinationPolicy

允许您配置 RM 目的地详情的 DestinationPolicyType 的一个元素

示例

例如,请参阅 “最大未确认的消息阈值”一节

21.5.2. 配置标准 WS-RM 策略属性

概述

您可以使用以下方法之一配置标准 WS-RM 策略属性:

ws-Policy RMAsertion Children

表 21.3 “WS-Policy RMAsertion Element 的子项” 显示 http://schemas.xmlsoap.org/ws/2005/02/rm/policy 命名空间中定义的元素:

表 21.3. WS-Policy RMAsertion Element 的子项

名称描述

InactivityTimeout

指定在端点可以视为因为不活跃而终止的 RM 序列前必须收到消息的时长。

BaseRetransmissionInterval

设置确认在给定消息中的 RM Source 必须接收的时间间隔。如果在 BaseRetransmissionInterval 设置的时间内未收到确认,则 RM Source 将重新传输该消息。

ExponentialBackoff

指示将使用已知指数级 backoff 算法(Tanenbaum)调整重新传输间隔。

如需更多信息,请参阅 Computer Networks、Andrew S. Tanenbaum、Prentice Hall PTR, 2003。

AcknowledgementInterval

在 WS-RM 中,确认信息会在返回消息上发送或独立发送。如果无法发送确认消息的返回消息,则 RM Destination 可在发送独立确认前等待确认间隔。如果没有未确认的消息,RM Destination 可以选择不发送确认消息。

更详细的参考信息

有关更详细的参考信息,包括每个元素的子元素和属性的描述,请参阅 http://schemas.xmlsoap.org/ws/2005/02/rm/wsrm-policy.xsd

rmManager Spring bean 中的 RMAssertion

您可以通过在 Apache CXF rmManager Spring bean 中添加 RMA sertion 来配置标准 WS-RM 策略属性。如果您要在同一配置文件中保留所有 WS-RM 配置,则这是最好的方法。也就是说,如果要配置同一文件中特定于 Apache CXF 的属性和标准 WS-RM 策略属性。

例如,例 21.5 “使用 rmManager Spring Bean 中的 RMAsertion 配置 WS-RM 属性” 中的配置会显示:

  • 标准 WS-RM 策略属性 BaseRetransmissionInterval 使用 rmManager Spring bean 中的 RMAsertion 配置。
  • 在同一配置文件中配置 Apache CXF 特定 RM 属性 intraMessageThreshold

例 21.5. 使用 rmManager Spring Bean 中的 RMAsertion 配置 WS-RM 属性

<beans xmlns:wsrm-policy="http://schemas.xmlsoap.org/ws/2005/02/rm/policy"
       xmlns:wsrm-mgr="http://cxf.apache.org/ws/rm/manager"
...>
<wsrm-mgr:rmManager id="org.apache.cxf.ws.rm.RMManager">
    <wsrm-policy:RMAssertion>
        <wsrm-policy:BaseRetransmissionInterval Milliseconds="4000"/>
    </wsrm-policy:RMAssertion>
    <wsrm-mgr:destinationPolicy>
        <wsrm-mgr:acksPolicy intraMessageThreshold="0" />
    </wsrm-mgr:destinationPolicy>
</wsrm-mgr:rmManager>
</beans>

功能中的策略

您可以在功能中配置标准 WS-RM 策略属性,如 例 21.6 “在功能内将 WS-RM 属性配置为策略” 所示。

例 21.6. 在功能内将 WS-RM 属性配置为策略

<xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:wsa="http://cxf.apache.org/ws/addressing"
        xmlns:wsp="http://www.w3.org/2006/07/ws-policy"
        xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
        xmlns:jaxws="http://cxf.apache.org/jaxws"
        xsi:schemaLocation="
http://www.w3.org/2006/07/ws-policy http://www.w3.org/2006/07/ws-policy.xsd
http://cxf.apache.org/ws/addressing http://cxf.apache.org/schema/ws/addressing.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <jaxws:endpoint name="{http://cxf.apache.org/greeter_control}GreeterPort" createdFromAPI="true">
        <jaxws:features>
               <wsp:Policy>
                   <wsrm:RMAssertion xmlns:wsrm="http://schemas.xmlsoap.org/ws/2005/02/rm/policy">
                     <wsrm:AcknowledgementInterval Milliseconds="200" />
                   </wsrm:RMAssertion>
                   <wsam:Addressing xmlns:wsam="http://www.w3.org/2007/02/addressing/metadata">
                       <wsp:Policy>
                            <wsam:NonAnonymousResponses/>
                       </wsp:Policy>
                   </wsam:Addressing>
              </wsp:Policy>
        </jaxws:features>
    </jaxws:endpoint>
</beans>

WSDL 文件

如果使用 WS-Policy 框架启用 WS-RM,您可以在 WSDL 文件中配置标准 WS-RM 策略属性。如果您希望服务互操作并使用 WS-RM 与部署到其他策略感知型 Web 服务堆栈的用户,最好采用这种方法。

例如,请参阅 “WS-Policy 框架:隐式添加拦截器”一节,其中在 WSDL 文件中配置了基本重新传输间隔。

外部附加

您可以在外部附加文件中配置标准 WS-RM 策略属性。如果您无法更改 WSDL 文件,这是个好方法。

例 21.7 “在外部附加中配置 WS-RM” 显示为特定 EPR 启用 WS-A 和 WS-RM(基本传输间隔为 30 秒)的外部附加。

例 21.7. 在外部附加中配置 WS-RM

<attachments xmlns:wsp="http://www.w3.org/2006/07/ws-policy" xmlns:wsa="http://www.w3.org/2005/08/addressing">
    <wsp:PolicyAttachment>
        <wsp:AppliesTo>
           <wsa:EndpointReference>
                <wsa:Address>http://localhost:9020/SoapContext/GreeterPort</wsa:Address>
            </wsa:EndpointReference>
        </wsp:AppliesTo>
        <wsp:Policy>
            <wsam:Addressing xmlns:wsam="http://www.w3.org/2007/02/addressing/metadata">
                <wsp:Policy/>
            </wsam:Addressing>
            <wsrmp:RMAssertion xmlns:wsrmp="http://schemas.xmlsoap.org/ws/2005/02/rm/policy">
                <wsrmp:BaseRetransmissionInterval Milliseconds="30000"/>
            </wsrmp:RMAssertion>
        </wsp:Policy>
    </wsp:PolicyAttachment>
</attachments>/

21.5.3. WS-RM 配置用例

概述

本小节着重介绍从用例的角度配置 WS-RM 属性。其中属性是一个标准的 WS-RM 策略属性(在 http://schemas.xmlsoap.org/ws/2005/02/rm/policy/ 命名空间中定义),只会显示在 rmManager Spring bean 中的 RMAsertion 中设置它的示例。有关如何在功能内设置这样的属性(如策略)的详情 ; 在 WSDL 文件中或外部附件中,请参阅 第 21.5.2 节 “配置标准 WS-RM 策略属性”

涵盖以下用例:

基本重新传输间隔

BaseRetransmissionInterval 元素指定在 RM 源重新传输了尚未确认的消息的时间间隔。它在 http://schemas.xmlsoap.org/ws/2005/02/rm/wsrm-policy.xsd 模式文件中定义。默认值为 3000 毫秒。

例 21.8 “设置 WS-RM Base Retransmission Interval” 显示如何设置 WS-RM 基本重新传输间隔。

例 21.8. 设置 WS-RM Base Retransmission Interval

<beans xmlns:wsrm-policy="http://schemas.xmlsoap.org/ws/2005/02/rm/policy
...>
<wsrm-mgr:rmManager id="org.apache.cxf.ws.rm.RMManager">
    <wsrm-policy:RMAssertion>
        <wsrm-policy:BaseRetransmissionInterval Milliseconds="4000"/>
    </wsrm-policy:RMAssertion>
</wsrm-mgr:rmManager>
</beans>

重新传输的 backoff

ExponentialBackoff 元素确定是否以指数级间隔执行对未确认消息的连续性重新传输尝试。

ExponentialBackoff 元素将启用此功能。默认情况下会使用 2 的 exponential backoff 比例。ExponentialBackoff 是一个标志。当元素存在时,会启用 exponential backoff。当元素不存在时,会禁用 exponential backoff。不需要值。

例 21.9 “设置 WS-RM Exponential Backoff Property” 演示了如何为重新传输设置 WS-RM exponential backoff。

例 21.9. 设置 WS-RM Exponential Backoff Property

<beans xmlns:wsrm-policy="http://schemas.xmlsoap.org/ws/2005/02/rm/policy
...>
<wsrm-mgr:rmManager id="org.apache.cxf.ws.rm.RMManager">
    <wsrm-policy:RMAssertion>
        <wsrm-policy:ExponentialBackoff/>
    </wsrm-policy:RMAssertion>
</wsrm-mgr:rmManager>
</beans>

确认的时间间隔

AcknowledgementInterval 元素指定 WS-RM 目标发送异步确认的时间间隔。除了同步确认外,还需要接收传入的消息。默认的异步确认间隔为 0 毫秒。这意味着,如果 AcknowledgementInterval 没有配置为特定值,确认将立即发送(即首次可用的商机)。

只有在满足以下条件时,RM 目的地才会发送异步确认:

  • RM 目的地使用非匿名 wsrm:acksTo 端点。
  • 在确认间隔到期前不会发生对响应消息的确认机会。

例 21.10 “设置 WS-RM Acknowledgement Interval” 显示如何设置 WS-RM 确认间隔。

例 21.10. 设置 WS-RM Acknowledgement Interval

<beans xmlns:wsrm-policy="http://schemas.xmlsoap.org/ws/2005/02/rm/policy
...>
<wsrm-mgr:rmManager id="org.apache.cxf.ws.rm.RMManager">
    <wsrm-policy:RMAssertion>
        <wsrm-policy:AcknowledgementInterval Milliseconds="2000"/>
    </wsrm-policy:RMAssertion>
</wsrm-mgr:rmManager>
</beans>

最大未确认的消息阈值

maxUnacknowledged 属性设置在序列被终止前每个序列的最大未确认消息数。

例 21.11 “设置 WS-RM Maximum Unacknowledged Message Threshold” 展示如何设置 WS-RM 的最大消息阈值。

例 21.11. 设置 WS-RM Maximum Unacknowledged Message Threshold

<beans xmlns:wsrm-mgr="http://cxf.apache.org/ws/rm/manager
...>
<wsrm-mgr:reliableMessaging>
    <wsrm-mgr:sourcePolicy>
        <wsrm-mgr:sequenceTerminationPolicy maxUnacknowledged="20" />
    </wsrm-mgr:sourcePolicy>
</wsrm-mgr:reliableMessaging>
</beans>

RM 序列的最大长度

maxLength 属性设置 WS-RM 序列的最大长度。默认值为 0, 这表示 WS-RM 序列的长度未绑定。

当设置此属性时,RM 端点会在达到限制时创建一个新的 RM 序列,并在收到之前发送的消息的所有确认后。使用 newsequence 发送新消息。

例 21.12 “设置 WS-RM 消息序列的最大长度” 演示了如何设置 RM 序列的最大长度。

例 21.12. 设置 WS-RM 消息序列的最大长度

<beans xmlns:wsrm-mgr="http://cxf.apache.org/ws/rm/manager
...>
<wsrm-mgr:reliableMessaging>
    <wsrm-mgr:sourcePolicy>
        <wsrm-mgr:sequenceTerminationPolicy maxLength="100" />
    </wsrm-mgr:sourcePolicy>
</wsrm-mgr:reliableMessaging>
</beans>

消息发送保障策略

您可以将 RM 目的地配置为使用以下发送保证策略:

  • AtMostOnce - RM 目标仅向应用程序目的地发送消息一次。如果发生错误后传送的信息超过。序列中的一些消息可能无法发送。
  • AtLeastOnce - RM 目的地至少向应用目的地发送消息。发送的每个消息都会被发送,否则将引发错误。有些信息可能会多次传送。
  • InOrder - RM 目标以发送顺序向应用程序目的地发送消息。这种交付保证可与 AtMostOnceAtLeastOnce 保障相结合。

例 21.13 “设置 WS-RM Message Delivery Assurance 策略” 展示如何设置 WS-RM 消息发送保证。

例 21.13. 设置 WS-RM Message Delivery Assurance 策略

<beans xmlns:wsrm-mgr="http://cxf.apache.org/ws/rm/manager
...>
<wsrm-mgr:reliableMessaging>
    <wsrm-mgr:deliveryAssurance>
        <wsrm-mgr:AtLeastOnce />
    </wsrm-mgr:deliveryAssurance>
</wsrm-mgr:reliableMessaging>
</beans>

21.6. 配置 WS-RM Persistence

概述

本章中已描述的 Apache CXF WS-RM 功能为网络故障(如网络故障)提供了可靠性。WS-RM 持久性提供其它类型故障的可靠性,如 RM 源或 RM 目标崩溃。

WS-RM 持久性涉及将各种 RM 端点的状态存储在持久存储中。这可让端点在被重试时继续发送和接收信息。

Apache CXF 在配置文件中启用 WS-RM 持久性。默认的 WS-RM 持久存储基于 JDBC。为方便起见,Apache CXF 包括 Derby 用于开箱即用的部署。此外,持久存储也使用 Java API 进行公开。要实现自己的持久性机制,您可以使用这个 API 与首选 DB 来实施。

重要

WS-RM 持久性只支持单向调用,默认是禁用的。

如何使用

Apache CXF WS-RM 持久性的工作方式如下:

  • 在 RM 源端点中,传出的消息会在传输前保留。在收到确认后,它将从持久性存储中驱除。
  • 在从崩溃中恢复后,它会恢复永久性的消息并重新传输,直到所有消息都已确认。此时,RM 序列是关闭的。
  • 在 RM 目标端点中,传入的信息会被保留,并在成功存储后发送确认。当成功分配消息时,它将从持久性存储中驱除。
  • 在从崩溃中恢复后,它会恢复保留的消息并分配它们。它还会使 RM 序列进入接受、确认和发送新消息的状态。

启用 WS-persistence

要启用 WS-RM 持久性,您必须指定为 WS-RM 实施持久性存储的对象。您可以自行开发,也可以使用 Apache CXF 附带的基于 JDBC 的存储。

例 21.14 “配置默认 WS-RM Persistence 存储” 中显示的配置可启用基于 JDBC 的存储,该存储带有 Apache CXF。

例 21.14. 配置默认 WS-RM Persistence 存储

<bean id="RMTxStore" class="org.apache.cxf.ws.rm.persistence.jdbc.RMTxStore"/>
<wsrm-mgr:rmManager id="org.apache.cxf.ws.rm.RMManager">
    <property name="store" ref="RMTxStore"/>
</wsrm-mgr:rmManager>

配置 WS-persistence

Apache CXF 附带的基于 JDBC 的存储支持 表 21.4 “JDBC 存储属性” 中显示的属性。

表 21.4. JDBC 存储属性

属性名称类型默认设置

driverClassName

字符串

org.apache.derby.jdbc.EmbeddedDriver

userName

字符串

null

passWord

字符串

null

url

字符串

jdbc:derby:rmdb;create=true

例 21.15 “为 WS-RM Persistence 配置 JDBC 存储” 中显示的配置可启用与 Apache CXF 附带的基于 JDBC 的存储,同时将 driverClassNameurl 设置为非默认值。

例 21.15. 为 WS-RM Persistence 配置 JDBC 存储

<bean id="RMTxStore" class="org.apache.cxf.ws.rm.persistence.jdbc.RMTxStore">
    <property name="driverClassName" value="com.acme.jdbc.Driver"/>
    <property name="url" value="jdbc:acme:rmdb;create=true"/>
</bean>

第 22 章 启用高可用性

摘要

本章论述了如何在 Apache CXF 运行时启用和配置高可用性。

22.1. 高可用性简介

概述

可扩展且可靠的应用程序需要高可用性来避免分布式系统中的单点故障。您可以使用 来保护您的系统不受单一故障点 复制的服务

复制的服务由同一服务 的多个实例 或副本组成。两者结合为一个逻辑服务。客户端调用复制服务上的请求,而 Apache CXF 则向其中一个成员副本提供请求。到副本的路由对客户端是透明的。

具有静态故障转移的 HA

Apache CXF 支持使用静态故障转移的高可用性(HA),其中副本详情是在服务 WSDL 文件中编码的。WSDL 文件包含多个端口,可以包含多个主机,可以针对同一服务包含多个主机。只要 WSDL 文件保持不变,集群中的副本数会一直保持静态。更改集群大小涉及编辑 WSDL 文件。

22.2. 使用静态故障切换启用 HA

概述

要使用静态故障转移启用 HA,您必须执行以下操作:

在您的服务 WSDL 文件中编码副本详情

您必须在服务 WSDL 文件中对集群中的副本进行编码。例 22.1 “使用静态故障转移启用 HA:WSDL 文件” 显示 WSDL 文件提取,以定义三个副本的服务集群。

例 22.1. 使用静态故障转移启用 HA:WSDL 文件

<wsdl:service name="ClusteredService">
    <wsdl:port binding="tns:Greeter_SOAPBinding" name="Replica1">
        <soap:address location="http://localhost:9001/SoapContext/Replica1"/>
    </wsdl:port>

    <wsdl:port binding="tns:Greeter_SOAPBinding" name="Replica2">
        <soap:address location="http://localhost:9002/SoapContext/Replica2"/>
    </wsdl:port>

    <wsdl:port binding="tns:Greeter_SOAPBinding" name="Replica3">
        <soap:address location="http://localhost:9003/SoapContext/Replica3"/>
    </wsdl:port>

</wsdl:service>

例 22.1 “使用静态故障转移启用 HA:WSDL 文件” 中显示的 WSDL 提取可以解释如下:

定义服务 ClusterService,它在三个端口上公开:

  1. Replica1
  2. Replica2
  3. Replica3

定义 Replica1,以通过端口 9001 上的 HTTP 端点公开 ClusterService 作为 SOAP。

定义 Replica2,以在端口 9002 上通过 HTTP 端点公开 ClusterService 作为 SOAP。

定义 Replica3,以在端口 9003 上通过 HTTP 端点公开 ClusterService 作为 SOAP。

在您的客户端配置中添加集群功能

在客户端配置文件中,添加集群功能,如 例 22.2 “使用静态故障转移启用 HA:客户端配置” 所示。

例 22.2. 使用静态故障转移启用 HA:客户端配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:jaxws="http://cxf.apache.org/jaxws"
       xmlns:clustering="http://cxf.apache.org/clustering"
         xsi:schemaLocation="http://cxf.apache.org/jaxws
         http://cxf.apache.org/schemas/jaxws.xsd
         http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans.xsd">

    <jaxws:client name="{http://apache.org/hello_world_soap_http}Replica1"
                  createdFromAPI="true">
        <jaxws:features>
            <clustering:failover/>
        </jaxws:features>
    </jaxws:client>

    <jaxws:client name="{http://apache.org/hello_world_soap_http}Replica2"
                  createdFromAPI="true">
        <jaxws:features>
            <clustering:failover/>
        </jaxws:features>
    </jaxws:client>

    <jaxws:client name="{http://apache.org/hello_world_soap_http}Replica3"
                  createdFromAPI="true">
        <jaxws:features>
            <clustering:failover/>
        </jaxws:features>
    </jaxws:client>

</beans>

22.3. 使用静态故障切换配置 HA

概述

默认情况下,如果与客户端通信不可用的原始服务不可用,则带有静态故障转移的 HA 会在选择副本服务时使用后续策略。后续策略在每次使用时都会以连续顺序选择一个副本服务。选择由 Apache CXF 的内部服务模型决定,生成确定性故障转移模式。

配置随机策略

在选择副本时,您可以使用静态故障转移配置 HA 来使用随机策略,而不是后续策略。random 策略在每次服务不可用时选择一个随机副本服务,或者出现故障。从集群中的surviv 成员中故障转移目标选择完全是随机的。

要配置随机策略,请将 例 22.3 “为静态故障转移配置 Random 策略” 中显示的配置添加到您的客户端配置文件中。

例 22.3. 为静态故障转移配置 Random 策略

<beans ...>
    <bean id="Random" class="org.apache.cxf.clustering.RandomStrategy"/>

    <jaxws:client name="{http://apache.org/hello_world_soap_http}Replica3"
                  createdFromAPI="true">
        <jaxws:features>
            <clustering:failover>
                <clustering:strategy>
                    <ref bean="Random"/>
                </clustering:strategy>
            </clustering:failover>
        </jaxws:features>
    </jaxws:client>
</beans>

例 22.3 “为静态故障转移配置 Random 策略” 中显示的配置可以解释如下:

定义实施随机策略的 Random bean 和实施类。

指定在选择副本时使用随机策略。

第 23 章 Apache CXF Binding ID

绑定 ID 表

附录 A. 使用 Maven OSGi 工具

摘要

为大项目手动创建捆绑包或捆绑包集合可能非常繁琐。Maven bundle 插件使作业通过自动化过程,并提供多个快捷方式来指定捆绑包清单的内容,从而更容易工作。

A.1. Maven Bundle Plug-In

红帽 Fuse OSGi 工具使用 Apache Felix 的 Maven 捆绑包插件。捆绑插件基于 Peter Kriens 中的 bnd 工具。它通过内省捆绑包中打包的类的内容,实现 OSGi 捆绑清单的构造。利用捆绑包中包含的类知识,插件可以计算正确的值,以填充捆绑包清单中的 Import-PackagesExport-Package 属性。该插件也具有用于捆绑清单中其他必要属性的默认值。

要使用 bundle 插件,请执行以下操作:

  1. 第 A.2 节 “设置红帽 Fuse OSGi 项目” 捆绑包插件到您的项目的 POM 文件。
  2. 第 A.3 节 “配置捆绑插件” 该插件用于正确填充捆绑包的清单。

A.2. 设置红帽 Fuse OSGi 项目

概述

用于构建 OSGi 捆绑包的 Maven 项目可以是一个简单级别的项目。它不需要任何子项目。但是,它需要您执行以下操作:

  1. 捆绑包插件添加到您的 POM。
  2. 指示 Maven 将结果打包为 OSGi 捆绑包。
注意

您可以使用几个 Maven archetypes 来设置项目及适当的设置。

目录结构

创建 OSGi 捆绑包的项目可以是单一级别的项目。它只需要有一个顶层 POM 文件和一个 src 文件夹。与所有 Maven 项目中一样,您要将所有 Java 源代码放在 src/java 文件夹中,并且您将任何非 Java 资源放到 src/resources 文件夹中。

非 Java 资源包括 Spring 配置文件、JBI 端点配置文件和 WSDL 合同。

注意

使用 Apache CXF、Apache Camel 或其他 Spring 配置的红帽 Fuse OSGi 项目还包括一个 Bean,它还包含 src/resources/META-INF/spring 文件夹中的 Bean.xml 文件。

添加 bundle 插件

在使用捆绑插件前,您必须添加对 Apache Felix 的依赖。添加依赖项后,您可以将捆绑包插件添加到 POM 的插件部分。

例 A.1 “将 OSGi 捆绑包插件添加到 POM” 显示将捆绑包插件添加到您的项目所需的 POM 条目。

例 A.1. 将 OSGi 捆绑包插件添加到 POM

...
<dependencies>
  <dependency>
    <groupId>org.apache.felix</groupId>
    <artifactId>org.osgi.core</artifactId>
    <version>1.0.0</version>
  </dependency>
...
</dependencies>
...
<build>
  <plugins>
    <plugin>
      <groupId>org.apache.felix</groupId>
      <artifactId>maven-bundle-plugin</artifactId>
      <configuration>
        <instructions>
          <Bundle-SymbolicName>${pom.artifactId}</Bundle-SymbolicName>
          <Import-Package>*,org.apache.camel.osgi</Import-Package>
          <Private-Package>org.apache.servicemix.examples.camel</Private-Package>
        </instructions>
      </configuration>
    </plugin>
  </plugins>
</build>
...

例 A.1 “将 OSGi 捆绑包插件添加到 POM” 中的条目执行以下操作:

添加 Apache Felix 的依赖

将 bundle 插件添加到项目中

配置插件以使用项目的工件 ID 作为捆绑包的符号链接

配置插件以包含捆绑类导入的所有 Java 软件包;还可导入 org.apache.camel.osgi 软件包

配置插件以捆绑列出的类,但不将其包含在导出软件包列表中

注意

编辑配置以满足您的项目要求。

有关配置捆绑插件的详情请参考 第 A.3 节 “配置捆绑插件”

激活捆绑包插件

要让 Maven 使用 bundle 插件,请指示它将项目的结果打包为捆绑包。通过将 POM 文件的 打包 元素设置为 bundle 来完成此操作。

有用的 Maven archetypes

有几种 Maven archetypes 可以生成预配置的项目来使用 bundle 插件:

Spring OSGi archetype

Spring OSGi archetype 创建通用项目以使用 Spring DM 构建 OSGi 项目,如下所示:

org.springframework.osgi/spring-bundle-osgi-archetype/1.1.2

您可以使用以下命令调用 archetype:

mvn archetype:generate -DarchetypeGroupId=org.springframework.osgi -DarchetypeArtifactId=spring-osgi-bundle-archetype -DarchetypeVersion=1.1.2 -DgroupId=groupId -DartifactId=artifactId -Dversion=version

Apache CXF code-first archetype

Apache CXF code-first archetype 创建一个项目,用于从 Java 构建服务,如下所示:

org.apache.servicemix.tooling/servicemix-osgi-cxf-code-first-archetype/2010.02.0-fuse-02-00

您可以使用以下命令调用 archetype:

mvn archetype:generate -DarchetypeGroupId=org.apache.servicemix.tooling -DarchetypeArtifactId=servicemix-osgi-cxf-code-first-archetype -DarchetypeVersion=2010.02.0-fuse-02-00 -DgroupId=groupId -DartifactId=artifactId -Dversion=version

Apache CXF wsdl-first archetype

Apache CXF wsdl-first archetype 创建一个项目,用于从 WSDL 创建服务,如下所示:

org.apache.servicemix.tooling/servicemix-osgi-cxf-wsdl-first-archetype/2010.02.0-fuse-02-00

您可以使用以下命令调用 archetype:

mvn archetype:generate -DarchetypeGroupId=org.apache.servicemix.tooling -DarchetypeArtifactId=servicemix-osgi-cxf-wsdl-first-archetype -DarchetypeVersion=2010.02.0-fuse-02-00 -DgroupId=groupId -DartifactId=artifactId -Dversion=version

Apache Camel archetype

Apache Camel archetype 创建了一个项目,用于构建部署到 Red Hat Fuse 中的路由,如下所示:

org.apache.servicemix.tooling/servicemix-osgi-camel-archetype/2010.02.0-fuse-02-00

您可以使用以下命令调用 archetype:

mvn archetype:generate -DarchetypeGroupId=org.apache.servicemix.tooling -DarchetypeArtifactId=servicemix-osgi-camel-archetype -DarchetypeVersion=2010.02.0-fuse-02-00 -DgroupId=groupId -DartifactId=artifactId -Dversion=version

A.3. 配置捆绑插件

概述

捆绑包插件需要很少的信息才能正常工作。所有所需属性都使用默认设置来生成有效的 OSGi 捆绑包。

虽然您可以使用默认值创建有效的捆绑包,但您可能需要修改某些值。您可以在插件的 instructions 元素中指定大多数属性。

配置属性

一些常用的配置属性有:

设置捆绑包的符号链接

默认情况下,Bundle 插件将 Bundle-SymbolicName 属性的值设置为 groupId + "." + artifactId,其例外情况如下:

  • 如果 groupId 只有一个部分(无点),则返回第一个带有类的软件包名称。

    例如,如果组 Id 是 commons-logging:commons-logging,则捆绑包的符号链接是 org.apache.commons.logging

  • 如果 artifactId 等于 groupId 的最后部分,则使用 groupId

    例如,如果 POM 指定组 ID 和工件 ID 作为 org.apache.maven:maven,则捆绑包的符号链接名为 org.apache.maven

  • 如果 artifactIdgroupId 的最后部分开始,该部分会被删除。

    例如,如果 POM 指定组 ID 和工件 ID 作为 org.apache.maven:maven-core,则捆绑包的符号链接名为 org.apache.maven.core

要为捆绑包符号名称指定您自己的值,在插件的 instructions 元素中添加 Bundle-SymbolicName 子,如 例 A.2 “设置捆绑包的符号链接” 所示。

例 A.2. 设置捆绑包的符号链接

<plugin>
  <groupId>org.apache.felix</groupId>
  <artifactId>maven-bundle-plugin</artifactId>
  <configuration>
   <instructions>
     <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
     ...
    </instructions>
  </configuration>
</plugin>

设置捆绑包的名称

默认情况下,捆绑包的名称设置为 ${project.name}

要为捆绑包名称指定您自己的值,在插件的 instructions 元素中添加 Bundle-Name 子部分,如 例 A.3 “设置捆绑包的名称” 所示。

例 A.3. 设置捆绑包的名称

<plugin>
  <groupId>org.apache.felix</groupId>
  <artifactId>maven-bundle-plugin</artifactId>
  <configuration>
   <instructions>
     <Bundle-Name>JoeFred</Bundle-Name>
     ...
    </instructions>
  </configuration>
</plugin>

设置捆绑包的版本

默认情况下,捆绑包的版本设置为 ${project.version}。所有横线(-)替换为句点(.),数字最多可为四位数。例如,4.2-SNAPSHOT 变为 4.2.0.SNAPSHOT

要为捆绑包版本指定您自己的值,将 Bundle-Version 子添加到插件的 instructions 元素中,如 例 A.4 “设置捆绑包的版本” 所示。

例 A.4. 设置捆绑包的版本

<plugin>
  <groupId>org.apache.felix</groupId>
  <artifactId>maven-bundle-plugin</artifactId>
  <configuration>
   <instructions>
     <Bundle-Version>1.0.3.1</Bundle-Version>
     ...
    </instructions>
  </configuration>
</plugin>

指定导出的软件包

默认情况下,OSOS 清单的 Export-Package 列表由您的本地 Java 源代码中的所有软件包(在 src/main/java 下)填充(在 src/main/java下), 默认软件包. 以及包含 .impl.internal 的软件包。

重要

如果您在插件配置中使用 Private-Package 元素,且您没有指定要导出的软件包列表,则默认行为仅包含捆绑包中的 Private-Package 元素中列出的软件包。没有导出软件包。

默认行为可能会导致非常大的软件包,并导出应保持私有的软件包。要更改导出的软件包列表,您可以在插件的 instructions 元素中添加 Export-Package child。

Export-Package 元素指定要包含在捆绑包中的软件包列表,并要导出。可以使用 * 通配符符号指定软件包名称。例如,条目 com.fuse.demo.* 包含项目类路径上以 com.fuse.demo 开头的所有软件包。

您可以指定要排除的软件包,用 ! 前缀。例如,条目 !com.fuse.demo.private 排除软件包 com.fuse.demo.private

当排除软件包时,列表中的条目顺序非常重要。这个列表会根据开始的顺序处理,并忽略后续迭代条目。

例如,要包含以 com.fuse.demo 开头的所有软件包,除了软件包 com.fuse.demo.private 外,请使用以下内容列出软件包:

!com.fuse.demo.private,com.fuse.demo.*

但是,如果您使用 com.fuse.demo.*,!com.fuse.demo.private 列出软件包,那么捆绑包中包含 com.fuse.demo.private,因为它与第一个模式匹配。

指定私有软件包

如果要在导出捆绑包中指定要包含在捆绑包中的软件包列表,您可以在捆绑包插件配置中添加 Private-Package 指令。默认情况下,如果您没有指定 Private-Package 指令,则捆绑包中包含您本地 Java 源中的所有软件包。

重要

如果软件包与 Private-Package 元素和 Export-Package 元素中的条目匹配,则 Export-Package 元素将具有优先权。软件包会添加到捆绑包中并导出。

Private-Package 元素的工作方式与 导出-Package 元素类似,您会指定要包含在捆绑包中的软件包列表。bundle 插件使用列表来查找要包含在捆绑包中的项目的类路径上的所有类。这些软件包打包在捆绑包中,但不导出(除非它们也由 Export-Package 指令选择)。

例 A.5 “在捆绑包中包含私有软件包” 显示在捆绑包中包含私有软件包的配置

例 A.5. 在捆绑包中包含私有软件包

<plugin>
  <groupId>org.apache.felix</groupId>
  <artifactId>maven-bundle-plugin</artifactId>
  <configuration>
   <instructions>
     <Private-Package>org.apache.cxf.wsdlFirst.impl</Private-Package>
     ...
    </instructions>
  </configuration>
</plugin>

指定导入的软件包

默认情况下,Bundle 插件使用捆绑包内容引用的所有软件包列表填充 OSGi 清单的 Import-Package 属性。

虽然默认行为通常足以满足大多数项目,但您可能会发现您要导入不会自动添加到列表中的软件包的实例。默认行为也可以导致导入不需要的软件包。

要指定要由捆绑包导入的软件包列表,请将 Import-Package child 添加到插件的 instructions 元素中。软件包列表的语法与 Export-Package 元素和 Private-Package 元素的语法相同。

重要

使用 Import-Package 元素时,插件不会自动扫描捆绑包的内容,以确定是否存在所需的导入。要确保对捆绑包的内容进行了扫描,您必须在软件包列表中放置一个 * 作为最后一个条目。

例 A.6 “指定捆绑包导入的软件包” 显示指定捆绑包导入的软件包的配置

例 A.6. 指定捆绑包导入的软件包

<plugin>
  <groupId>org.apache.felix</groupId>
  <artifactId>maven-bundle-plugin</artifactId>
  <configuration>
   <instructions>
     <Import-Package>javax.jws, javax.wsdl, org.apache.cxf.bus, org.apache.cxf.bus.spring, org.apache.cxf.bus.resource, org.apache.cxf.configuration.spring, org.apache.cxf.resource, org.springframework.beans.factory.config, * </Import-Package>
     ...
   </instructions>
  </configuration>
</plugin>

更多信息

有关配置捆绑包插件的详情,请参考:

部分 V. 使用 JAX-WS 开发应用程序

本指南介绍了如何使用标准 JAX-WS API 开发 Web 服务。

第 24 章 底层服务开发

摘要

有许多实例,您的 Java 代码已实现一组功能,您希望作为面向服务的应用程序的一部分公开。您可能还想避免使用 WSDL 来定义接口。使用 JAX-WS 注释,您可以添加 service 启用 Java 类所需的信息。您还可以创建一个 可以代替 WSDL 合同的服务端点接口 (SEI)。如果您需要 WSDL 合同,Apache CXF 提供了从标注的 Java 代码生成合同的工具。

24.1. JAX-WS 服务开发简介

要创建从 Java 启动的服务,您必须执行以下操作:

  1. 第 24.2 节 “创建 SEI” 一个 Service Endpoint Interface(SEI),用于定义您要作为服务公开的方法。

    注意

    您可以直接从 Java 类工作,但建议从接口操作。接口更适合与负责开发使用服务的应用程序的开发人员共享。这个接口比较小,不提供任何服务的实现详情。

  2. 第 24.3 节 “为代码添加注解” 代码所需的注解。
  3. 第 24.4 节 “生成 WSDL” 您的服务的 WSDL 合同。

    注意

    如果要使用 SEI 作为服务的合同,则不需要生成 WSDL 合同。

  4. 第 31 章 发布服务 服务作为服务提供商。

24.2. 创建 SEI

概述

服务端点接口 (SEI)是服务实施与在该服务上发出请求的消费者之间共享的 Java 代码。SEI 定义服务实施的方法,并提供了有关如何将服务公开为端点的详细信息。从 WSDL 合同开始时,SEI 由代码生成器生成。但是,从 Java 开始,开发人员负责创建 SEI。 创建 SEI 的基本模式有两个:

  • 绿色字段开发 - 在这个模式中,您要开发没有现有 Java 代码或 WSDL 的新服务。最先创建 SEI。然后,您可以将 SEI 分发给负责实施使用 SEI 的服务供应商和消费者的任何开发人员。

    注意

    推荐使用绿色字段服务开发的方法是创建一个定义服务及其接口的 WSDL 合同。请参阅 第 26 章 开始点 WSDL 合同

  • 服务启用 - 在这个模式中,您通常具有作为 Java 类实施的现有功能集,并且您要启用该服务。这意味着您必须执行两个操作:

    1. 创建一个 SEI,它只包含作为服务的一部分公开的操作。
    2. 修改现有的 Java 类,以便其实现 SEI。

      注意

      虽然您可以将 JAX-WS 注释添加到 Java 类,但不建议这样做。

编写接口

SEI 是一个标准 Java 接口。它定义一组类实施的方法。它还可定义多个成员字段以及实施类可访问的常量。

如果是 SEI,定义的方法旨在映射到服务所公开的操作。SEI 与 wsdl:portType 元素对应。SEI 定义的方法与 wsdl:portType 元素中的 wsdl:operation 元素对应。

注意

JAX-WS 定义了一个注释,允许您指定不作为服务一部分公开的方法。但是,最好的做法是将这些方法从 SEI 离开。

例 24.1 “simple SEI” 显示用于库存更新服务的简单 SEI。

例 24.1. simple SEI

package com.fusesource.demo;

public interface quoteReporter
{
  public Quote getQuote(String ticker);
}

实现接口

由于 SEI 是一个标准 Java 接口,因此实施它的类是标准 Java 类。如果从 Java 类开始,您必须修改才能实施接口。如果使用 SEI 启动,则实施类将实施 SEI。

例 24.2 “简单的实施类” 显示在 例 24.1 “simple SEI” 中实施接口的类。

例 24.2. 简单的实施类

package com.fusesource.demo;

import java.util.*;

public class stockQuoteReporter implements quoteReporter
{
  ...
public Quote getQuote(String ticker)
  {
    Quote retVal = new Quote();
    retVal.setID(ticker);
    retVal.setVal(Board.check(ticker));[1]
    Date retDate = new Date();
    retVal.setTime(retDate.toString());
    return(retVal);
  }
}


[1] Board is an assumed class whose implementation is left to the reader.

24.3. 为代码添加注解

24.3.1. JAX-WS Annotations 概述

JAX-WS 注释指定用于将 SEI 映射到完全指定的服务定义的元数据。注解中提供的信息包括:

  • 服务的目标命名空间。
  • 用于保存请求消息的类名称
  • 用于保存响应消息的类名称
  • 如果某个操作是单向操作
  • 服务使用的绑定风格
  • 用于任何自定义例外的类名称
  • 服务使用的命名空间
注意

大多数注解都有可识别的默认值,不需要为其提供值。但是,您在注解中提供的更多信息,会指定更好的服务定义。精心指定的服务定义会增加分布式应用程序的所有部分将一起工作的可能性。

24.3.2. 必需的注解

概述

要从 Java 代码创建服务,您只需要向代码添加一个注解。您必须在 SEI 和实施类中添加 @WebService 注释。

@WebService 注解

@WebService 注释由 javax.jws.WebService 接口定义,它被放在接口或要用作服务的类中。@webService 具有中描述的属性 表 24.1 “@webService 属性”

表 24.1. @webService 属性

属性描述

name

指定服务接口的名称。此属性映射到 wsdl:portType 元素的 name 属性,该元素在 WSDL 合同中定义服务的接口。默认为在实施类的名称中添加 PortType[a]

targetNamespace

指定定义该服务的目标命名空间。如果没有指定此属性,则目标命名空间派生自软件包名称。

serviceName

指定已发布的服务的名称。此属性映射到定义所发布服务的 wsdl:service 元素的 name 属性。默认值是使用服务的实施类的名称。

wsdlLocation

指定存储服务的 WSDL 合同的 URL。这必须使用一个相对 URL 指定。默认为部署该服务的 URL。

endpointInterface

指定实施类实施的 SEI 的完整名称。仅在服务实施类中使用 属性时指定此属性。

portName

指定发布该服务的端点的名称。此属性映射到 wsdl:port 元素的 name 属性,用于指定公布的服务的端点详情。默认为在服务的实现类中添加 Port

[a] 从 SEI 生成 WSDL 时,会使用接口名称来代替实施类名称。
注意

不需要为任何 @WebService 注释的属性提供值。但是,建议您提供尽可能多的信息。

为 SEI 标注

SEI 要求您添加 @WebService 注释。由于 SEI 是定义服务的合同,所以您应该在 @WebService 注释的属性中指定服务尽可能多的详细信息。

例 24.3 “带有 @WebService 注解的接口” 显示 例 24.1 “simple SEI” 中带有 @WebService 注释的接口。

例 24.3. 带有 @WebService 注解的接口

package com.fusesource.demo;

import javax.jws.*;

@WebService(name="quoteUpdater",
            targetNamespace="http://demos.redhat.com",
	        serviceName="updateQuoteService",
            wsdlLocation="http://demos.redhat.com/quoteExampleService?wsdl",
            portName="updateQuotePort")
public interface quoteReporter
{
  public Quote getQuote(String ticker);
}

例 24.3 “带有 @WebService 注解的接口” 中的 @WebService 注释执行以下操作:

指定定义服务接口的 wsdl:portType 元素的 name 属性的值是 quoteUpdater

指定服务的目标命名空间是 http://demos.redhat.com

指定定义所发布服务的 wsdl:service 元素的值为 updateQuoteService

指定该服务将在 http://demos.redhat.com/quoteExampleService?wsdl 发布其 WSDL 合同。

指定定义公开该服务的 端点的 name 属性的值是 updateQuotePort

为服务实施添加注解

除了使用 @WebService 注释标注 SEI 外,还必须为服务实施类添加 @WebService 注释。当在服务实施类中添加注解时,您只需要指定 endpointInterface 属性。如 例 24.4 “注解的服务实现类” 所示,属性必须设置为 SEI 的全名。

例 24.4. 注解的服务实现类

package org.eric.demo;

import javax.jws.*;

@WebService(endpointInterface="com.fusesource.demo.quoteReporter")
public class stockQuoteReporter implements quoteReporter
{
public Quote getQuote(String ticker)
  {
  ...
  }
}

24.3.3. 可选注解

摘要

虽然 @WebService 注释足以启用 Java 接口或 Java 类,但它不完全描述服务将如何作为服务提供商公开。JAX-WS 编程模型使用许多可选注释来添加有关服务的详细信息,如其使用的绑定到 Java 代码。您可以将这些注解添加到服务的 SEI 中。

您在 SEI 中提供的更多详情是开发人员实施可使用它所定义的功能的应用程序。它还使 WSDL 文档更具体由工具生成。

概述

使用 Annotations 定义绑定属性

如果您正在为您的服务使用 SOAP 绑定,您可以使用 JAX-WS 注解来指定多个绑定属性。这些属性直接与您在服务的 WSDL 合同中指定的属性对应。某些设置(如参数风格)可以限制如何实施方法。这些设置也可以影响在注解方法参数时使用哪些注解。

@SOAPBinding 注解

@SOAPBinding 注解由 javax.jws.SOAp.SOAPBinding 接口定义。它提供有关服务在部署时使用的 SOAP 绑定的详细信息。如果没有指定 @SOAPBinding 注解,则会使用嵌套的 doc/literal SOAP 绑定来发布服务。

您可以将 @SOAPBinding 注释放在 SEI 上,以及任何 SEI 的方法。在方法中使用时,将方法的 @SOAPBinding 注释设置具有优先权。

表 24.2 “@SOAPBinding 属性” 显示 @SOAPBinding 注释的属性。

表 24.2. @SOAPBinding 属性

属性描述

样式

样式.DOCUMENT(默认)

样式.RPC

指定 SOAP 消息的样式。如果指定了 RPC 样式,则 SOAP 正文中的每个消息部分都是参数或返回值,并出现在 soap:body 元素中的 wrapper 元素中。wrapper 元素中的消息部分对应于操作参数,且必须与操作中的参数的顺序相同。如果指定了 DOCUMENT 风格,则 SOAP 正文的内容必须是有效的 XML 文档,但其表单并没有严格限制。

使用

使用.LITERAL(默认)

use.ENCODED[a]

指定传输 SOAP 消息的数据。

parameterStyle [b]

ParameterStyle.BARE

ParameterStyle.WRAPPED(默认)

指定与 WSDL 合同中的消息部分对应的方法参数如何放入 SOAP 消息正文。如果指定了 BARE,则会将每个参数放在邮件正文中,作为消息根的子元素。如果指定了 WRAPPED,则所有输入参数都嵌套到请求消息上的单个元素中,所有输出参数都会嵌套到响应消息中的单个元素中。

[a] 目前不支持 use.ENCODED。
[b] 如果将 风格 设置为 RPC,则必须使用 WRAPPED 参数样式。

文档裸机风格参数

文档裸机风格是 Java 代码与服务生成的 XML 代码之间最直接映射。使用这种风格时,从操作参数列表中定义的输入和输出参数直接生成 schema 类型。

您需要使用 @SOAPBinding 注释将其样式设置为 Style.DOCUMENT,其 parameterStyle 属性设为 ParameterStyle.BARE 来指定您要使用裸机文档\literal 样式的样式。

要确保在使用裸机参数时操作不会违反使用文档风格的限制,您的操作必须遵循以下条件:

  • 操作不能有多个输入或输入/输出参数。
  • 如果操作具有非 void 的返回类型,它不能具有任何输出或输入/输出参数。
  • 如果操作的返回类型为 void,则不能有多个输出或输入/输出参数。
注意

使用 @WebParam 注释或 @WebResult 注释放入 SOAP 标头中的任何参数都不会根据允许的参数数目进行计数。

文档嵌套参数

文档嵌套风格允许更多 RPC,如 Java 代码和服务的 XML 表示之间的映射。使用这种风格时,方法的 parameter 列表中的参数会被绑定嵌套到单个元素中。这样做的缺点是,它在 Java 实施之间引入了一个额外的间接层,以及如何将消息放置在线路上。

要指定您要使用嵌套文档\literal 样式的 @SOAPBinding 注释,其 样式 属性设置为 Style.DOCUMENT,并将其 parameterStyle 属性设置为 ParameterStyle.WRAPPED。

您可以对使用 “@RequestWrapper 注释”一节 注解和 “@ResponseWrapper 注释”一节 注解生成的打包程序有一些控制。

示例

例 24.5 “使用 SOAP Binding 注解指定文档 Bare SOAP Binding” 显示使用文档裸机 SOAP 消息的 SEI。

例 24.5. 使用 SOAP Binding 注解指定文档 Bare SOAP Binding

package org.eric.demo;

import javax.jws.*;
import javax.jws.soap.*;
import javax.jws.soap.SOAPBinding.*;

@WebService(name="quoteReporter")
@SOAPBinding(parameterStyle=ParameterStyle.BARE)
public interface quoteReporter
{
  ...
}

概述

使用注释定义操作属性

当运行时将 Java 方法定义映射到 XML 操作定义时,它提供详情,例如:

  • 在 XML 中交换的信息类似如下
  • 如果消息可以优化为一条方法消息
  • 定义消息的命名空间

@WebMethod 注释

@WebMethod 注释由 javax.jws.WebMethod 接口定义。它放置在 SEI 中的方法中。@WebMethod 注释提供了通常在 ws:operation 元素中 代表的信息,用于描述与该方法关联的操作。

表 24.3 “@WebMethod 属性” 描述 @WebMethod 注释的属性。

表 24.3. @WebMethod 属性

属性描述

operationName

指定关联的 wsdl:operation 元素 的名称。默认值为方法的名称。

action

指定方法生成的 soap:operation 元素的 soapAction 属性的值。默认值为空字符串。

exclude

指定是否应该将方法排除在服务接口中。默认值为 false。

@RequestWrapper 注释

@RequestWrapper 注释由 javax.xml.ws.RequestWrapper 接口定义。它放置在 SEI 中的方法中。@RequestWrapper 注释指定 Java 类,用于实施请求消息交换方法参数的 wrapperan。它还指定了在处理请求消息时运行时使用的元素名称和命名空间。

表 24.4 “@RequestWrapper Properties” 描述 @RequestWrapper 注释的属性。

表 24.4. @RequestWrapper Properties

属性描述

localName

指定请求消息 XML representation 中的 wrapper 元素的本地名称。默认值可以是方法的名称,也可以是 “@WebMethod 注释”一节 注解的 operationName 属性的值。

targetNamespace

指定定义 XML wrapper 元素的命名空间。默认值为 SEI 的目标命名空间。

className

指定实施 wrapper 元素的 Java 类的完整名称。

注意

只有 className 属性才是必需的。

重要

如果方法也带有 @SOAPBinding 注释,其 parameterStyle 属性设为 ParameterStyle.BARE,则忽略此注解。

@ResponseWrapper 注释

@ResponseWrapper 注释由 javax.xml.ws.ResponseWrapper 接口定义。它放置在 SEI 中的方法中。@ResponseWrapper 指定在消息交换中为方法参数实施打包程序的 Java 类。它还指定在处理响应消息和解包时运行时使用的元素名称和命名空间。

表 24.5 “@ResponseWrapper Properties” 描述 @ResponseWrapper 注释的属性。

表 24.5. @ResponseWrapper Properties

属性描述

localName

指定响应消息 XML representation 中的 wrapper 元素的本地名称。默认值是附加 Response 的方法的名称,或者 “@WebMethod 注释”一节 注解的 operationName 属性的值附加了 Response。

targetNamespace

指定定义 XML 打包程序元素的命名空间。默认值为 SEI 的目标命名空间。

className

指定实施 wrapper 元素的 Java 类的完整名称。

注意

只有 className 属性才是必需的。

重要

如果方法也带有 @SOAPBinding 注释,其 parameterStyle 属性设为 ParameterStyle.BARE,则忽略此注解。

@WebFault 注释

@WebFault 注释由 javax.xml.ws.WebFault 接口定义。它会被置于您的 SEI 引发的异常。@WebFault 注释用于将 Java 异常映射到 wsdl:fault 元素。这些信息用于将例外置于可由服务及其消费者处理的表示中。

表 24.6 “@WebFault Properties” 描述 @WebFault 注释的属性。

表 24.6. @WebFault Properties

属性描述

name

指定 fault 元素的本地名称。

targetNamespace

指定定义 fault 元素的命名空间。默认值为 SEI 的目标命名空间。

faultName

指定实施异常的 Java 类的全名。

重要

name 属性是必需的。

@Oneway 注解

@Oneway 注释由 javax.jws.Oneway 接口定义。它放置在 SEI 中不需要来自该服务的响应的方法。@Oneway 注释告知运行时,它可以通过不等待响应而优化方法执行,而且不会保留任何资源来处理响应。

此注解只能在满足以下条件的方法中使用:

  • 它们返回 void
  • 它们没有实现 Holder 接口的参数
  • 它们不会抛出任何例外,可以传回给消费者

示例

例 24.6 “带有注解的方法 SEI” 显示标有其方法的 SEI。

例 24.6. 带有注解的方法 SEI

package com.fusesource.demo;

import javax.jws.*;
import javax.xml.ws.*;

@WebService(name="quoteReporter")
public interface quoteReporter
{
  @WebMethod(operationName="getStockQuote")
  @RequestWrapper(targetNamespace="http://demo.redhat.com/types",
                  className="java.lang.String")
  @ResponseWrapper(targetNamespace="http://demo.redhat.com/types",
                   className="org.eric.demo.Quote")
  public Quote getQuote(String ticker);
}

概述

使用 Annotations 定义参数属性

SEI 中的方法参数对应于 wsdl:message 元素及其 wsdl:part 元素。JAX-WS 提供注解,供您描述为方法参数生成的 wsdl:part 元素。

@WebParam 注释

@WebParam 注释由 javax.jws.WebParam 接口定义。它放置在 SEI 中定义的方法的参数中。如果参数将被放入 SOAP 标头,则 @WebParam 注释可以指定参数方向,以及生成的 wsdl:part 的其他属性。

表 24.7 “@WebParam 属性” 描述 @WebParam 注释的属性。

表 24.7. @WebParam 属性

属性描述

name

 

指定参数的名称,因为它出现在生成的 WSDL 文档中。对于 RPC 绑定,这是代表 参数的 wsdl:part 的名称。对于文档绑定,这是代表 参数的 XML 元素的本地名称。根据 JAX-WS 规范,默认值为 arg N ,其中 N 替换为基于零的参数索引(如 arg0、arg0 等)。

targetNamespace

 

指定参数的命名空间。它只适用于参数映射到 XML 元素的文档绑定。默认值是使用服务的命名空间。

模式

mode.IN(默认)[a]

mode.OUT

Mode.INOUT

指定参数方向。

header

false(默认)

true

指定参数是否作为 SOAP 标头的一部分传递。

partName

 

指定 参数的 wsdl:part 元素的 name 属性的值。此属性用于文档风格的 SOAP 绑定。

[a] 任何实现 Holder 接口的参数默认映射到 Mode.INOUT。

@WebResult 注解

@WebResult 注释由 javax.jws.WebResult 接口定义。它放置在 SEI 中定义的方法中。@WebResult 注释允许您指定为方法返回值生成的 wsdl:part 的属性。

表 24.8 “@WebResult Properties” 描述 @WebResult 注释的属性。

表 24.8. @WebResult Properties

属性描述

name

指定返回值的名称,因为它出现在生成的 WSDL 文档中。对于 RPC 绑定,这是代表返回值的 wsdl:part 的名称。对于文档绑定,这是代表返回值的 XML 元素的本地名称。默认值为 return。

targetNamespace

指定返回值的命名空间。它仅用于记录绑定,其中返回值映射到 XML 元素。默认值是使用服务的命名空间。

header

指定返回值是否作为 SOAP 标头的一部分传递。

partName

指定返回值的 wsdl:part 元素的 name 属性的值。此属性用于文档风格的 SOAP 绑定。

示例

例 24.7 “完全注解的 SEI” 显示已完全注解的 SEI。

例 24.7. 完全注解的 SEI

package com.fusesource.demo;

import javax.jws.*;
import javax.xml.ws.*;
import javax.jws.soap.*;
import javax.jws.soap.SOAPBinding.*;
import javax.jws.WebParam.*;

@WebService(targetNamespace="http://demo.redhat.com",
            name="quoteReporter")
@SOAPBinding(style=Style.RPC, use=Use.LITERAL)
public interface quoteReporter
{
  @WebMethod(operationName="getStockQuote")
  @RequestWrapper(targetNamespace="http://demo.redhat.com/types",
                  className="java.lang.String")
  @ResponseWrapper(targetNamespace="http://demo.redhat.com/types",
                   className="org.eric.demo.Quote")
  @WebResult(targetNamespace="http://demo.redhat.com/types",
             name="updatedQuote")
  public Quote getQuote(
                        @WebParam(targetNamespace="http://demo.redhat.com/types",
                                  name="stockTicker",
                                  mode=Mode.IN)
                        String ticker
  );
}

24.3.4. Apache CXF Annotations

24.3.4.1. WSDL 文档

@WSDL 文档注释

@WSDL 文档 注释由 org.apache.cxf.annotations.WSDL 文档接口定义。它可以放在 SEI 或 SEI 方法上。

此注解可让您添加文档,然后在 SEI 转换为 WSDL 后在 wsdl:documentation 元素内显示。默认情况下,文档元素显示在端口类型中,但您可以指定放置属性,使文档显示在 WSDL 文件的其他位置。第 24.3.4.2 节 “@WSDL 文档属性” 显示 @WSDL 文档注释支持的属性

24.3.4.2. @WSDL 文档属性

属性描述

value

(必需) 包含文档文本的字符串。

placement

(可选) 指定在 WSDL 文件中显示此文档的位置。有关可能的放置值列表,请参阅 “在 WSDL 合同中放置”一节

faultClass

(可选) 如果放置设置为 FAULT_MESSAGEPORT_TYPE_OPERATION_FAULTBINDING_OPERATION_FAULT,则必须将此属性设置为代表该故障的 Java 类。

@WSDLDocumentationCollection 注解

@WSDLDocumentationCollection 注释由 org.apache.cxf.annotations.WSDLDocumentationCollection 接口定义。它可以放在 SEI 或 SEI 方法上。

此注解用于在单一位置或不同的位置插入多个文档元素。

在 WSDL 合同中放置

要指定在 WSDL 合同中应当出现文档的位置,您可以指定 放置 属性,类型为 WSDLDocumentation.Placement。放置可以具有以下值之一:

  • WSDLDocumentation.Placement.BINDING
  • WSDLDocumentation.Placement.BINDING_OPERATION
  • WSDLDocumentation.Placement.BINDING_OPERATION_FAULT
  • WSDLDocumentation.Placement.BINDING_OPERATION_INPUT
  • WSDLDocumentation.Placement.BINDING_OPERATION_OUTPUT
  • WSDLDocumentation.Placement.DEFAULT
  • WSDLDocumentation.Placement.FAULT_MESSAGE
  • WSDLDocumentation.Placement.INPUT_MESSAGE
  • WSDLDocumentation.Placement.OUTPUT_MESSAGE
  • WSDLDocumentation.Placement.PORT_TYPE
  • WSDLDocumentation.Placement.PORT_TYPE_OPERATION
  • WSDLDocumentation.Placement.PORT_TYPE_OPERATION_FAULT
  • WSDLDocumentation.Placement.PORT_TYPE_OPERATION_INPUT
  • WSDLDocumentation.Placement.PORT_TYPE_OPERATION_OUTPUT
  • WSDLDocumentation.Placement.SERVICE
  • WSDLDocumentation.Placement.SERVICE_PORT
  • WSDLDocumentation.Placement.TOP
@WSDL 文档示例

第 24.3.4.3 节 “使用 @WSDL 文档” 展示如何将 @WSDL 文档 注释添加到 SEI 和其方法之一。

24.3.4.3. 使用 @WSDL 文档

@WebService
@WSDLDocumentation("A very simple example of an SEI")
public interface HelloWorld {
    @WSDLDocumentation("A traditional form of greeting")
    String sayHi(@WebParam(name = "text") String text);
}

第 24.3.4.4 节 “使用文档生成的 WSDL” 中显示的 WSDL(在 第 24.3.4.3 节 “使用 @WSDL 文档” 中)生成时,文档 元素的默认位置分别是 PORT_TYPEPORT_TYPE_OPERATION

24.3.4.4. 使用文档生成的 WSDL

<wsdl:definitions ... >
  ...
  <wsdl:portType name="HelloWorld">
    <wsdl:documentation>A very simple example of an SEI</wsdl:documentation>
    <wsdl:operation name="sayHi">
      <wsdl:documentation>A traditional form of greeting</wsdl:documentation>
      <wsdl:input name="sayHi" message="tns:sayHi">
    </wsdl:input>
      <wsdl:output name="sayHiResponse" message="tns:sayHiResponse">
    </wsdl:output>
    </wsdl:operation>
  </wsdl:portType>
  ...
</wsdl:definitions>
@WSDL 文档Collection 的示例

第 24.3.4.5 节 “使用 @WSDL 文档Collection” 展示如何将 @WSDLDocumentationCollection 注释添加到 SEI。

24.3.4.5. 使用 @WSDL 文档Collection

@WebService
@WSDLDocumentationCollection(
    {
        @WSDLDocumentation("A very simple example of an SEI"),
        @WSDLDocumentation(value = "My top level documentation",
                           placement = WSDLDocumentation.Placement.TOP),
        @WSDLDocumentation(value = "Binding documentation",
                           placement = WSDLDocumentation.Placement.BINDING)
    }
)
public interface HelloWorld {
    @WSDLDocumentation("A traditional form of Geeky greeting")
    String sayHi(@WebParam(name = "text") String text);
}

24.3.4.6. 消息的 schema 验证

@SchemaValidation 注释

@SchemaValidation 注释由 org.apache.cxf.annotations.SchemaValidation 接口定义。它可以放在 SEI 和独立 SEI 方法上。

此注解打开发送到此端点的 XML 消息的 schema 验证。当您怀疑出现传入 XML 消息格式的问题时,这可用于测试目的。默认情况下禁用验证,因为它对性能有显著影响。

模式验证类型

架构验证 behaviour 由 type 参数控制,其值是 org.apache.cxf.annotations.SchemaValidation.SchemaValidationType 类型的枚举。第 24.3.4.7 节 “架构验证类型值” 显示可用验证类型的列表。

24.3.4.7. 架构验证类型值

类型描述

IN

对客户端和服务器上的传入消息应用架构验证。

OUT

将架构验证应用到客户端和服务器上的传出消息。

两者

对客户端和服务器上的传入和传出消息应用架构验证。

NONE

禁用所有 schema 验证。

REQUEST(请求)

将模式验证应用到 Request 消息,从而导致验证应用到传出客户端消息和传入的服务器消息。

RESPONSE

将模式验证应用到响应消息,从而导致验证应用到传入客户端消息和传出服务器消息。

示例

以下示例演示了如何根据 MyService SEI 为端点启用消息的 schema 验证。请注意,注解如何作为一个整体应用到 SEI,以及 SEI 中的个别方法。

@WebService
@SchemaValidation(type = SchemaValidationType.BOTH)
public interface MyService {
    Foo validateBoth(Bar data);

    @SchemaValidation(type = SchemaValidationType.NONE)
    Foo validateNone(Bar data);

    @SchemaValidation(type = SchemaValidationType.IN)
    Foo validateIn(Bar data);

    @SchemaValidation(type = SchemaValidationType.OUT)
    Foo validateOut(Bar data);

    @SchemaValidation(type = SchemaValidationType.REQUEST)
    Foo validateRequest(Bar data);

    @SchemaValidation(type = SchemaValidationType.RESPONSE)
    Foo validateResponse(Bar data);
}

24.3.4.8. 指定数据绑定

@DataBinding 注解

@DataBinding 注解由 org.apache.cxf.annotations.DataBinding 接口定义。它放置在 SEI 上。

此注释用于将数据绑定与 SEI 关联,以替换默认的 JAXB 数据块。@DataBinding 注解的值必须是提供数据绑定 ClassName.class 的类。

支持的数据绑定

Apache CXF 目前支持以下数据绑定:

  • org.apache.cxf.jaxb.JAXBDataBinding

    (默认) 标准 JAXB 数据绑定。

  • org.apache.cxf.sdo.SDODataBinding

    Service Data Objects(SDO)数据绑定基于 Apache Tuscany SDO 实现。如果要在 Maven 构建上下文中使用此数据绑定,则需要在 cxf-rt-databinding-sdo 工件中添加依赖项。

  • org.apache.cxf.aegis.databinding.AegisDatabinding

    如果要在 Maven 构建上下文中使用此数据绑定,则需要在 cxf-rt-databinding-aegis 工件中添加依赖项。

  • org.apache.cxf.xmlbeans.XmlBeansDataBinding

    如果要在 Maven 构建上下文中使用此数据绑定,则需要在 cxf-rt-databinding-xmlbeans 工件中添加依赖项。

  • org.apache.cxf.databinding.source.SourceDataBinding

    这个数据绑定属于 Apache CXF 内核。

  • org.apache.cxf.databinding.stax.StaxDataBinding

    这个数据绑定属于 Apache CXF 内核。

示例

第 24.3.4.9 节 “设置数据绑定” 展示如何将 SDO 绑定与 HelloWorld SEI 关联

24.3.4.9. 设置数据绑定

@WebService
@DataBinding(org.apache.cxf.sdo.SDODataBinding.class)
public interface HelloWorld {
    String sayHi(@WebParam(name = "text") String text);
}

24.3.4.10. 压缩信息

@GZIP 注解

@GZIP 注释由 org.apache.cxf.annotations.GZIP 接口定义。它放置在 SEI 上。

启用 GZIP 压缩信息。GZIP 是一个协商的增强。也就是说,客户端的初始请求将不会被 gzip 压缩,但会添加 Accept 标头;如果服务器支持 GZIP 压缩,其响应将被 gzip 压缩,任何后续请求也会被压缩。

第 24.3.4.11 节 “@GZIP Properties” 显示 @GZIP 注释支持的可选属性。

24.3.4.11. @GZIP Properties

属性描述

threshold

超过此属性指定大小的消息 不会被 gzip 压缩。默认为 -1(无限制)。

@FastInfoset

@FastInfoset 注释由 org.apache.cxf.annotations.FastInfoset 接口定义。它放置在 SEI 上。

为该消息启用 FastInfoset 格式。fastinfoset 是 XML 的二进制编码格式,旨在优化消息大小和 XML 消息处理性能。如需了解更多详细信息,请参阅 Fast Infoset 中的以下 Sun 文章。

fastinfoset 是一个协商的增强。也就是说,来自客户端的初始请求不会采用 FastInfoset 格式,但会添加 Accept 标头。如果服务器支持 FastInfoset,响应将位于 FastInfoset 中,任何后续请求也会被添加。

第 24.3.4.12 节 “@fastinfoset Properties” 显示 @FastInfoset 注释支持的可选属性。

24.3.4.12. @fastinfoset Properties

属性描述

force

强制使用 FastInfoset 格式的布尔值属性,而不是协商。当为 true 时,强制使用 FastInfoset 格式,否则协商。默认为 false

@GZIP 示例

第 24.3.4.13 节 “启用 GZIP” 显示如何为 HelloWorld SEI 启用 GZIP 压缩。

24.3.4.13. 启用 GZIP

@WebService
@GZIP
public interface HelloWorld {
    String sayHi(@WebParam(name = "text") String text);
}
@FastInfoset 的考试

第 24.3.4.14 节 “启用 FastInfoset” 显示如何为 HelloWorld SEI 启用 FastInfoset 格式。

24.3.4.14. 启用 FastInfoset

@WebService
@FastInfoset
public interface HelloWorld {
    String sayHi(@WebParam(name = "text") String text);
}

24.3.4.15. 在端点上启用日志记录

@logging 注解

@Logging 注释由 org.apache.cxf.annotations.Logging 接口定义。它放置在 SEI 上。

此注解为与 SEI 关联的所有端点启用日志记录。第 24.3.4.16 节 “@logging 属性” 显示此注解中可以设置的可选属性。

24.3.4.16. @logging 属性

属性描述

limit

指定在日志中截断信息的大小限制。默认为 64K。

inLocation

指定记录传入信息的位置。可以是 < stderr>、& lt;stdout& gt;、<logger > 或文件名。默认为 &lt ;logger>

outLocation

指定记录传出消息的位置。可以是 < stderr>、& lt;stdout& gt;、<logger > 或文件名。默认为 &lt ;logger>

示例

第 24.3.4.17 节 “使用注解进行日志配置” 演示了如何为 HelloWorld SEI 启用日志记录,其中传入消息发送到 < stdout> 和传出消息到 < logger>

24.3.4.17. 使用注解进行日志配置

@WebService
@Logging(limit=16000, inLocation="<stdout>")
public interface HelloWorld {
    String sayHi(@WebParam(name = "text") String text);
}

24.3.4.18. 在端点中添加属性和策略

摘要

属性和策略都可用于将配置数据与端点关联。它们之间的基本区别在于属性是 Apache CXF 特定的配置机制,而 策略 则是标准的 WSDL 配置机制。策略通常来自 WS 规格和标准,它们通常通过定义 W dl:policy 元素(在 WSDL 合同中出现)来设置。相反,属性是特定于 Apache CXF 的,它们通常通过在 Apache CXF Spring 配置文件中定义 jaxws:properties 元素进行设置。

不过,也可以使用注释在 Java 中定义属性设置和 WSDL 策略设置,如下所述。

24.3.4.19. 添加属性

@EndpointProperty 注释

@EndpointProperty 注释由 org.apache.cxf.annotations.EndpointProperty 接口定义。它放置在 SEI 上。

此注解为端点添加特定于 Apache CXF 的配置设置。endpoint 属性也可以在 Spring 配置文件中指定。例如,若要在端点上配置 WS-Security,您可以使用 Spring 配置文件中的 jaxws:properties 元素添加端点属性,如下所示:

<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:jaxws="http://cxf.apache.org/jaxws"
   ... >

   <jaxws:endpoint
      id="MyService"
      address="https://localhost:9001/MyService"
      serviceName="interop:MyService"
      endpointName="interop:MyServiceEndpoint"
      implementor="com.foo.MyService">

      <jaxws:properties>
         <entry key="ws-security.callback-handler" value="interop.client.UTPasswordCallback"/>
         <entry key="ws-security.signature.properties" value="etc/keystore.properties"/>
         <entry key="ws-security.encryption.properties" value="etc/truststore.properties"/>
         <entry key="ws-security.encryption.username" value="useReqSigCert"/>
      </jaxws:properties>

   </jaxws:endpoint>
</beans>

另外,您可以通过在 SEI 中添加 @EndpointProperty 注解来指定 Java 中的上述配置设置,如 第 24.3.4.20 节 “使用 @EndpointProperty Annotations 配置 WS-Security” 所示。

24.3.4.20. 使用 @EndpointProperty Annotations 配置 WS-Security

@WebService
@EndpointProperty(name="ws-security.callback-handler" value="interop.client.UTPasswordCallback")
@EndpointProperty(name="ws-security.signature.properties" value="etc/keystore.properties")
@EndpointProperty(name="ws-security.encryption.properties" value="etc/truststore.properties")
@EndpointProperty(name="ws-security.encryption.username" value="useReqSigCert")
public interface HelloWorld {
    String sayHi(@WebParam(name = "text") String text);
}
@EndpointProperties annotation

@EndpointProperties 注释由 org.apache.cxf.annotations.EndpointProperties 接口定义。它放置在 SEI 上。

此注释提供了一种将多个 @EndpointProperty 注释分组到列表中的方法。使用 @EndpointProperties 时,可以重新编写 第 24.3.4.20 节 “使用 @EndpointProperty Annotations 配置 WS-Security”,如 第 24.3.4.21 节 “使用 @EndpointProperties 注解配置 WS-Security” 所示。

24.3.4.21. 使用 @EndpointProperties 注解配置 WS-Security

@WebService
@EndpointProperties(
  {
  @EndpointProperty(name="ws-security.callback-handler" value="interop.client.UTPasswordCallback"),
  @EndpointProperty(name="ws-security.signature.properties" value="etc/keystore.properties"),
  @EndpointProperty(name="ws-security.encryption.properties" value="etc/truststore.properties"),
  @EndpointProperty(name="ws-security.encryption.username" value="useReqSigCert")
})
public interface HelloWorld {
    String sayHi(@WebParam(name = "text") String text);
}

24.3.4.22. 添加策略

@policy 注释

@Policy 注释由 org.apache.cxf.annotations.Policy 接口定义。它可以放在 SEI 或 SEI 方法上。

此注释用于将 WSDL 策略与 SEI 或 SEI 方法关联。该策略通过提供 URI 来引用包含标准 wsdl:policy 元素的 XML 文件。如果从 SEI 生成 WSDL 合同(例如,使用 java2ws 命令行工具),您可以指定是否要将这个策略包含在 WSDL 中。

第 24.3.4.23 节 “@policy 属性” 显示 @Policy 注释支持的属性。

24.3.4.23. @policy 属性

属性描述

uri

(必需) 文件的位置,包含策略定义。

includeInWSDL

(可选) 在生成 WSDL 时,是否将策略包含在生成的合同中。默认为 true

placement

(可选) 指定在 WSDL 文件中显示此文档的位置。有关可能的放置值列表,请参阅 “在 WSDL 合同中放置”一节

faultClass

(可选) 如果放置设置为 BINDING_OPERATION_FAULTPORT_TYPE_OPERATION_FAULT,则必须设置此属性来指定这个策略应用到哪个故障。该值是代表故障的 Java 类。

@policies 注释

@Policies 注释由 org.apache.cxf.annotations.Policies 接口定义。它可以放在 SEI 或thse SEI 方法上。

此注释提供了一种将多个 @Policy 注释分组到列表中的方法。

在 WSDL 合同中放置

要指定在 WSDL 合同中应出现策略的位置,您可以指定 放置 属性,即 Policy.Placement 类型。放置可以具有以下值之一:

Policy.Placement.BINDING
Policy.Placement.BINDING_OPERATION
Policy.Placement.BINDING_OPERATION_FAULT
Policy.Placement.BINDING_OPERATION_INPUT
Policy.Placement.BINDING_OPERATION_OUTPUT
Policy.Placement.DEFAULT
Policy.Placement.PORT_TYPE
Policy.Placement.PORT_TYPE_OPERATION
Policy.Placement.PORT_TYPE_OPERATION_FAULT
Policy.Placement.PORT_TYPE_OPERATION_INPUT
Policy.Placement.PORT_TYPE_OPERATION_OUTPUT
Policy.Placement.SERVICE
Policy.Placement.SERVICE_PORT
@Policy 示例

以下示例演示了如何将 WSDL 策略与 HelloWorld SEI 关联,以及如何将策略与 sayHi 方法关联。策略本身存储在文件系统中的 XML 文件中,该文件在 注解policies 目录下。

@WebService
@Policy(uri = "annotationpolicies/TestImplPolicy.xml",
        placement = Policy.Placement.SERVICE_PORT),
@Policy(uri = "annotationpolicies/TestPortTypePolicy.xml",
        placement = Policy.Placement.PORT_TYPE)
public interface HelloWorld {
    @Policy(uri = "annotationpolicies/TestOperationPTPolicy.xml",
            placement = Policy.Placement.PORT_TYPE_OPERATION),
    String sayHi(@WebParam(name = "text") String text);
}
@Policies 示例

您可以使用 @Policies 注释将多个 @Policy 注释分组到列表中,如下例所示:

@WebService
@Policies({
    @Policy(uri = "annotationpolicies/TestImplPolicy.xml",
            placement = Policy.Placement.SERVICE_PORT),
    @Policy(uri = "annotationpolicies/TestPortTypePolicy.xml",
            placement = Policy.Placement.PORT_TYPE)
})
public interface HelloWorld {
    @Policy(uri = "annotationpolicies/TestOperationPTPolicy.xml",
            placement = Policy.Placement.PORT_TYPE_OPERATION),
    String sayHi(@WebParam(name = "text") String text);
}

24.4. 生成 WSDL

使用 Maven

注解您的代码后,您可以使用 java2ws Maven 插件的 -wsdl 选项为您的服务生成 WSDL 合同。有关 java2ws Maven 插件的选项列表,请参阅 第 44.3 节 “java2ws”

例 24.8 “从 Java 生成 WSDL” 显示如何设置 java2ws Maven 插件来生成 WSDL。

例 24.8. 从 Java 生成 WSDL

<plugin>
  <groupId>org.apache.cxf</groupId>
  <artifactId>cxf-java2ws-plugin</artifactId>
  <version>${cxf.version}</version>
  <executions>
    <execution>
      <id>process-classes</id>
      <phase>process-classes</phase>
      <configuration>
        <className>className</className>
        <genWsdl>true</genWsdl>
      </configuration>
      <goals>
        <goal>java2ws</goal>
      </goals>
    </execution>
  </executions>
</plugin>
注意

将 className 的值替换为 qualified className。

示例

例 24.9 “从 SEI生成 WSDL” 显示在 例 24.7 “完全注解的 SEI” 中为 SEI 生成的 WSDL 合同。

例 24.9. 从 SEI生成 WSDL

<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions targetNamespace="http://demo.eric.org/"
          xmlns:tns="http://demo.eric.org/"
		  xmlns:ns1=""
		  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
		  xmlns:ns2="http://demo.eric.org/types"
		  xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
		  xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
  <wsdl:types>
    <xsd:schema>
      <xs:complexType name="quote">
        <xs:sequence>
          <xs:element name="ID" type="xs:string" minOccurs="0"/>
          <xs:element name="time" type="xs:string" minOccurs="0"/>
          <xs:element name="val" type="xs:float"/>
        </xs:sequence>
      </xs:complexType>
    </xsd:schema>
  </wsdl:types>
  <wsdl:message name="getStockQuote">
    <wsdl:part name="stockTicker" type="xsd:string">
    </wsdl:part>
  </wsdl:message>
  <wsdl:message name="getStockQuoteResponse">
    <wsdl:part name="updatedQuote" type="tns:quote">
    </wsdl:part>
  </wsdl:message>
  <wsdl:portType name="quoteReporter">
    <wsdl:operation name="getStockQuote">
      <wsdl:input name="getQuote" message="tns:getStockQuote">
    </wsdl:input>
      <wsdl:output name="getQuoteResponse" message="tns:getStockQuoteResponse">
    </wsdl:output>
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="quoteReporterBinding" type="tns:quoteReporter">
    <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />
    <wsdl:operation name="getStockQuote">
      <soap:operation style="rpc" />
      <wsdl:input name="getQuote">
        <soap:body use="literal" />
      </wsdl:input>
      <wsdl:output name="getQuoteResponse">
        <soap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="quoteReporterService">
    <wsdl:port name="quoteReporterPort" binding="tns:quoteReporterBinding">
      <soap:address location="http://localhost:9000/quoteReporterService" />
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

第 25 章 在没有 WSDL 合同的情况下开发消费者

摘要

您不需要 WSDL 合同来开发服务消费者。您可以从标注的 SEI 创建服务消费者。除了 SEI,您需要知道公开该服务的端点的地址,定义公开该服务的 service 元素的 QName,以及定义消费者发出请求的端点的 QName。此信息可以在 SEI 的注解中指定或单独提供。

25.1. Java-First Consumer Development

要创建没有 WSDL 合同的消费者,您必须执行以下操作:

25.2. 创建服务对象

概述

javax.xml.ws.Service 类代表 wsdl:service 元素,其中包含公开服务的所有端点的定义。因此,它提供可让您获得由 wsdl:port 元素定义的端点的方法,这些元素是用于在服务上执行远程调用的代理。

注意

Service 类提供抽象概念,允许客户端代码使用 Java 类型而不是使用 XML 文档。

create()方法

Service 类有两个静态 create() 方法,可用于创建新的 Service 对象。如 例 25.1 “service create() 方法” 所示,create() 方法采用 wsdl:service 元素的 QName 来代表 Service 对象,另一个则使用指定 WSDL 合同位置的 URI。

注意

所有服务发布他们的 WSDL 合同。对于 SOAP/HTTP 服务,URI 通常是附加了 ?wsdl 的服务的 URI。

例 25.1. service create() 方法

公共静态服务创建URLwsdlLocationQNameserviceNameWebServiceExceptionpublic 静态服务创建QNameserviceNameWebServiceException

serviceName 参数的值是一个 QName。其 namespace 部分的值是该服务的目标命名空间。该服务的目标命名空间在 @WebService 注释的 targetNamespace 属性中指定。QName 的本地部分的值是 wsdl:service 元素的 name 属性的值。您可以使用以下方法之一确定这个值: .它在 @WebService 注释的 serviceName 属性中指定。

  1. Service 附加到 @WebService 注释的 name 属性的值。
  2. Service 附加到 SEI 的名称。
重要

在 OSGi 环境中部署的 CXF 消费者需要特殊处理,以避免发生类 NotFoundException的可能性。对于包含编程创建的 CXF 消费者的每个捆绑包,您需要创建一个单例 CXF 默认总线,并确保所有捆绑包的 CXF 使用者都使用它。如果没有这种保护机制,可以为一个捆绑包分配在另一个捆绑包中创建的 CXF 默认总线,这可能会导致继承捆绑包失败。

例如,假设捆绑包 A 没有明确设置 CXF 默认总线,并且被分配了捆绑包 B 中创建的 CXF 默认总线。如果捆绑包 A 中的 CXF 总线需要配置额外功能(如 SSL 或 WS-Security),或者需要从捆绑包 A 中加载特定类或资源,则会失败。这是因为 CXF 总线实例将线程上下文类加载程序设置为创建它的捆绑包的类加载程序(本例中为 B)。此外,某些框架,比如 ws4j(在 CXF 中实施 WS-Security)使用 TCCL 从捆绑包内部加载资源,如 calback 处理程序类或其他属性文件。因为分配了捆绑包 B 的默认 CXF 总线及其 TCCL,因此 ws4j 层无法从捆绑包 A 加载所需资源,从而导致 ClassNotFoundException 错误。

要创建单例 CXF 默认总线,请将此代码插入到创建服务对象 的主 方法的开头,如 “示例”一节 所示:

BusFactory.setThreadDefaultBus(BusFactory.newInstance().createBus());

示例

例 25.2 “创建服务 对象” 显示为 例 24.7 “完全注解的 SEI” 中显示的 SEI 创建 Service 对象的代码。

例 25.2. 创建服务 对象

package com.fusesource.demo;

import javax.xml.namespace.QName;
import javax.xml.ws.Service;

public class Client
{
public static void main(String args[])
  {
    BusFactory.setThreadDefaultBus(BusFactory.newInstance().createBus());
    QName serviceName = new QName("http://demo.redhat.com", "stockQuoteReporter");
    Service s = Service.create(serviceName);
   ...
  }
}

例 25.2 “创建服务 对象” 中的代码执行以下操作:

创建一个单例 CXF 默认总线,供服务的所有 CXF 使用者使用。

使用 targetNamespace 属性和 @WebService 注解的 name 属性,为服务构建 QName。

调用单一参数 create() 方法以创建新的 Service 对象。

注意

使用单一参数 create() 可让您获得访问 WSDL 合同的任何依赖项。

25.3. 将端口添加到服务

概述

服务的端点信息在 wsdl:port 元素中定义,Service 对象会为 WSDL 合同中定义的每个端点创建一个代理实例。如果您在创建 Service 对象时不指定 WSDL 合同, Service 对象没有获取有关实施您的服务的端点的信息,因此无法创建任何代理实例。在这种情况下,您必须为 Service 对象提供使用 addPort() 方法代表 wsdl:port 元素所需的信息。

addPort()方法

Service 类定义了一个 addPort() 方法(在 例 25.3 “addPort() 方法” 中显示),在消费者实施中没有可用于 WSDL 合同的情况下使用。addPort() 方法允许您为 Service 对象提供信息,后者通常存储在 wsdl:port 元素中,以便为服务实施创建代理。

例 25.3. addPort() 方法

addPortQNameportNameStringbindingIdStringendpointAddressWebServiceException

portName 的值是一个 QName。其 namespace 部分的值是该服务的目标命名空间。该服务的目标命名空间在 @WebService 注释的 targetNamespace 属性中指定。QName 的本地部分的值是 wsdl:port 元素的 name 属性的值。您可以使用以下方法之一确定这个值:

  1. @WebService 注释的 portName 属性中指定它。
  2. Port 附加到 @WebService 注释的 name 属性的值。
  3. Port 附加到 SEI 的名称。

bindingId 参数的值是一个字符串,它唯一标识端点使用的绑定类型。对于使用标准 SOAP 命名空间的 SOAP 绑定: http://schemas.xmlsoap.org/soap/。如果端点没有使用 SOAP 绑定,则 bindingId 参数的值由绑定开发人员决定。 endpointAddress 参数的值是发布端点的地址。对于 SOAP/HTTP 端点,地址是一个 HTTP 地址。HTTP 以外的传输使用不同的地址方案。

示例

例 25.4 “将端口添加到 服务对象 显示在 例 25.2 “创建服务 对象” 中创建的服务 对象中 添加端口的代码。

例 25.4. 将端口添加到 服务对象

package com.fusesource.demo;

import javax.xml.namespace.QName;
import javax.xml.ws.Service;

public class Client
{
public static void main(String args[])
  {
    ...
    QName portName = new QName("http://demo.redhat.com", "stockQuoteReporterPort");
    s.addPort(portName,
              "http://schemas.xmlsoap.org/soap/",
              "http://localhost:9000/StockQuote");
    ...
  }
}

例 25.4 “将端口添加到 服务对象 中的代码执行以下操作:

portName 参数创建 QName。

调用 addPort() 方法。

指定端点使用 SOAP 绑定。

指定发布端点的地址。

25.4. 获取端点的代理

概述

服务代理是一个对象,提供由远程服务公开的所有方法,并处理进行远程调用所需的所有详情。Service 对象为通过 getPort() 方法了解的所有端点提供服务代理。具有服务代理后,您可以调用其方法。代理使用服务合同中指定的连接详情将调用转发到远程服务端点。

getPort()方法

getPort() 方法显示在 例 25.5 “getPort() 方法” 中,为指定的端点返回服务代理。返回的代理与 SEI 相同。

例 25.5. getPort() 方法

public<T> TgetPortQNameClass<T&gt;serviceEndpointInterfaceWebServiceException

portName 参数的值是一个 QName,用于标识 wsdl:port 元素,用于定义创建代理的端点。serviceEndpointInterface 参数的值是 SEI 的完全限定名称。

注意

当您在没有 WSDL 合同的情况下工作时,portName 参数的值通常与调用 addPort() 时用于 portName 参数的值相同。

示例

例 25.6 “获取服务代理” 显示为添加到 例 25.4 “将端口添加到 服务对象 中的端点获取服务代理的代码。

例 25.6. 获取服务代理

package com.fusesource.demo;

import javax.xml.namespace.QName;
import javax.xml.ws.Service;

public class Client
{
public static void main(String args[])
  {
    ...
    quoteReporter proxy = s.getPort(portName, quoteReporter.class);
    ...
  }
}

25.5. 实现 Consumer 的商业 Logic

概述

为远程端点实例化服务代理后,您可以像本地对象一样调用其方法。调用块直到远程方法完成。

注意

如果某个方法带有 @OneWay 注释,则调用会立即返回。

示例

例 25.7 “在没有 WSDL 合同的情况下实施的消费者” 显示 例 24.7 “完全注解的 SEI” 中定义的服务的使用者。

例 25.7. 在没有 WSDL 合同的情况下实施的消费者

package com.fusesource.demo;

import java.io.File;
import java.net.URL;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;

public class Client
{
public static void main(String args[])
  {
    QName serviceName = new QName("http://demo.eric.org", "stockQuoteReporter");
  Service s = Service.create(serviceName);

    QName portName = new QName("http://demo.eric.org", "stockQuoteReporterPort");
  s.addPort(portName, "http://schemas.xmlsoap.org/soap/", "http://localhost:9000/EricStockQuote");

  quoteReporter proxy = s.getPort(portName, quoteReporter.class);

  Quote quote = proxy.getQuote("ALPHA");
    System.out.println("Stock "+quote.getID()+" is worth "+quote.getVal()+" as of "+quote.getTime());
  }
}

例 25.7 “在没有 WSDL 合同的情况下实施的消费者” 中的代码执行以下操作:

创建 Service 对象。

Service 对象中添加端点定义。

Service 对象获取服务代理。

调用服务代理上的操作。

第 26 章 开始点 WSDL 合同

26.1. WSDL 合同示例

例 26.1 “HelloWorld WSDL Contract” 显示 HelloWorld WSDL 合同。此合同在 wsdl:portType 元素中定义了一个接口 Greeter。该合同还定义了要在 wsdl:port 元素中实施该服务的端点。

例 26.1. HelloWorld WSDL Contract

<?xml version="1.0" encoding=";UTF-8"?>
<wsdl:definitions name="HelloWorld"
                  targetNamespace="http://apache.org/hello_world_soap_http"
                  xmlns="http://schemas.xmlsoap.org/wsdl/"
                  xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
                  xmlns:tns="http://apache.org/hello_world_soap_http"
                  xmlns:x1="http://apache.org/hello_world_soap_http/types"
                  xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
                  xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <wsdl:types>
    <schema targetNamespace="http://apache.org/hello_world_soap_http/types"
            xmlns="http://www.w3.org/2001/XMLSchema"
            elementFormDefault="qualified">
      <element name="sayHiResponse">
        <complexType>
          <sequence>
            <element name="responseType" type="string"/>
          </sequence>
        </complexType>
      </element>
      <element name="greetMe">
        <complexType>
          <sequence>
            <element name="requestType" type="string"/>
          </sequence>
        </complexType>
      </element>
      <element name="greetMeResponse">
        <complexType>
          <sequence>
            <element name="responseType" type="string"/>
          </sequence>
        </complexType>
      </element>
      <element name="greetMeOneWay">
        <complexType>
          <sequence>
            <element name="requestType" type="string"/>
          </sequence>
        </complexType>
      </element>
      <element name="pingMe">
        <complexType/>
      </element>
      <element name="pingMeResponse">
        <complexType/>
      </element>
      <element name="faultDetail">
        <complexType>
          <sequence>
            <element name="minor" type="short"/>
            <element name="major" type="short"/>
          </sequence>
        </complexType>
      </element>
    </schema>
  </wsdl:types>

  <wsdl:message name="sayHiRequest">
    <wsdl:part element="x1:sayHi" name="in"/>
  </wsdl:message>
  <wsdl:message name="sayHiResponse">
    <wsdl:part element="x1:sayHiResponse" name="out"/>
  </wsdl:message>
  <wsdl:message name="greetMeRequest">
    <wsdl:part element="x1:greetMe" name="in"/>
  </wsdl:message>
  <wsdl:message name="greetMeResponse">
    <wsdl:part element="x1:greetMeResponse" name="out"/>
  </wsdl:message>
  <wsdl:message name="greetMeOneWayRequest">
    <wsdl:part element="x1:greetMeOneWay" name="in"/>
  </wsdl:message>
  <wsdl:message name="pingMeRequest">
    <wsdl:part name="in" element="x1:pingMe"/>
  </wsdl:message>
  <wsdl:message name="pingMeResponse">
    <wsdl:part name="out" element="x1:pingMeResponse"/>
  </wsdl:message>
  <wsdl:message name="pingMeFault">
    <wsdl:part name="faultDetail" element="x1:faultDetail"/>
  </wsdl:message>

  <wsdl:portType name="Greeter">
    <wsdl:operation name="sayHi">
      <wsdl:input message="tns:sayHiRequest" name="sayHiRequest"/>
      <wsdl:output message="tns:sayHiResponse" name="sayHiResponse"/>
    </wsdl:operation>

    <wsdl:operation name="greetMe">
      <wsdl:input message="tns:greetMeRequest" name="greetMeRequest"/>
      <wsdl:output message="tns:greetMeResponse" name="greetMeResponse"/>
    </wsdl:operation>

    <wsdl:operation name="greetMeOneWay">
      <wsdl:input message="tns:greetMeOneWayRequest" name="greetMeOneWayRequest"/>
    </wsdl:operation>

    <wsdl:operation name="pingMe">
      <wsdl:input name="pingMeRequest" message="tns:pingMeRequest"/>
      <wsdl:output name="pingMeResponse" message="tns:pingMeResponse"/>
      <wsdl:fault name="pingMeFault" message="tns:pingMeFault"/>
    </wsdl:operation>
  </wsdl:portType>

  <wsdl:binding name="Greeter_SOAPBinding" type="tns:Greeter">
    ...
  </wsdl:binding>

  <wsdl:service name="SOAPService">
    <wsdl:port binding="tns:Greeter_SOAPBinding" name="SoapPort">
      <soap:address location="http://localhost:9000/SoapContext/SoapPort"/>
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

例 26.1 “HelloWorld WSDL Contract” 中定义的 Greeter 接口定义以下操作:

sayHi - 单个输出参数,即 xsd:string

greetMe - xsd:string 的输入参数,以及一个输出参数,即 xsd:string

greetMeOneWay - 具有 xsd 的单个输入参数:string。由于此操作没有输出参数,所以它被优化为单向调用(即,使用者不会等待服务器的响应)。

pingMe - 没有输入参数,没有输出参数,但可能会引发错误异常。

第 27 章 顶级服务开发

摘要

在开发服务提供商的顶层方法中,您从定义了服务提供商要实施的操作和方法的 WSDL 文档开始。使用 WSDL 文档,您可以为服务提供商生成起始点代码。在生成的代码中添加业务逻辑是使用常规 Java 编程 API 完成的。

27.1. JAX-WS 服务提供商开发概述

拥有 WSDL 文档后,开发 JAX-WS 服务提供商的过程如下:

  1. 第 27.2 节 “生成 Starting Point Code” 起始点代码。
  2. 实施 服务提供商的操作。
  3. 第 31 章 发布服务 所实施的服务。

27.2. 生成 Starting Point Code

概述

JAX-WS 指定从 WSDL 中定义的服务到将服务实施为服务提供商的 Java 类的详细映射。由 wsdl:portType 元素定义的逻辑接口映射到服务端点接口(SEI)。WSDL 中定义的任何复杂类型都会映射到 Java 类,遵循用于 XML Binding(JAXB)规格的 Java 架构定义的映射。由 wsdl:service 元素定义的端点也会生成成 Java 类,供使用者用于访问实施该服务的服务提供商。

cxf-codegen-plugin Maven 插件生成此代码。它还为您提供了为实施生成起始点代码的选项。代码生成器提供了控制生成的代码的多个选项。

运行代码生成器

例 27.1 “服务代码生成” 演示了如何使用代码生成器为服务生成起点代码。

例 27.1. 服务代码生成

<plugin>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-codegen-plugin</artifactId>
    <version>${cxf.version}</version>
    <executions>
        <execution>
            <id>generate-sources</id>
            <phase>generate-sources</phase>
            <configuration>
                <sourceRoot>outputDir</sourceRoot>
                <wsdlOptions>
                    <wsdlOption>
                        <wsdl>wsdl</wsdl>
                        <extraargs>
                            <extraarg>-server</extraarg>
                            <extraarg>-impl</extraarg>
                        </extraargs>
                    </wsdlOption>
                </wsdlOptions>
            </configuration>
            <goals>
                <goal>wsdl2java</goal>
            </goals>
       </execution>
    </executions>
</plugin>

这会执行以下操作:

  • impl 选项为 WSDL 合同中的每个 wsdl:portType 元素生成 shell 实施类。
  • server 选项生成 一个简单的 main(),以将您的服务提供商作为独立应用程序运行。
  • sourceRoot 指定生成的代码被写入名为 outputDir 的目录。
  • WSDL 元素指定 从中生成代码的 WSDL 合同。

有关代码生成器选项的完整列表请参考 第 44.2 节 “cxf-codegen-plugin”

生成的代码

表 27.1 “为服务提供商生成的类” 描述为创建服务提供商生成的文件。

表 27.1. 为服务提供商生成的类

File描述

portTypeName.java

SEI.此文件包含您的服务提供商实现的接口。您不应该编辑这个文件。

serviceName.java

端点。此文件包含用于在服务上发出请求的 Java 类消费者。