Apache CXF 开发指南
部分 I. 编写 WSDL 合同
这部分论述了如何使用 WSDL 定义 Web 服务接口。
第 1 章 WSDL 合同简介
摘要
WSDL 文档使用 Web 服务描述语言和许多可能的扩展来定义服务。文档具有逻辑部分和导引部分。合同摘要部分定义了实施中立数据类型和消息的服务。文档的对比部分定义了实施服务的端点如何与外界交互。
设计服务的建议方法是在编写任何代码前在 WSDL 和 XML Schema 中定义您的服务。在手动编辑 WSDL 文档时,您必须确保文档有效,并且正确。要执行此操作,您必须对 WSDL 有一定的了解。您可以在 W3C 网站 www.w3.org 中找到标准。
1.1. WSDL 文档的结构
概述
WSDL 文档在其最简单的元素中是根 定义
元素中包含的元素集合。这些元素描述了服务以及如何实施该服务的端点。
WSDL 文档有两个不同的部分:
- 在实施中立条款中定义服务 的逻辑部分
- 一个 concrete 部分,用于定义如何在网络中公开实施该服务的端点
逻辑部分
WSDL 文档的逻辑部分包含 类型
、消息
和 portType
元素。它描述了服务的接口以及服务交换的消息。在 类型
元素中,XML Schema 用于定义组成消息的数据的结构。许多 消息
元素用于定义服务所使用的消息的结构。portType
元素包含一个或多个 操作
元素,用于定义由服务公开的操作发送的消息。
concrete 部分
WSDL 文档中的 concrete 部分包含 绑定
和服务
元素。它描述了实现服务的端点如何连接到外部世界。绑定
元素描述了 消息
元素所描述的数据单元如何映射到 concrete,在线数据格式,如 SOAP。服务
元素包含一个或多个 端口
元素,它们定义实施服务的端点。
1.2. WSDL 元素
WSDL 文档由以下元素组成:
-
定义
- WSDL 文档的根元素。此元素的属性指定 WSDL 文档的名称、文档的目标命名空间以及 WSDL 文档中引用的命名空间的简短定义。 -
类型
- 组成由服务使用消息的构建块的数据单元的 XML Schema 定义。有关定义数据类型的详情,请参考 第 2 章 定义逻辑数据单位。 -
Message - 在调用服务操作期间交换的消息的描述。
这些元素定义了组成您的服务的操作的参数。有关定义信息的详情,请参考 第 3 章 定义服务使用的逻辑消息。
-
portType
- 描述服务的逻辑接口的操作
元素集合。有关定义端口类型的详情,请参考 第 4 章 定义逻辑接口。 -
operation
- 服务执行的操作描述。操作通过调用操作时在两个端点之间传递的消息来定义。有关定义操作的详情,请参考 “操作”一节。 -
binding
- 端点的 concrete 数据格式规格。binding
元素定义抽象消息如何映射到端点使用的 concrete 数据格式。这个元素是指定参数顺序和返回值等具体位置。 -
服务
- 相关端口元素
的集合。这些元素是用于组织端点定义的存储库。 -
端口
- 由绑定和物理地址定义的端点。这些元素将所有抽象定义集合在一起,结合传输详情的定义,并定义服务所公开的物理端点。
1.3. 设计一个合同
要为服务设计 WSDL 合同,您必须执行以下步骤:
- 定义服务使用的数据类型。
- 定义服务所使用的消息。
- 定义您的服务的接口。
- 定义各个接口使用的消息之间的绑定,以及线上数据的 concrete 表示。
- 定义每个服务的传输详细信息。
第 2 章 定义逻辑数据单位
摘要
在 WSDL 合同中描述服务时,使用 XML Schema 将服务定义为逻辑单元。
2.1. 逻辑数据单元简介
在定义服务时,您必须考虑首先考虑将数据用作公开操作的参数。与使用固定数据结构的编程语言编写的应用程序不同,服务必须在逻辑单元中定义其数据,这些单元可由任意数量的应用程序使用。这涉及两个步骤:
- 将数据拆分为逻辑单元,它们可映射到服务物理实施使用的数据类型
- 将逻辑单元合并到端点之间传递的消息中以执行操作
本章讨论第一步。第 3 章 定义服务使用的逻辑消息 讨论第二步。
2.2. 将数据映射到逻辑数据单元
概述
用于实施服务的接口定义了代表操作参数的数据,作为 XML 文档。如果您要为已经实施的服务定义接口,您必须将实施操作的数据类型转换为可编译到消息的 XML 元素中。如果您从头开始,您必须确定构建您的消息的构建块,以便在实施角度有意义。
用于定义服务单元的可用类型
根据 WSDL 规范,您可以使用任意类型系统在 WSDL 合同中定义数据类型。但是,W3C 规范指出 XML Schema 是 WSDL 文档的首选规范类型系统。因此,XML Schema 是 Apache CXF 中的内部类型系统。
XML Schema 作为类型系统
XML Schema 用于定义 XML 文档的结构。这可以通过定义组成文档的元素来完成。这些元素可以使用原生 XML Schema 类型,如 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 Schema 来代表 WSDL 文档中的数据类型的准则:
- 使用元素,而不是属性。
- 不要使用特定于协议的类型作为基本类型。
2.3. 在合同中添加数据单元
概述
根据您选择创建 WSDL 合同的方式,创建新的数据定义需要不同的知识。Apache CXF GUI 工具为使用 XML Schema 描述数据类型提供了多个帮助。其他 XML 编辑器可提供不同级别的帮助。无论您选择哪种编辑器,都最好了解所生成合同应看的内容。
流程
定义 WSDL 合同中使用的数据涉及以下步骤:
- 确定合同描述的接口中使用的所有数据单元。
-
在您的合同中创建
类型
元素。 创建一个
架构
元素,如 例 2.1 “WSDL 合同的 schema 条目” 所示,作为type
元素的子项。targetNamespace
属性指定定义新数据类型的命名空间。最佳实践是定义提供目标命名空间访问权限的命名空间。剩余的条目不应更改。例 2.1. WSDL 合同的 schema 条目
<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/">
-
对于作为元素集合的每个复杂类型,使用
complexType
元素定义数据类型。请参阅 第 2.5.1 节 “定义数据结构”。 -
对于每个数组,使用
complexType
元素定义数据类型。请参阅 第 2.5.2 节 “定义数组”。 -
对于从简单类型派生的每一复杂类型,使用
simpleType
元素定义数据类型。请参阅 第 2.5.4 节 “根据限制定义类型”。 -
对于每个枚举类型,请使用
simpleType
元素定义数据类型。请参阅 第 2.5.5 节 “定义枚举类型”。 -
对于每个元素,使用
元素
来定义它。请参阅 第 2.6 节 “定义元素”。
2.4. XML Schema 简单的类型
概述
如果消息部分是简单类型,则不需要为其创建类型定义。但是,合同中定义的接口所使用的复杂类型是使用简单类型来定义的。
输入简单类型
XML Schema 简单的类型主要放在您的合同类型部分中使用的元素中。它们也用于限制元素和扩展
元素
的基本
属性。
始终使用 xsd
前缀输入简单的类型。例如,要指定元素类型是 int
,您需要在其 type
属性中输入 xsd:int
,如 例 2.2 “使用简单类型定义元素” 所示。
例 2.2. 使用简单类型定义元素
<element name="simpleInt" type="xsd:int" />
支持的 XSD 简单类型
Apache CXF 支持以下 XML Schema 简单类型:
-
xsd:string
-
xsd:normalizedString
-
xsd:int
-
xsd:unsignedInt
-
xsd:long
-
xsd:unsignedLong
-
xsd:short
-
xsd:unsignedShort
-
xsd:float
-
xsd:double
-
xsd:boolean
-
xsd:byte
-
xsd:unsignedByte
-
xsd:integer
-
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 Schema 提供了一种灵活、强大的机制,用于从其简单数据类型构建复杂数据结构。您可以通过创建一系列元素和属性来创建数据结构。您还可以扩展定义的类型,以创建更复杂的类型。
除了构建复杂数据结构外,您还可以描述专用类型,如枚举类型、具有特定值的数据类型或需要遵循特定模式的数据类型,通过扩展或限制原语类型。
2.5.1. 定义数据结构
概述
在 XML Schema 中,是数据字段集合的数据集使用 复杂的Type
元素进行定义。指定复杂类型需要三段信息:
-
定义的类型的名称在
complexType
元素的name
属性中指定。 -
complexType
的第一个子元素描述结构字段在线上时的行为。请参阅 “复杂类型 varieties”一节。 -
定义的结构的每个字段都在
复杂Type
元素中的元素中定义。请参阅 “定义结构的部分”一节。
例如: 例 2.3 “简单结构” 中显示的结构在 XML Schema 中定义为带有两个元素的复杂类型。
例 2.3. 简单结构
struct personalInfo { string name; int age; };
例 2.4 “复杂类型” 显示 例 2.3 “简单结构” 中显示的结构的一个可能 XML Schema 映射,例 2.4 “复杂类型” 中定义的结构会生成包括两个元素: name
和 age
的消息。
.
例 2.4. 复杂类型
<complexType name="personalInfo"> <sequence> <element name="name" type="xsd:string" /> <element name="age" type="xsd:int" /> </sequence> </complexType>
复杂类型 varieties
XML Schema 有三种方法:描述复杂类型的字段在以 XML 文档表示并传递线时如何组织。complexType
元素的第一个子元素决定了使用哪一种复杂类型。表 2.1 “复杂的类型描述符元素” 显示用来定义复杂类型行为的元素。
element | 复杂的类型行为 |
---|---|
所有复杂的类型字段都可以存在,它们必须按照类型定义中指定的顺序。 | |
所有复杂的类型字段都可以存在,但可以按照任何顺序排列。 | |
结构中只有一个元素可以放在消息中。 |
如果结构是使用 选择
元素定义的,如 例 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
元素
中的每个元素都表示定义的数据结构中的一个字段。
要完全描述数据结构中的字段,元素
元素有两个必要属性:
除了名称和类型 外,元素
还有两个常用的可选属性: minOcurrs
和 maxOccurs
。
这些属性根据字段在结构中发生的次数绑定。默认情况下,每个字段仅在复杂类型中仅发生一次。通过使用这些属性,您可以更改字段必须或可在结构中出现的次数。例如,您可以定义一个字段(
之前Jobs
),它必须至少发生三次,且不超过七次,如 例 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
设置为零(如 例 2.7 “带有 minOccurs 设置为 0 的简单复杂类型” 所示),使用 minOccurs
使 age
字段是可选的。在这种情况下,年龄
可以被省略,数据仍将有效。
例 2.7. 带有 minOccurs 设置为 0 的简单复杂类型
<complexType name="personalInfo"> <choice> <element name="name" type="xsd:string"/> <element name="age" type="xsd:int" minOccurs="0"/> </choice> </complexType>
定义属性
在 XML 文档中,属性包含在元素的标签中。例如,在下面的代码中的 complexType
元素中,name
是一个属性。要为复杂类型指定属性,您可以在 complexType
元素定义中定义 属性
元素。属性
元素只能在 所有
、sequence
或 choice
元素后面出现。为每个复杂类型的属性指定一个 属性
元素。任何 属性
元素都必须是 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>
在前面的代码中,属性
元素指定 personalInfo
复杂类型具有 age
属性。属性
元素具有这些属性:
在 属性
元素中,您可以指定可选 默认
属性,这可让您为属性指定默认值。
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 阵列通过利用 wsdl:arrayType
元素从 SOAP-ENC:Array
基础类型分离来定义。其语法显示在 例 2.10 “使用 wsdl:arrayType 进行 SOAP 数组派生的语法” 中。确保 定义
元素声明 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
和 dissions 的数量,带有 []
意味着一个维度。
例 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
属性必须始终设置为 未绑定
。
2.5.3. 按扩展定义类型
与大多数主要编码语言一样,XML Schema 允许您创建数据类型,从其他数据类型继承其部分元素。这称为扩展来定义类型。例如,您可以创建一个名为 alienInfo
的新类型,通过添加名为 planet
的新元素来扩展 例 2.4 “复杂类型” 中定义的 personalInfo
结构。
由扩展定义的类型有四个部分:
-
类型的名称由
complexType
元素的name
属性定义。 complexContent
元素指定新类型将拥有多个元素。注意如果您只向复杂类型添加新属性,您可以使用
simpleContent
元素。-
新类型派生的类型(称为 基本 类型)是在 extension 元素的
base
属性中指定
。 -
新的类型的元素和属性在
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 Schema 允许您通过限制 XML Schema 简单类型可能的值来创建新类型。例如,您可以定义一个简单的类型 SSN
,字符串为正好 9 个字符。通过限制使用 simpleType
元素来定义简单类型的新类型。
按限制划分的定义需要三个因素:
-
新类型的名称由
simpleType
元素的name
属性指定。 -
新类型派生自的简单类型(称为 基本类型 )是在 limit 元素中指定。
请参阅 “指定基本类型”一节。
-
名为 facets 的规则,定义基本类型的限制被定义为
限制
元素的子项。请参阅 “定义限制”一节。
指定基本类型
基础类型是被限制在定义新类型中的类型。它使用 限制
元素来指定。limit 元素是 simpleType
元素的唯一子项,它有一个属性 base
,用于指定基本类型。基础类型可以是任何 XML Schema 简单的类型。
例如,若要通过限制 xsd:int
的值来定义一个新类型,您可以使用类似 例 2.14 “使用 int 作为基本类型” 所示的定义。
例 2.14. 使用 int 作为基本类型
<simpleType name="restrictedInt"> <restriction base="xsd:int"> ... </restriction> </simpleType>
定义限制
定义对基本类型的限制的规则被称为 facets。facets 是带有一个属性( 值
)的元素,用于定义 facet 的强制实施方式。可用因素及其 有效值
设置取决于基本类型。例如,xsd:string
支持六个问题,包括:
-
length
-
minLength
-
maxLength
-
pattern
-
whitespace
-
enumeration
每个 facet 元素都是 限制
元素的子项。
示例
例 2.15 “SSN 简单的类型描述” 显示 SSN
的简单类型示例,它代表一个社交安全编号。生成的类型是 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 Schema 中枚举的类型是一个根据限制定义的特殊情形。它们通过使用枚举的 枚举来说明
,它受所有 XML Schema 原语类型的支持。与大多数现代编程语言中枚举类型一样,此类型的变量只能具有一个指定的值。
在 XML Schema 中定义枚举
例 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 是任意数字一或大于值,指定枚举每个具体案例的值。枚举的类型可以具有任意数量的 case 值,但它源自一个简单类型,因此一次只有其中一个问题单值才有效。
示例
例如,如果一个含有 < widgetSize
>big</widgetSize>big</widgetSize>,则由 enumeration widgetSize> 定义元素的 XML 文档在 例 2.17 “widgetSize enumeration” 中包含 <widgetSize> 时才有效。
例 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 Schema 中的元素代表从架构生成的 XML 文档中的元素实例。最基本的 元素由单一元素组成
。与定义复杂类型的成员的 element
元素一样,它们有三个属性:
-
name
- 一个必需属性,用于指定在 XML 文档中出现的元素名称。 -
type
- 指定元素的类型。类型可以是任何 XML Schema 原语类型,也可以是合同中定义的任何指定复杂类型。如果类型包含 in-line 定义,则可以省略此属性。 -
nillable
- 指定一个元素是否可以完全省略。如果将nillable
设为true
,则这个元素可以从使用 schema 生成的任何文档中省略。
元素也可以 具有在线 类型定义。使用 complexType
元素或 simpleType
元素来指定在线类型。指定数据类型是否比较复杂或简单后,您可以使用每种数据类型可用的工具定义任何类型的数据。不建议使用 in-line 类型的定义,因为无法重复使用。
第 3 章 定义服务使用的逻辑消息
摘要
服务由消息在调用其操作时进行交换定义。在 WSDL 合同中,这些消息通过使用 消息
元素来定义。这些消息由一个或多个使用 部分
元素定义的部分组成。
概述
服务的操作是通过指定调用操作时交换的逻辑消息来定义。这些逻辑消息定义通过网络作为 XML 文档传递的数据。它们包含属于方法调用一部分的所有参数。 使用合同中的 message
元素定义逻辑消息。每个逻辑消息由一个或多个部分组成,它们在 部分
元素中定义。
虽然您的消息可以列出各个参数作为单独的部分,但推荐的做法是只使用单个部分来封装操作所需的数据。
消息和参数列表
服务公开的每个操作只能有一个输入消息和一个输出信息。输入消息定义服务在调用操作时接收的所有信息。输出消息定义在操作完成时返回的所有数据。容错消息定义在发生错误时服务返回的数据。
此外,每个操作都可以具有任意数量的故障消息。故障消息定义服务遇到错误时返回的数据。这些消息通常仅有一个部分提供足够的信息供消费者理解该错误。
用于与旧系统集成的消息设计
如果您要将现有应用程序定义为服务,您必须确保实施该操作方法使用的每个参数都会在消息中表示。您还必须确保返回的值包含在操作的输出消息中。
定义消息的一种方法是 RPC 样式。使用 RPC 风格时,您可以在方法的参数列表中为每个参数定义一个部分。每条消息部分都基于合同元素中定义的 类型
。您的输入消息包含方法中每个输入参数的一个部分。您的输出消息包含每个输出参数的一个部分,以及用于表示返回值的部分(如果需要)。如果参数同时是输入和输出参数,它将被列为输入消息和输出消息的一部分。
当服务启用使用 Tibco 或 CORBA 等传输的系统时,RPC 风格消息定义很有用。这些系统围绕流程和方法设计。因此,它们最容易使用类似参数列表的消息来建模。RPC 风格还在服务与应用程序间进行清晰映射。
SOAP 服务的消息设计
尽管 RPC 风格对于对现有系统建模非常有用,但该服务的社区很强大地选择被嵌套的文档样式。在嵌套文档样式中,每个消息都有单个部分。消息的部分引用在合同 类型
的元素中定义的 wrapper 元素。wrapper 元素具有以下特征:
- 它是包含一系列元素的复杂类型。更多信息请参阅 第 2.5 节 “定义复杂数据类型”。
如果它是输入消息的打包程序:
- 它有一个元素,用于各个方法的输入参数。
- 其名称与与之关联的操作的名称相同。
如果它是一个输出消息的打包程序:
- 它为每个方法的输出参数和一个元素,每个方法的 inout 参数都有一个元素。
- 其第一个元素表示方法的 return 参数。
-
其名称是通过在与打包程序关联的操作名称中添加
Response
来生成的。
消息命名
合同中的每个消息都必须在其命名空间内具有唯一的名称。建议您使用以下命名规则:
- 消息仅应由单个操作使用。
-
将
Request
附加到操作名称即可形成输入消息名称。 -
通过将
Response
附加到操作名称来形成输出信息名称。 - 容错消息名称应该代表故障的原因。
Message parts
Message 部分是逻辑消息的正式数据单元。每一部分使用 part
元素进行定义,由 name
属性和 type
属性识别,或者指定其数据类型的元素属性。数据类型属性列在 表 3.1 “部分数据类型属性” 中。
属性 | 描述 |
---|---|
部分的数据类型由名为 elem_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 合同中定义逻辑接口,您必须执行以下操作:
端口类型
WSDL portType
元素是逻辑接口定义中的根元素。虽然许多 Web 服务实现将 portType
元素直接映射到生成实现对象,但逻辑接口定义并不指定由实施的服务提供的确切功能。例如,名为 ticketSystem 的逻辑接口可导致销售问题单或问题清除票据实现。
portType
元素是 WSDL 文档的单元,它映射到一个绑定,用于定义由端点公开定义的服务使用的物理数据。
WSDL 文档中的每个 portType
元素都必须具有唯一的名称,该名称使用 name
属性指定,由一组操作组成,它们在 操作
元素中描述。WSDL 文档可以描述任意数量的端口类型。
操作
使用 WSDL 操作元素定义的逻辑 操作
,定义两个端点之间的交互。例如,对检查帐户平衡的请求和跨小部件的顺序可以定义为操作。
portType
元素中定义的每个操作都必须使用 name
属性指定的唯一名称。定义操作需要 name
属性。
操作消息
逻辑操作由一组元素组成,它们代表端点之间传递的逻辑消息来执行操作。可以描述操作的元素列在 表 4.1 “操作消息元素” 中。
element | 描述 |
---|---|
| 指定在发出请求时客户端端点发送到服务提供商的消息。此消息的部分对应于操作的输入参数。 |
| 指定服务供应商发送到客户端端点的消息以响应请求。此消息的部分对应于任何可由服务提供商更改的操作参数,如引用传递的值。这包括操作返回值。 |
| 指定用于在端点之间传递错误条件的消息。 |
要至少有一个 输入
或一个 输出
元素,需要一个操作。操作可以同时具有
元素,但它只能有一个。不需要操作来有任何错误元素,但可以根据需要具有任意数量的 输入和输出
故障
元素。
元素在 表 4.2 “输入和输出元素的属性” 中列出的有两个属性。
属性 | 描述 |
---|---|
| 标识消息,以便在将操作映射到 concrete 数据格式时对其进行引用。名称必须在封闭的端口类型内唯一。 |
|
指定描述正在发送或接收数据的抽象消息。 |
不需要为所有
元素指定 输入和输出
name
属性;WSDL 提供了一个基于嵌套操作名称的默认命名方案。如果操作中只有一个元素,则元素名称默认为操作的名称。如果使用
元素,则元素名称默认为操作的名称,并且分别附加了 输入和输出
Request
或 Response
。
返回值
因为 operation
元素是在操作过程中传递的数据抽象定义,所以 WSDL 不提供为操作指定的返回值。如果方法返回了一个值,它将映射到 output
元素,作为该消息的最后一个部分。
示例
例如,您可能有一个与 例 4.1 “personalInfo lookup interface” 中显示的接口类似的接口。
例 4.1. personalInfo lookup interface
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 中的绑定
摘要
绑定将用于定义服务的逻辑消息映射到端点可以传输和接收的有效载荷格式。
概述
绑定为服务使用的逻辑消息提供网桥,用于隔离端点在物理世界中使用的数据格式。它们描述了逻辑消息如何映射到端点线上所用载荷格式。它在绑定中指定了参数顺序、concrete 数据类型和返回值。例如,消息的部分可以在绑定中重新排序,以反映 RPC 调用所需的顺序。根据绑定类型,您还可以识别消息部分(若有)代表方法的返回类型。
端口类型和绑定
端口类型和绑定直接相关。端口类型是两个逻辑服务之间一组交互的抽象定义。绑定是实施逻辑服务将如何在物理世界实例化的用于实施逻辑服务的消息的结盟定义。然后,每个绑定都与一组网络详细信息关联,以完成一个端点的定义,该端点公开了端口类型定义的逻辑服务。
为确保端点仅定义了单个服务,WSDL 要求绑定只能表示单个端口类型。例如,如果您有一个具有两个端口类型的合同,则无法写入将这两个映射为共用数据格式的单个绑定。您需要两个绑定。
但是,WSDL 允许将端口类型映射到多个绑定。例如,如果您的合同具有单一端口类型,您可以将其映射到两个或者多个绑定。每个绑定都可以改变消息的部分映射方式,也可以为消息指定完全不同的有效负载格式。
WSDL 元素
使用 WSDL 绑定元素在合同中定义绑定
。绑定元素由 名称
等属性组成,用于指定提供 PortType 引用的绑定和 类型
的唯一名称。此属性的值用于将绑定与端点关联,如 第 4 章 定义逻辑接口 中所述。
实际映射在 绑定
元素的子项中定义。这些元素根据您决定使用的有效负载格式类型而有所不同。以下章节中讨论不同的有效载荷格式以及用于指定其映射的元素。
添加到合同
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 绑定
使用 wsdl2soap
要使用 wsdl2soap
命令生成 SOAP 1.1 绑定:ws dl2soap
-iport-type-name-bbinding-name-doutput-directory-ooutput-file-nsoap-body-namespace-style (document/rpc)-use (literal/encoded)-v-verbose-quietwsdlurl
要使用 wsdl2soap
,您需要下载 Apache CXF 分发。
该命令有以下选项:
选项 | 解释 |
---|---|
|
指定生成绑定的 |
wsdlurl |
包含 |
该工具具有以下可选参数:
选项 | 解释 |
---|---|
| 指定生成的 SOAP 绑定的名称。 |
| 指定要放置所生成的 WSDL 文件的目录。 |
| 指定生成的 WSDL 文件的名称。 |
| 当样式为 RPC 时,指定 SOAP 正文命名空间。 |
| 指定 SOAP 绑定中使用的编码风格(文档或 RPC)。默认为 document。 |
| 指定 SOAP 绑定中使用的绑定使用(编码或文字)。默认值为字面值。 |
| 显示工具的版本号。 |
| 在代码生成过程中显示注释。 |
| 在代码生成过程中阻止注释。 |
需要 -i
port-type-name 和 wsdlurl 参数。如果指定了 -style rpc
参数,则还需要 -n
soap-body-namspace 参数。所有其他参数都是可选的,可以按任何顺序列出。
wsdl2soap
不支持生成 文档/编码的
SOAP 绑定。
示例
如果您的系统有一个处理订单的接口,并提供单一操作来处理在 WSDL 片段中定义的订单,类似于 例 6.1 “排序系统接口” 中显示的订单。
例 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 绑定” 中。
例 6.2. orderWidgets
的 SOAP 1.1 绑定
<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 标头添加到 SOAP 1.1 Binding 中
概述
SOAP 标头通过将 soap:header
元素添加到默认 SOAP 1.1 绑定来定义。soap:header
元素是 输入
、输出
和绑定 错误
元素的可选子项。SOAP 标头成为父消息的一部分。通过指定消息和消息部分来定义 SOAP 标头。每个 SOAP 标头只能包含一个消息部分,但您可以根据需要插入所需数量的 SOAP 标头。
语法
定义 SOAP 标头的语法显示在 例 6.3 “SOAP 标头语法” 中。soap:header
的 message
属性是要插入到标头中的部分的合格名称。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
也支持 命名空间
、使用
,以及 编码Style
属性。这些属性与 soap:header
的作用相同 。
在正文和标头间分割消息
插入到 SOAP 标头中的消息部分可以是来自合同的任何有效的消息部分。它甚至可以从父消息中用作 SOAP 正文的部分。由于不太可能在同一消息中发送信息两次,SOAP 绑定提供了指定插入到 SOAP 正文中的消息部分的方法。
soap:body
元素具有一个可选属性 部分
,它用以空格分隔的部分名称列表。定义部分后,只有列出的消息部分才会插入到 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. 在 WSDL 文档中添加 SOAP 1.2 绑定
使用 wsdl2soap
要使用 wsdl2soap,您需要下载 Apache CXF 分发。
要使用 wsdl2soap
命令生成 SOAP 1.2 绑定:ws dl2soap
-iport-type-name-bbinding-name-soap12-doutput-directory-ooutput-file-nsoap-body-namespace-style (document/rpc)-use (literal/encoded)-name -b binding-quietwdl-quiet wdlurl 工具具有以下参数:
选项 | 解释 |
---|---|
|
指定生成绑定的 |
| 指定生成的绑定使用 SOAP 1.2。 |
wsdlurl |
包含 |
该工具具有以下可选参数:
选项 | 解释 |
---|---|
| 指定生成的 SOAP 绑定的名称。 |
| 指定生成的绑定将使用 SOAP 1.2。 |
| 指定要放置所生成的 WSDL 文件的目录。 |
| 指定生成的 WSDL 文件的名称。 |
| 当样式为 RPC 时,指定 SOAP 正文命名空间。 |
| 指定 SOAP 绑定中使用的编码风格(文档或 RPC)。默认为 document。 |
| 指定 SOAP 绑定中使用的绑定使用(编码或文字)。默认值为字面值。 |
| 显示工具的版本号。 |
| 在代码生成过程中显示注释。 |
| 在代码生成过程中阻止注释。 |
需要 -i
port-type-name 和 wsdlurl 参数。如果指定了 -style rpc
参数,则需要 -n
soap-body-namspace 参数。所有其他参数都是可选的,可以按任何顺序列出。
wsdl2soap
不支持生成 文档/编码的
SOAP 1.2 绑定。
示例
如果您的系统有一个处理订单的接口,并提供单一操作来处理在 WSDL 片段中定义的订单,类似于 例 7.1 “排序系统接口” 中显示的订单。
例 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
元素是 输入
、输出
和绑定 错误
元素的可选子项。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>
soap12:header
元素的属性在 表 7.1 “soap12:header
Attributes” 中描述。
属性 | 描述 |
---|---|
必需的属性,指定从中插入部分要放入标题中的相应消息的合格名称。 | |
指定插入到 SOAP 标头中的消息部分的名称必需属性。 | |
指定消息部分是否使用编码规则进行编码。如果设为 | |
指定用于构建消息的编码规则。 | |
定义 |
在正文和标头间分割消息
插入到 SOAP 标头中的消息部分可以是来自合同的任何有效的消息部分。它甚至可以从父消息中用作 SOAP 正文的部分。由于不太可能在同一消息中发送信息两次,SOAP 1.2 绑定提供了指定插入到 SOAP 正文中的消息部分的方法。
soap12:body
元素具有一个可选属性 部分
,它用以空格分隔的部分名称列表。定义部分后,只有列出的消息部分才会插入到 SOAP 1.2 消息的正文中。然后,您可以将剩余的部分插入到消息的标头中。
当使用父消息的部分定义 SOAP 标头时,Apache CXF 会自动填写 SOAP 标头。
示例
例 7.4 “带有 SOAP 标头的 SOAP 1.2 绑定” 显示 例 7.1 “排序系统接口” 中显示的 orderWidgets
服务的修改版本。此版本会被修改,以便每个顺序在请求标题和响应的标头中都有一个 xsd:base64binary
值。标头定义为 widgetKey
消息中的 keyVal
部分。在本例中,您要负责添加应用程序逻辑以创建标头,因为它不是输入或输出消息的一部分。
例 7.4. 带有 SOAP 标头的 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 标头的 SOAP 1.2 绑定”,以便标头值是输入和输出信息的一部分,如 例 7.5 “带有 SOAP 标头的 orderWidget 的 SOAP 1.2 绑定” 所示。在本例中,keyVal
是输入和输出消息的一部分。在 soap12:body
元素中,parts
属性指定 键Val
不应插入到正文中。但是,它将插入到标头中。
例 7.5. 带有 SOAP 标头的 orderWidget 的 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 发送 Binary 数据
摘要
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 绑定中的 soap:body
元素。剩余的 mime:part
元素定义在消息中发送的附件。
描述 MIME 多部分信息
MIME 多部件使用 mime:multipartRelated
元素 来描述
。要完全描述 MIME 多部件,您必须执行以下操作:
-
在您要发送为 MIME 多部件的输入或输出消息内,添加
mime:mulipartRelated
元素作为所属消息的第一个子元素。 -
将
mime:part
子元素添加到mime:multipartRelated
元素,并将其name
属性设置为唯一字符串。 添加
soap:body
元素作为mime:part
元素的子元素,并相应地设置其属性。注意如果合同具有默认的 SOAP 绑定,您可以将
soap:body
元素从默认绑定复制到 MIME 多部分消息。-
将另一个
mime:part
子元素添加到mime:multipartReleated
元素,并将其name
属性设置为唯一字符串。 将
mime:content
子元素添加到mime:part
元素,以描述消息此部分的内容。要完全描述 MIME 消息部分部分
mime:content
元素有以下属性:表 8.1. MIME:content 属性 属性 描述 + 指定来自父消息定义中的 WSDL 消息
部分
的名称,该名称用作 MIME 多部件在线上放置的 MIME 多部件的内容。+
此消息部分中数据的 MIME 类型。MIME 类型定义为类型,子类型使用语法 类型
/
子类型。+
有很多预定义的 MIME 类型,如
image/jpeg
和text/plain
。MIME 类型由互联网编号授权机构(IANA)维护,并在 多用途 Internet 邮件扩展(MIME)中详细介绍:Internet Message Bodies 和 多用途 Internet 邮件扩展(MIME)第 2 部分的内容。+
- 对于每个额外的 MIME 部分,重复步骤 [i303819] 和 [i303821]。
示例
例 8.2 “使用带有附件的 SOAP 的合同” 显示 WSDL 片段,它定义了以 JPEG 格式存储 X-rays 的服务。镜像数据 xRay
存储在 xsd:base64 二进制代码
中,并打包成 MIME 多部件的第二个部分 imageData
。输入消息的两部分 patientName
和 patientNumber
在 MIME 多部件镜像的第一部分中作为 SOAP 正文的一部分发送。
例 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 发送二进制数据不需要您完全定义 MIME 多部件/续订消息作为 SOAP 绑定的一部分。但是,它要求您进行以下操作:
9.2. 将数据类型注解为使用 MTOM
概述
在 WSDL 中,在定义传入二进制数据的数据类型时,如镜像文件或声文件,您可以定义要类型为 xsd:base64
inary 数据的元素。默认情况下,类型为 xsd:base64Binary
的任何元素都会生成 byte[]
,这些元素可以使用 MTOM 进行序列化。但是,代码生成器的默认行为不会充分利用序列化。
要充分利用 MTOM,您必须在服务的 WSDL 文档或实施二进制数据结构的 JAXB 类中添加注解。在 WSDL 文档中添加注解会强制代码生成器为二进制数据生成流数据处理程序。注解 JAXB 类涉及指定正确的内容类型,并可能涉及更改包含二进制数据的字段类型规格。
WSDL 首先
例 9.1 “MTOM 的消息” 显示 Web 服务的 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 类型,代码生成器会创建一个数据处理程序。某些 MIME 类型(如镜像的那些类型)定义了映射。
MIME 类型由互联网编号授权机构(IANA)维护,并在 多用途互联网邮件扩展(MIME)中详细介绍:Internet Message Bo dies 和 多用途 Internet 邮件扩展(MIME)第 2 部分的内容。
对于大多数使用,您可以指定 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 就绪:
- 确保包含二进制数据的字段为数据处理程序。
-
将
@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 支持,如下所示:
访问已发布服务的
Endpoint
对象。访问
Endpoint
对象的最简单方法是当您发布端点时。更多信息请参阅 第 31 章 发布服务。使用其
getBinding ()
方法从Endpoint
获取 SOAP 绑定,如 例 9.4 “从 Endpoint 获取 SOAP Binding” 所示。例 9.4. 从 Endpoint 获取 SOAP Binding
// Endpoint ep is declared previously SOAPBinding binding = (SOAPBinding)ep.getBinding();
您必须将返回的绑定对象转换为
SOAPBinding
对象来访问 MTOM 属性。使用绑定的
setMTOMEnabled ()
方法将绑定的 MTOM enabled 属性设为true
,如 例 9.5 “设置服务提供商的 MTOM Enabled Property” 所示。例 9.5. 设置服务提供商的 MTOM Enabled Property
binding.setMTOMEnabled(true);
消费者
要 MTOM 启用 JAX-WS 使用者,您必须执行以下操作:
将消费者的代理投到
BindingProvider
对象。有关获取消费者代理的详情,请参考 第 25 章 在没有 WSDL 合同的情况下开发消费者 或 第 28 章 从 WSDL 合同开发消费者。
使用其
getBinding ()
方法从BindingProvider
获取 SOAP 绑定,如 例 9.6 “从BindingProvider
获取 SOAP 绑定” 所示。例 9.6. 从
BindingProvider
获取 SOAP 绑定// BindingProvider bp declared previously SOAPBinding binding = (SOAPBinding)bp.getBinding();
使用绑定的
setMEnabled ()方法将 bindings MTOM
enabled 属性设为true
,如 例 9.7 “设置 Consumer 的 MTOM Enabled Property” 所示。例 9.7. 设置 Consumer 的 MTOM Enabled Property
binding.setMTOMEnabled(true);
9.3.2. 使用配置
概述
如果使用 XML (如部署到容器时)发布您的服务,您可以在端点配置文件中的 MTOM 支持启用端点的 MTOM 支持。有关配置端点的更多信息,请参阅 第 IV 部分 “配置 Web 服务端点”。
流程
MTOM 属性在您的端点的 jaxws:endpoint
元素内设置。启用 MTOM 执行以下操作:
-
向端点的
jaxws:property
子元素中添加jaxws:
property 子元素。 -
向
jaxws:property
元素中添加条目
子元素。 -
将
条目
元素的key
属性设置为mtom-enabled
。 -
将
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 绑定的扩展。请参阅 “XML 绑定命名空间”一节。
-
在您的合同中添加标准 WSDL
绑定
元素来容纳 XML 绑定,为绑定指定唯一名称
,并指定代表所绑定的接口的 WSDLportType
元素的名称。 -
向绑定元素中添加
xformat:
子元素,以标识消息作为纯 XML 文档处理,但没有 SOAP envelopes。binding
-
另外,还可将
xformat:binding
元素的rootNode
属性设置为有效的 QName。有关rootNode
属性的效果的更多信息,请参阅 “线上的 XML 消息”一节。 -
对于每个在绑定接口中定义的操作,添加一个标准的 WSDL
操作
元素,以存放操作消息的绑定信息。 对于添加到绑定的每个操作,添加
输入
、输出和错误
子元素,以表示操作所使用的消息。这些元素对应于逻辑操作的接口定义中定义的消息。
-
(可选)将具有有效
rootNode
属性的xformat:body
元素添加到添加的输入
、输出
和故障元素中,以覆盖绑定级别的rootNode
设置值。
如果您的任何消息都没有部分,例如返回 void 的操作的输出消息,您必须为消息设置 rootNode
属性,以确保在线上写入的消息有效,但空 XML 文档。
线上的 XML 消息
当您指定接口的消息作为 XML 文档传递时,如果没有 SOAP envelope,则必须小心谨慎,以确保您的消息表单在有线上写时,确保消息形成有效的 XML 文档。您还需要确保接收 XML 文档的非 Apache CXF 参与者了解 Apache CXF 生成的消息。
解决这两个问题的简单方法是,在 global xformat:binding
元素上使用可选的 rootNode
属性,或者用于单个消息的 xformat:body
元素。rootNode
属性为元素指定 QName,充当由 Apache CXF 生成的 XML 文档的根节点。如果没有设置 rootNode
属性时,Apache CXF 使用消息部分的 root 元素,在使用 doc 风格消息时将消息部分名称用作 root 元素,或使用消息部分名称作为 root 元素。
例如,如果 rootNode
属性没有设置 例 10.1 “有效的 XML 绑定消息” 中定义的信息,则会生成带有 root 元素 lineNumber
的 XML 文档。
例 10.1. 有效的 XML 绑定消息
<type ... > ... <element name="operatorID" type="xsd:int"/> ... </types> <message name="operator"> <part name="lineNumber" element="ns1:operatorID"/> </message>
对于只有一个部分的消息,即使未设置 rootNode
属性,Apache CXF 也会生成有效的 XML 文档。但是,例 10.2 “无效的 XML 绑定消息” 中的信息将生成无效的 XML 文档。
例 10.2. 无效的 XML 绑定消息
<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 绑定消息”生成的 XML 文档无效,因为它有两个根元素: pairName
和 entryNum
。
例 10.3. 无效的 XML 文档
<pairName> Fred&Linda </pairName> <entryNum> 123 </entryNum>
如果您设置了 rootNode
属性,如 例 10.4 “带有 rootNode 设置的 XML 绑定” Apache CXF 所示,将在指定的根元素中嵌套元素。在本例中,rootNode
属性是针对整个绑定定义的,并指定根元素的名称为 entrants。
例 10.4. 带有 rootNode 设置的 XML 绑定
<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 属性设置
您还可以为每个单个消息设置 rootNode
属性,或者使用消息绑定中的 xformat:body
元素覆盖特定消息的全局设置。例如: 如果您希望 例 10.4 “带有 rootNode 设置的 XML 绑定” 中定义的输出消息具有与输入消息不同的根元素,您可以覆盖绑定的根元素,如 例 10.6 “Using xformat:body
” 所示。
例 10.6. Using 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 服务传输
这部分论述了如何在 WSDL 文档中添加 Apache CXF 传输。
第 11 章 了解 WSDL 中的如何定义端点
摘要
端点表示实例化服务。它们通过将绑定和用于公开端点的网络详情组合来定义。
概述
端点可以被视为服务的物理清单。它组合了一个绑定,用于指定由服务使用的逻辑数据的物理表示,以及一组网络详情,用于定义用于使服务可被其他端点联系的物理连接详情。
CXF 提供程序是 CXF 消费者的服务器,对应于客户端。如果您使用 CXF (camel-cxf
)组件作为路由中的起始端点,则端点同时是 Camel consumer 和 CXF 供应商。如果您使用 Camel CXF 组件,作为路由中的端点,则端点都是 Camel producer 和 CXF consumer。
端点和服务
与绑定只能映射单个接口一样,端点只能映射到单个服务。不过,服务可以通过任意数量的端点进行描述。例如,您可以定义一个由四个不同端点的清单销售服务。但是,您无法使用一个端点来记录一个 ticket 销售服务和一个小部件销售服务。
WSDL 元素
端点利用 WSDL 服务
元素和 WSDL 端口
元素的组合在合同中定义。service
元素是相关端口元素 的集合
。端口
元素定义实际的端点。
WSDL 服务
元素具有一个属性,名为,用于指定唯一名称。service
元素用作相关端口元素集合的父 元素
。WSDL 没有有关 端口
元素的规范。您可以以任何方式关联 端口
元素。
WSDL 端口
元素具有一个 绑定
属性,用于指定端点使用的绑定,它引用 wsdl:binding
元素。它还包括 name
属性,这是在所有端口之间提供唯一名称的强制属性。port
元素是元素的父元素,用于指定端点使用的实际传输详细信息。以下部分讨论用于指定传输详情的元素。
在合同中添加端点
Apache CXF 提供命令行工具,可以生成用于预定义服务接口和绑定组合的端点。
这些工具将为您的合同添加正确的元素。但是,建议您了解定义端点工作时使用的不同传输方式。
您也可以使用任何文本编辑器向合同中添加端点。当您手动编辑合同时,您需要确保合同有效。
支持的传输
端点定义是使用为 Apache CXF 支持的每个传输的扩展而定义的扩展。这包括以下传输:
- HTTP
- CORBA
- Java 消息传递服务
第 12 章 使用 HTTP
摘要
HTTP 是 Web 的底层传输。它为在端点之间进行通信提供了一个标准化、强大且灵活的平台。因为这些因素是假定为大多数 WS-* 规格的传输,是 RESTful 架构不可或缺的。
12.1. 添加基本 HTTP 端点
其它 HTTP 运行时
Apache CXF 支持以下替代 HTTP 运行时实现:
- Undertow,在 第 12.4 节 “配置 Undertow 运行时” 中进行了详细介绍。
- Netty,在 第 12.5 节 “配置 Netty 运行时” 中进行了详细介绍。
Netty HTTP URL
通常,HTTP 端点使用,每当类路径中包含 HTTP 运行时(Undertow 或 Netty)中。如果类路径上同时包含 Undertow 运行时和 Netty 运行时,则需要在希望使用 Netty 运行时明确指定,因为默认情况下将使用 Undertow 运行时。
如果类路径上有多个 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 地址
元素来指定端点的地址。它具有一个属性,即 location
,它将端点的地址指定为 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 地址
元素来指定端点的地址。它具有一个属性,即 location
,它将端点的地址指定为 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 地址
元素来指定端点的地址。它具有一个属性,即 location
,它将端点的地址指定为 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. 配置一个消费者
12.2.1. HTTP Consumer Endpoints 的机制
HTTP 消费者端点可以指定很多 HTTP 连接属性,包括端点是否自动接受重定向响应,端点是否可以使用块,端点是否会请求持久的,端点如何与代理交互。除了 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 consumer 端点。http-conf:conduit
元素使用单个属性名称,用于指定与端点对应的 WSDL 端口
元素。name
属性的值采用 portQName'.http-conduit' 的形式。例 12.5 “http-conf:conduit
Element” 显示 http-conf:conduit
元素,用于为 WSDL 片段 < port binding="widgetSOAPBinding" name="widgetSOAPPort&
gt; 指定的端点添加配置。
例 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 Consumer Endpoint 的元素” 中进行了说明。
element | 描述 |
---|---|
| 指定 HTTP 连接属性,如超时、保留请求、内容类型等。请参阅 “client 元素”一节。 |
指定用于配置端点预先使用的基本身份验证方法的参数。首选的方法是提供 | |
指定用于为传出 HTTP 代理服务器配置基本身份验证的参数。 | |
指定用于配置 SSL/TLS 的参数。 | |
指定提供端点使用的基本身份验证信息的对象 bean 引用或类名称,可抢占或响应 401 HTTP 质询。 | |
指定对象的 bean 引用或类名称,用于检查 HTTP (S) |
client 元素
http-conf:client
元素用于配置消费者端点 HTTP 连接的非安全属性。其属性(如 表 12.2 “HTTP Consumer Configuration Attributes” 所述)指定连接的属性。
属性 | 描述 |
---|---|
指定消费者在连接超时前尝试建立连接的时间长度(以毫秒为单位)。默认值为
| |
指定消费者在超时前等待响应的时间长度(以毫秒为单位)。默认值为
| |
指定消费者是否会自动遵循服务器发出的重定向。默认值为 | |
指定消费者要重新传输请求以满足重定向的次数上限。默认值为 | |
指定消费者是否使用块发送请求。默认值为 如果以下条件之一为 true,则无法使用块:
在这两种情况下, | |
指定消费者准备处理哪些媒体类型。该值用作 HTTP | |
指定接收响应时使用者喜欢的语言(例如,美国英语)。该值用作 HTTP 语言标签由标准(ISO)国际组织规定,通常通过组合语言代码(由 ISO-639 标准决定)和国家/地区代码(由 ISO-3166 标准决定)由 ISO-3166 标准决定,由连字符分开。例如,De-US 代表美国英语。 | |
指定消费者已准备好处理的内容编码。内容编码标签由互联网编号授权机构(IANA)规定。该值用作 HTTP | |
指定消息正文中发送数据的介质类型。介质类型使用多用途的互联网邮件扩展(MIME)类型来指定。该值用作 HTTP
对于 Web 服务,这应设置为 | |
指定请求被调用的资源的互联网主机和端口号。该值用作 HTTP 通常不需要此属性。只有某些 DNS 场景或应用程序设计才需要它。例如,它指示了集群客户端首选的主机(即,用于虚拟服务器映射到相同的互联网协议(IP)地址)。 | |
指定在每个请求/响应对话框后,是否保持打开或关闭特定连接。有两个有效值:
| |
指定有关通过链中涉及缓存的缓存遵守行为的指令,这些指令由来自消费者到服务提供商的请求组成。请参阅 第 12.2.4 节 “消费者缓存控制指令”。 | |
指定与所有请求一起发送的静态 Cookie。 | |
指定请求源自的浏览器的信息。在 World Wide Web consortium (W3C)的 HTTP 规格中,这也被称为 user-agent。某些服务器根据发送请求的客户端进行优化。 | |
指定定向到消费者在特定服务上发出请求的资源的 URL。该值用作 HTTP 推荐 当请求是浏览器用户点击超链接而不是输入 URL 时,会使用此 HTTP 属性。这可允许服务器根据之前的任务流优化处理,并为日志、优化缓存、跟踪过时或错误类型链路等目的生成后端链接列表。但是,它通常在 Web 服务应用程序中使用。
如果 | |
指定在一个单独的 provider→consumer 连接中接收响应的分离端点的 URL。有关使用分离端点的更多信息,请参阅 第 12.6 节 “在拒绝模式中使用 HTTP 传输”。 您必须配置使用者端点和服务供应商端点,以使用 WS-Addressing 分离端点才能工作。 | |
指定路由请求的代理服务器的 URL。 | |
指定路由请求的代理服务器的端口号。 | |
指定用于路由请求的代理服务器的类型。有效值为:
|
示例
例 12.6 “HTTP Consumer Endpoint 配置” 显示要保持与请求间打开的 HTTP 消费者端点的配置,该端点只会在每次调用一次重新传输请求,且无法使用块流。
例 12.6. HTTP Consumer Endpoint 配置
<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 元素的命名空间” 中显示的行添加到端点 WSDL 文档中的 定义
元素中。
例 12.7. HTTP Consumer WSDL 元素的命名空间
<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 端口
元素的子级。它具有与配置文件中使用的 client
元素相同的属性。属性在 表 12.2 “HTTP Consumer Configuration Attributes” 中描述。
示例
例 12.8 “WSDL 配置 HTTP Consumer 端点” 显示 WSDL 片段,用于配置 HTTP 消费者端点来指定它与缓存交互。
例 12.8. WSDL 配置 HTTP Consumer 端点
<service ... > <port ... > <soap:address ... /> <http-conf:client CacheControl="no-cache" /> </port> </service>
12.2.4. 消费者缓存控制指令
表 12.3 “http-conf:client
Cache Control Directives” 列出 HTTP 使用者支持的缓存控制指令。
指令 | 行为 |
---|---|
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 配置命名空间” 中显示的行添加到端点配置文件的 Bean
元素中。另外,您必须将配置元素的命名空间添加到 xsi:schemaLocation
属性中。
例 12.9. HTTP Provider 配置命名空间
<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
> 指定的端点配置。
例 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 服务提供商端点的元素” 中进行了说明。
element | 描述 |
---|---|
指定 HTTP 连接属性。请参阅 “server 元素”一节。 | |
指定配置上下文匹配策略以处理 HTTP 请求的参数。 | |
指定此目的地处理的 HTTP 请求的参数顺序是否已解决。 |
server 元素
http-conf:server
元素用于配置服务提供商端点的 HTTP 连接的属性。其属性(如 表 12.5 “HTTP 服务提供商配置属性” 所述)指定连接的属性。
属性 | 描述 |
---|---|
设定在连接超时前尝试接收请求的时间长度(以毫秒为单位)。默认值为
| |
指定在收到请求时遇到错误时是否会出现异常。默认值为 | |
指定在向消费者发送响应时遇到错误时要抛出异常。默认值为 | |
指定在发送响应后,服务提供商是否遵循要保持打开的连接的请求。默认值为 | |
如果客户端请求中指定的 URL 不再适合于请求资源,则指定客户端请求的 URL 应该重定向到该 URL。在这种情况下,如果服务器响应的第一行中没有自动设置状态代码,则状态代码被设置为 302,状态描述设置为 Object Moved。该值用作 HTTP RedirectURL 属性的值。 | |
指定有关通过链中涉及缓存的缓存遵守行为的指令,将来自服务提供商的响应组成到消费者。请参阅 第 12.3.4 节 “服务提供商缓存控制指令”。 | |
设置响应中发送的资源的 URL。 | |
指定响应中发送的信息的介质类型。介质类型使用多用途的互联网邮件扩展(MIME)类型来指定。该值用作 HTTP ContentType 位置的值。 | |
指定任何已应用于服务提供商发送的信息的额外内容编码。内容编码标签由互联网编号授权机构(IANA)规定。可能的内容编码值包括 zip、gzip、压缩、deflate 和 identity。这个值被用作 HTTP ContentEncoding 属性的值。 内容编码的主要用途是允许使用一些编码机制(如 zip 或 gzip)来压缩文档。Apache CXF 对内容编码没有验证。用户负责确保在应用程序级别支持指定的内容编码。 | |
指定发送响应的服务器类型。值采用 |
示例
例 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 元素的命名空间” 中显示的行添加到端点 WSDL 文档中的 定义
元素中。
例 12.12. HTTP Provider WSDL 元素的命名空间
<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 端口
元素的子级。它具有与配置文件中使用的 server
元素相同的属性。属性在 表 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:server
Cache Control Directives” 列出 HTTP 服务提供商支持的缓存控制指令。
指令 | 行为 |
---|---|
no-cache | 缓存无法使用特定的响应来满足后续请求,而不必先评估服务器响应。如果使用此值指定特定的响应标头字段,则限制仅适用于响应中的这些标头字段。如果没有指定响应标头字段,这个限制将应用到整个响应。 |
public | 任何缓存都可以存储响应。 |
private | 公共(共享)缓存无法存储响应,因为响应适用于单个用户。如果使用此值指定特定的响应标头字段,则限制仅适用于响应中的这些标头字段。如果没有指定响应标头字段,这个限制将应用到整个响应。 |
no-store | 缓存不得存储响应的任何部分或调用它的请求的任何部分。 |
no-transform | 缓存不得在服务器和客户端之间响应中修改内容的介质类型或位置。 |
must-revalidate | 缓存必须重新验证与响应相关的过期条目,然后才能在随后的响应中使用该条目。 |
proxy-revalidate | 与 must-revalidate 相同的操作,除了只能在共享缓存上强制执行,并由私有非共享缓存忽略。当使用这个指令时,必须使用公共 cache 指令。 |
max-age | 客户端可以接受其年龄不会超过指定秒数的响应。 |
s-max-age | 与 max-age 相同的操作,只是只能在共享缓存中强制使用,并由私有非共享缓存忽略。s-max-age 指定的年龄会覆盖 max-age 指定的年龄。当使用这个指令时,还必须使用 proxy-revalidate 指令。 |
cache-extension | 指定其他缓存指令的额外扩展。扩展可以是信息或行为。在标准指令上下文中指定了扩展指令,以便不了解扩展指令的应用程序可以遵循标准 指令强制的行为。 |
12.4. 配置 Undertow 运行时
概述
HTTP 服务供应商和 HTTP 使用者使用 Undertow 运行时,利用分离的端点。可以配置运行时的线程池,您也可以通过 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 运行时工厂元素” 中。
element | 描述 |
---|---|
| 指定特定 Undertow 运行时实例的配置。请参阅 “engine 元素”一节。 |
指定用于保护 HTTP 服务提供商的可重用属性集。它有一个属性 | |
指定用于控制 Undertow 实例的线程池的一组可重复使用的属性。它有一个属性 请参阅 “配置线程池”一节。 |
engine 元素
httpu:engine
元素用于配置 Undertow 运行时的特定实例。它有一个属性 port
,用于指定由 Undertow 实例管理的端口数量。
您可以为 port
属性指定 0
值。httpu:engine
元素中指定的任何线程属性(其 port
属性设置为 0)都用作未明确配置的 Undertow 侦听器的配置。
每个 httpu:engine
元素都可以具有两个子项:一个用于配置安全属性,另一个用于配置 Undertow 实例的线程池。对于每种配置,您可以直接提供配置信息,也可以提供对父 httpu:engine-factory
元素中定义的一组配置属性的引用。
表 12.8 “配置 Undertow 运行时实例的元素” 描述用于提供配置属性的子元素。
element | 描述 |
---|---|
指定一组属性,以配置用于特定 Undertow 实例的安全性。 | |
指的是由 | |
指定特定 Undertow 实例使用的线程池的大小。请参阅 “配置线程池”一节。 | |
是指由 |
配置线程池
您可以通过以下任一方式配置 Undertow 实例的线程池的大小:
-
使用
engine-factory
元素中的identifiedThreadingParameters
元素指定线程池的大小。然后,您可以使用threadingParametersRef
元素来引用这个元素。 -
使用
threadingParameters
元素直接指定线程池的大小。
threadingParameters
有两个属性来指定线程池的大小。属性在 表 12.9 “配置 Undertow 线程池的属性” 中描述。
httpu:identifiedThreadingParameters
元素具有单个子 线程Parameters
元素。
属性 | 描述 |
---|---|
指定 worker 要创建的 I/O 线程数量。如果没有指定,则会选择 dafult 值。默认值为每个 CPU 内核的一个 I/O 线程。 | |
指定 Undertow 实例可用于处理请求的线程数量最少。 | |
指定 Undertow 实例可用于处理请求的线程数上限。 |
示例
例 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>
12.5. 配置 Netty 运行时
概述
HTTP 服务供应商和 HTTP 用户使用 Netty 运行时,使用分离的端点。可以配置运行时的线程池,您还可以通过 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.16 “Netty Runtime Configuration 命名空间” 中显示的行添加到端点配置文件的 Bean
元素中。另外,您必须将配置元素的命名空间添加到 xsi:schemaLocation
属性中。
例 12.16. Netty Runtime Configuration 命名空间
<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 运行时的根元素。它具有单个必需属性 总线
,其值是管理所配置的 Netty 实例的 总线
的名称。
该值通常是 cxf
,这是默认 总线实例的名称
。
httpn:engine-factory
元素有三个子项,其中包含用于配置由 Netty 运行时工厂实例化的 HTTP 端口的信息。子项包括在 表 12.10 “配置 Netty Runtime Factory 的元素” 中。
element | 描述 |
---|---|
| 指定特定 Netty 运行时实例的配置。请参阅 “engine 元素”一节。 |
指定用于保护 HTTP 服务提供商的可重用属性集。它有一个属性 | |
指定控制 Netty 实例的线程池的可重用属性集合。它有一个属性 请参阅 “配置线程池”一节。 |
engine 元素
httpn:engine
元素用于配置 Netty 运行时的特定实例。表 12.11 “配置 Netty Runtime 实例的属性” 显示 httpn:engine
元素支持的属性。
属性 | 描述 |
---|---|
|
指定 Netty HTTP 服务器实例使用的端口。您可以为 port 属性指定 |
| 指定 Netty HTTP 服务器实例使用的侦听地址。该值可以是主机名或 IP 地址。如果没有指定,Netty HTTP 服务器将侦听所有本地地址。 |
| 指定 Netty 连接的最大读时时间。每当对底层流有任何读取操作时,会重置计时器。 |
| 指定 Netty 连接的最大写入空闲时间。每当对底层流有任何写入操作时,会重置计时器。 |
| 指定 Netty 连接的最大聚合内容大小。默认值为 10MB。 |
httpn:engine
元素具有一个用于配置安全属性的子元素,以及用于配置 Netty 实例的线程池的一个子元素。对于每种配置,您可以直接提供配置信息,也可以提供对父 httpn:engine-factory
元素中定义的一组配置属性的引用。
httpn:engine
支持的子元素显示在 表 12.12 “配置 Netty Runtime 实例元素” 中。
element | 描述 |
---|---|
指定一组属性,用于配置用于特定 Netty 实例的安全性。 | |
指的是由 | |
指定特定 Netty 实例使用的线程池的大小。请参阅 “配置线程池”一节。 | |
是指由 | |
|
当 |
|
指定设置 |
配置线程池
您可以通过以下任一方式配置 Netty 实例的线程池的大小:
-
使用
engine-factory
元素中的identifiedThreadingParameters
元素指定线程池的大小。然后,您可以使用threadingParametersRef
元素来引用这个元素。 -
使用
threadingParameters
元素直接指定线程池的大小。
threadingParameters
元素有一个属性来指定线程池的大小,如 表 12.13 “配置 Netty Thread Pool 的属性” 所述。
httpn:identifiedThreadingParameters
元素具有单个子 线程Parameters
元素。
属性 | 描述 |
---|---|
| 指定 Netty 实例用于处理请求的线程数量。 |
示例
例 12.17 “配置 Netty 实例” 显示配置片段,用于配置各种 Netty 端口。
例 12.17. 配置 Netty 实例
<?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 传输需要进行以下操作:
将使用者配置为使用 WS-Addressing。
将使用者配置为使用分离的端点。
请参阅 “配置使用者”一节。
配置消费者与 交互的任何服务提供商,以使用 WS-Addressing。
配置端点以使用 WS-Addressing
指定消费者以及使用 WS-Addressing 的任何服务提供商。
您可以通过以下两种方式之一指定端点使用 WS-Addressing:
将
wswa:UsingAddressing
元素添加到端点的 WSDL端口
元素中,如 例 12.18 “使用 WSDL 激活 WS-Address” 所示。例 12.18. 使用 WSDL 激活 WS-Address
... <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.19 “使用策略激活 WS-Addressing” 所示。例 12.19. 使用策略激活 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.20 “将消费者配置为使用 Decoupled HTTP 端点” 显示设置 例 12.18 “使用 WSDL 激活 WS-Address” 中定义的端点的配置,以使用分离的端点。现在,消费者在 http://widgetvendor.net/widgetSellerInbox 接收所有响应。
例 12.20. 将消费者配置为使用 Decoupled 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 传输的消息流
请求会启动以下过程:
- 使用者实施调用操作,并且生成请求消息。
WS-Addressing 层将 WS-A 标头添加到消息。
当在消费者配置中指定分离端点时,分离的端点的地址将放入 WS-A ReplyTo 标头中。
- 消息发送到服务提供程序。
- 服务提供商接收消息。
- 来自消费者的请求消息被分配到供应商的 WS-A 层。
- 因为 WS-A ReplyTo 标头没有设置为 anonymous,因此该提供程序将 HTTP 状态代码发回为 202,确认已收到该请求。
- HTTP 层使用原始连接的 back-channel 将 202 Accepted 消息发回到使用者。
使用者接收了用于发送原始消息的 HTTP 连接的 202 Accepted reply。
当消费者收到 202 Accepted 回复时,HTTP 连接会关闭。
- 该请求将传递到处理请求的服务提供商的实施。
- 当响应就绪时,它将被分配给 WS-A 层。
- WS-A 层将 WS-Addressing 标头添加到响应消息。
- HTTP 传输将响应发送到消费者的分离端点。
- 消费者的分离端点从服务提供商接收响应。
- 响应被分配到消费者的 WS-A 层,使用 WS-AlatesTo 标头将其与正确的请求关联。
- 相关响应返回给客户端实施,调用调用将被取消阻塞。
第 13 章 使用 SOAP Over JMS
摘要
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 由全球 Wide Web Consortium (W3C)定义为为大部分服务使用的自定义ary SOAP/HTTP 协议提供更可靠的传输层的方法。Apache CXF 实现与规范完全兼容,并且应与还合规的任何框架兼容。
此传输使用 JNDI 来查找 JMS 目的地。调用操作时,该请求将打包为 SOAP 消息,并在 JMS 消息的正文中发送到指定的目的地。
使用 SOAP/JMS 传输:
- 指定传输类型是 SOAP/JMS。
- 使用 JMS URI 指定目标目的地。
- 另外,还可配置 JNDI 连接。
- (可选)添加额外的 JMS 配置。
指定 JMS 传输类型
您会将 SOAP 绑定配置为在指定 WSDL 绑定时使用 JMS 传输。您可以将 soap:binding
元素的 transport
属性设置为 http://www.w3.org/2010/soapjms/
。例 13.1 “使用 JMS 绑定规格的 SOAP” 显示使用 SOAP/JMS 的 WSDL 绑定。
例 13.1. 使用 JMS 绑定规格的 SOAP
<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 URI,如 JMS 1.0 的 URI Scheme 中定义的。例 13.2 “JMS URI 语法” 显示 JMS URI 的语法。
例 13.2. JMS URI 语法
jms:variant:destination?options
表 13.1 “JMS URI 变体” 描述 JMS URI 的可用变体。
变体 | 描述 |
---|---|
jndi | 指定目的地名称是 JNDI 队列名称。使用这种变体时,您必须提供用于访问 JNDI 供应商的配置。 |
jndi-topic | 指定目的地名称是 JNDI 主题名称。使用这种变体时,您必须提供用于访问 JNDI 供应商的配置。 |
队列 |
指定目的地是使用 JMS 解析的队列名称。提供的字符串传递到 |
topic |
指定目的地是使用 JMS 解析的主题名称。提供的字符串传递到 |
JMS URI 的选项 部分用于配置传输,并在 第 13.2 节 “JMS URI” 中进行讨论。
例 13.3 “SOAP/JMS 端点地址” 显示用于使用 JNDI 检查目标目的地的 SOAP/JMS 端点的 WSDL 端口条目。
例 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 也可用于配置 JMS 连接,方法是在 URI 中附加一个或多个选项。这些选项在 IETF 标准中详述,Java Message Service 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 选项。
属性 | 默认 | 描述 |
---|---|---|
| [可选] 是一个字符串值,前缀为 conduit 创建的所有关联 ID。选择器可以使用它来监听回复。 | |
|
|
指定是否使用 JMS |
| [可选] 指定连接的客户端标识符。此属性用于将连接与提供程序代表客户端维护的状态相关联。这可让带有同一身份的后续订阅者恢复其前面订阅的状态。 | |
| [可选] 指定订阅的名称。 | |
|
| 指定 CXF 使用的 JMS 消息类型。有效值为:
|
| [可选] 指定创建连接的密码。不建议将此属性附加到 URI。 | |
|
| 指定 JMS 消息优先级,范围从 0 (最低)到 9 (最高)。 |
|
| 指定时间,以毫秒为单位,在使用请求/重新交换时,客户端会等待回复。 |
|
| [弃用在 CXF 3.0] 中,指定在出现异常时传输是否应重新连接。 从 3.0 开始,传输会在异常发生时始终重新连接。 |
|
[可选] 指定队列消息的回复目的地。回复目的地会出现在 此属性的值根据 JMS URI 中指定的变体进行解释:
| |
|
| 指定事务类型。有效值为:
|
|
|
指定 JMS 提供程序丢弃消息的时间(以毫秒为单位)。 |
| [可选] 指定主题消息的回复目的地。此属性的值根据 JMS URI 中指定的变体进行解释:
| |
|
| 指定 conduit 的 UUID 将用作所有关联 ID 的前缀。
由于所有 conduit 都分配有唯一 UUID,请将此属性设置为 |
| [可选] 指定用于创建连接的用户名。 |
JNDI 属性
表 13.3 “JNDI 属性 settable 作为 URI 选项” 显示可用于配置此端点 JNDI 的 URI 选项。
属性 | 描述 |
---|---|
| 指定 JMS 连接工厂的 JNDI 名称。 |
|
指定 JNDI 提供程序的完全限定 Java 类名称(必须是 |
|
指定在 Spring、Blueprint 或 JNDI 中搜索的 JTA 事务管理器的名称。如果找到事务管理器,将启用 JTA 事务。请参阅 |
|
指定初始化 JNDI 供应商的 URL。等同于设置 |
其他 JNDI 属性
属性 java.naming.factory.initial
和 java.naming.provider.url
是标准属性,这是初始化任何 JNDI 提供程序所必需的。但有些时候,JNDI 供应商除标准供应商外还可能支持自定义属性。在这种情况下,您可以通过设置 jndi-PropertyName
格式的 URI 选项来设置任意 JNDI 属性。
例如,如果您使用 SUN 的 LDAP 实施 JNDI,您可以设置 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 属性 settable 作为 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 标准 发布()
方法无法用于发布 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 扩展元素。
element | 默认 | 描述 |
---|---|---|
|
指定 JNDI 提供程序的完全限定 Java 类名称。等同于设置 | |
|
指定初始化 JNDI 供应商的 URL。等同于设置 | |
|
指定用于创建 JNDI | |
| 指定 JMS 连接工厂的 JNDI 名称。 | |
|
|
指定是否使用 JMS |
|
[可选] 指定队列消息的回复目的地。回复目的地会出现在 此属性的值根据 JMS URI 中指定的变体进行解释:
| |
|
| 指定 JMS 消息优先级,范围从 0 (最低)到 9 (最高)。 |
|
|
JMS 提供程序丢弃消息的时间(以毫秒为单位)。 |
配置范围
WSDL 合同中的 WSDL 元素会影响对合同中定义的端点更改的范围。SOAP/JMS WSDL 元素可以放在 wsdl: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 交付方式设置为非持久性,并将每条消息设置为 live (一分钟)。
指定目标目的地。
配置 JMS 传输,以便回复消息在greeter Reply.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 提供程序,并与通过 TextMessage
或 ByteMessage
交换 JMS 消息的应用程序一起工作。
启用和配置 JMS 传输方法有两种:
14.2. 使用 JMS 配置 bean
概述
为简化 JMS 配置并使其强大,Apache CXF 使用单一 JMS 配置 Bean 配置 JMS 端点。bean 通过 org.apache.cxf.transport.jms.JMSConfiguration
类来实施。它可用于直接配置端点,或者配置 JMS conduits 和目的地。
配置命名空间
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>
指定配置
您可以通过定义 bean 类 org.apache.cxf.transport.jms.JMSConfiguration
来指定 JMS 配置。Bean 的属性提供传输的配置设置。
在 CXF 3.0 中,JMS 传输不再依赖于 Spring JMS,因此删除了一些 Spring JMS 相关的选项。
表 14.1 “常规 JMS 配置属性” 列出提供商和消费者常用的属性。
属性 | 默认 | 描述 |
---|---|---|
| [required] 指定定义 JMS ConnectionFactory 的 bean 的引用。 | |
|
| 在 CXF 3.0 中删除
pre CXF 3.0 指定是否将 ConnectionFactory 替换为 Spring
在使用不含池连接的 ConnectionFactory 时启用此属性,因为它将提高 JMS 传输的性能。因此,因为 JMS 传输为每个消息创建一个新连接,并且 |
|
| 在 CXF 3.0 CXF 中已弃用,总是在异常时重新连接。 pre CXF 3.0 指定在出现异常时是否创建新连接。
使用 Spring
|
| 指定目的地的 JNDI 名称或特定于提供程序的名称。 | |
| 指定发送回复的 JMS 目的地的 JMS 名称。此属性允许使用用户定义的目的地进行回复。详情请查看 第 14.6 节 “使用 Named Reply Destination”。 | |
| DynamicDestinationResolver |
指定 Spring 通过此属性,您可以定义目标名称如何解析为 JMS 目的地。有效值为:
|
| 指定 Spring 事务管理器的引用。这使得该服务能够参与 JTA 事务。 | |
|
| 在 CXF 3.0 中删除 pre CXF 3.0 指定对 Spring TaskExecutor 的引用。这用于监听器来确定如何处理传入的信息。 |
|
| 在 CXF 3.0 中删除,CXF 3.0 仅支持 JMS 1.1 功能。 pre CXF 3.0 指定是否使用 JMS 1.1 功能。有效值为:
|
|
| 在 CXF 3.0 中删除 pre CXF 3.0 指定 JMS 传输是否希望 JMS 代理来提供消息 ID。有效值为:
|
|
| 在 CXF 3.0 中删除 pre CXF 3.0 指定 JMS 传输是否希望 JMS 代理提供消息时间戳。有效值为:
|
|
| 在 CXF 3.0 中删除 pre CXF 3.0 指定 JMS 侦听器容器可以应用的缓存级别。有效值为:
|
|
| 指定在使用主题时是否接收您自己的消息。
|
|
| 指定响应消息的时间(毫秒)。 |
|
|
指定是否明确为每条消息( |
|
| 指定消息是否持久。有效值为:
|
|
|
指定消息优先级。JMS 优先级值范围从 |
|
| 在丢弃了消息之前,以毫秒为单位指定时间。 |
|
| 指定是否使用 JMS 事务。 |
|
| 在 CXF 3.0 中删除 pre CXF 3.0 指定监听器的最小并发用户数量。 |
|
| 在 CXF 3.0 中删除 pre CXF 3.0 指定监听器的最大并发用户数量。 |
| 指定用于过滤传入消息的选择器的字符串值。这个属性可让多个连接共享一个队列。如需有关用于指定消息选择器的语法的更多信息,请参阅 JMS 1.1 规范。 | |
|
| 指定服务器是否使用 durable 订阅。 |
| 指定用于注册持久订阅的名称(字符串)。 | |
|
| 指定消息数据将如何打包为 JMS 消息。有效值为:
|
|
| 指定目标目的地是主题还是一个队列。有效值为:
|
|
| 指定 JMS 提供程序是否为 Tibco EMS。
当设置为 |
|
| 在 CXF 3.0 中删除 指定 JMS 是否将使用消息 ID 来关联消息。
当设置为 |
|
| CXF 3.0 指定 JMS 目标可能具有的最大暂停数。当当前数量超过指定的最大值时,JMSListenerContainer 将停止。 |
|
|
CXF 3.0 指定在超过
当其当前暂停的延续数低于 的值时 |
如 例 14.2 “JMS 配置 bean” 所示,bean 的属性被指定为 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 功能机制直接应用于服务器和客户端端点。要做到这一点:
-
将端点的
address
属性设置为jms://
。 -
将
jaxws:feature
元素添加到端点的配置。 -
向 功能添加 bean 类型的
org.apache.cxf.transport.jms.JMSConfigFeature
。 -
将
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 conduit 中添加 JMS 配置” 显示使用 例 14.2 “JMS 配置 bean” 中的 JMS 配置的 JMS conduit。
例 14.4. 在 JMS conduit 中添加 JMS 配置
<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。因此,因为 session 和 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);
有关共用的更多信息,请参阅 Red Hat JBoss Fuse 事务指南中的"Appendix A Optimizing Performance of JMS Single- and Multiple-Resource Transactions"。
避免同步接收
对于请求/重新交换,JMS 传输会发送请求,然后等待回复。在可能的情况下,使用 JMS MessageListener
以异步方式实施请求/回复。
但是,当 CXF 需要共享端点之间的队列时,CXF 必须使用 synchronous Consumer.receive ()
方法。此场景需要 MessageListener
来使用消息选择器来过滤消息。邮件选择器必须提前已知,因此 MessageListener
只只打开一次。
应该避免避免出现消息选择器的两种情况:
当将
JMSMessageID
用作JMSCorrelationID
时如果 JMS
属性使用ConduitIdSelector
和conduitSelectorPrefix
,则客户端不会设置JMSCorrelationId
。这会导致服务器使用JMSMessageId
请求的消息作为JMSCorrelationId
。由于JMSMessageID
无法事先知道,客户端必须使用同步的Consumer.receive ()
方法。请注意,您必须将
Consumer.receive ()
方法用于 IBM JMS 端点(默认)。用户在请求消息中设置
JMStype
,然后设置自定义JMSCorrelationID
。同样,因为无法事先知道自定义
JMSCorrelationID
,客户端必须使用同步的Consumer.receive ()
方法。
因此,常规规则是避免使用需要同步接收的设置。
14.4. 配置 JMS 事务
概述
CXF 3.0 在使用单向消息传递时支持 CXF 端点上的本地 JMS 事务和 JTA 事务。
本地事务
只有在发生异常时,使用本地资源的事务才会回滚 JMS 消息。它们不会直接协调其他资源,如数据库事务。
要设置本地事务,请将端点配置为您通常会将属性 sessionTrasnsacted
设置为 true
。
有关事务和池的更多信息,请参阅 Red Hat JBoss Fuse 事务指南。
JTA 事务
使用 JTA 事务时,您可以协调任意数量的 XA 资源。如果为 JTA 事务配置了 CXF 端点,它会在调用服务实施前启动事务。如果没有异常,交易将被提交。否则,它将回滚。
在 JTA 事务中,使用 JMS 消息并写入数据库的数据。发生异常时,两个资源都会回滚,因此信息会被消耗,并且数据写入数据库,或者消息将被回滚,数据也不会写入数据库。
配置 JTA 事务需要两个步骤:
定义事务管理器
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 中查找事务管理器。
配置 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,其 idConnectionFactory
。注意
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 端点属性” 中。
属性 | 描述 |
---|---|
指定 JMS 目的地是否为 JMS 队列或 JMS 主题。 | |
指定连接到 JMS 目的地时要使用的 JMS 连接工厂的 JNDI 名称。 | |
指定发送到请求的 JMS 目的地的 JMS 名称。 | |
指定发送回复的 JMS 目的地的 JMS 名称。此属性允许您使用定义的用户定义的目的地进行回复。详情请查看 第 14.6 节 “使用 Named Reply Destination”。 | |
指定 JNDI 名称,绑定到发送到请求的 JMS 目标。 | |
指定绑定到发送回复的 JMS 目的地的 JNDI 名称。此属性允许您使用定义的用户定义的目的地进行回复。详情请查看 第 14.6 节 “使用 Named Reply Destination”。 | |
指定连接到 JMS 代理时要使用的用户名。 | |
指定连接到 JMS 代理时使用的密码。 |
jms:address
WSDL 元素使用 jms:JMSNamingProperties
子元素来指定连接到 JNDI 提供程序所需的其他信息。
指定 JNDI 属性
为增加与 JMS 和 JNDI 提供程序的互操作性,jms:address
元素具有一个子元素,jms:JMSNamingProperties
,允许您指定用于连接 JNDI 提供程序时所用的属性的值。jms:JMSNamingProperties
元素有两个属性: name
和 value
。name
指定要设置的属性的名称。value
属性指定指定属性的值。JMS:JMSNamingProperties
元素也可用于规范提供程序特定的属性。
下表列出了可以设置的常见 JNDI 属性:
-
java.naming.factory.initial
-
java.naming.provider.url
-
java.naming.factory.object
-
java.naming.factory.state
-
java.naming.factory.url.pkgs
-
java.naming.dns.url
-
java.naming.authoritative
-
java.naming.batchsize
-
java.naming.referral
-
java.naming.security.protocol
-
java.naming.security.authentication
-
java.naming.security.principal
-
java.naming.security.credentials
-
java.naming.language
-
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
时,使用者端点使用 字节[]
作为将数据存储到 JMS 消息正文中的数据的方法。发送消息时,消息数据(包括任何格式信息)被打包成 字节[]
,并在消息正文放置之前被放入一个线路中。收到消息后,消费者端点将尝试传播消息正文中存储的数据,就像以字节 []
打包一样。
使用 TextMessage
时,使用者端点使用字符串作为消息正文中存储和检索数据的方法。发送消息时,消息信息(包括任何格式特定信息)将转换为字符串并放入 JMS 消息正文。当收到消息时,消费者端点将尝试推断 JMS 消息正文中存储的数据,就如同它被打包成一个字符串一样。
当原生 JMS 应用与 Apache CXF 用户交互时,JMS 应用负责解读消息和格式化信息。例如,如果 Apache CXF 合同指定用于 JMS 端点的绑定是 SOAP,并且消息被打包为 TextMessage
,则接收的 JMS 应用程序将收到包含所有 SOAP envelope 信息的文本消息。
指定消息类型
JMS consumer 端点接受的消息类型使用可选的 jms:client
元素进行配置。jms:client
元素是 WSDL 端口
元素的子项,它有一个属性:
指定消息数据将如何打包为 JMS 消息。 |
示例
例 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 提供程序端点具有多种可配置行为。包括:
- 如何关联消息
- 使用 durable 订阅
- 如果服务使用本地 JMS 事务
- 端点使用的消息代理
指定配置
提供程序端点行为可通过可选 jms:server
元素进行配置。jms:server
元素是 WSDL wsdl:port
元素的子项,具有以下属性:
属性 | 描述 |
---|---|
指定 JMS 是否将使用消息 ID 来关联消息。默认值为 | |
指定用于注册持久订阅的名称。 | |
指定要使用的消息选择器的字符串值。如需有关用于指定消息选择器的语法的更多信息,请参阅 JMS 1.1 规范。 | |
指定本地 JMS 代理是否围绕消息处理创建事务。默认值为 | |
示例
例 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 配置的一部分。
设置回复目的地名称
您可以使用 jmsReplyDestinationName
属性或端点 JMS 配置中的 jndiReplyDestinationName
属性指定回复目的地。客户端端点将侦听指定目的地的回复,它将在所有传出请求的 ReplyTo
字段中指定 属性的值。如果请求的 ReplyTo
字段中没有指定目的地,则服务端点将使用 jndiReplyDestinationName
属性的值作为放置回复的位置。
示例
例 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 “用于连接到 Apache ActiveMQ 的 SOAP/JMS WSDL” 显示 SOAP/JMS WSDL 扩展以创建与 Apache ActiveMQ 集成的 JNDI InitialContext
。
例 15.1. 用于连接到 Apache ActiveMQ 的 SOAP/JMS WSDL
<soapjms:jndiInitialContextFactory> org.apache.activemq.jndi.ActiveMQInitialContextFactory </soapjms:jndiInitialContextFactory> <soapjms:jndiURL>tcp://localhost:61616</soapjms:jndiURL>
在 例 15.1 “用于连接到 Apache ActiveMQ 的 SOAP/JMS WSDL” 中,Apache ActiveMQ 客户端连接到位于 tcp://localhost:61616
的代理端口。
查找连接工厂
此外,还要创建 JNDI InitialContext
实例,您必须指定绑定到 javax.jms.ConnectionFactory
实例的 JNDI 名称。如果是 Apache ActiveMQ,则 InitialContext
实例中有一个预定义绑定,它将 JNDI 名称 ConnectionFactory
映射到 ActiveMQConnectionFactory
实例。例 15.2 “用于指定 Apache ActiveMQ 连接工厂的 SOAP/JMS WSDL” 用于指定 Apache ActiveMQ 连接工厂的 SOAP/JMS 扩展元素。
例 15.2. 用于指定 Apache ActiveMQ 连接工厂的 SOAP/JMS WSDL
<soapjms:jndiConnectionFactoryName> ConnectionFactory </soapjms:jndiConnectionFactoryName>
动态目的地的语法
要动态访问队列或主题,请将目的地的 JNDI 名称指定为 JNDI 复合名称,采用以下格式之一:
dynamicQueues/QueueName dynamicTopics/TopicName
QueueName 和 TopicName 是 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
摘要
拥塞是实施出站连接的低级传输架构。其行为和生命周期可影响系统性能和处理负载。
概述
conduits 管理 Apache CXF 运行时中的客户端侧或出站传输详情。它们负责打开端口、建立出站连接、发送消息和侦听应用与单一外部端点之间的任何响应。如果应用连接到多个端点,则每个端点将有一个 conduit 实例。
每个传输类型都使用 Conduit 接口来实施自己的 conduit。这样,在应用程序级别功能和传输之间实现了标准化接口。
通常,在配置客户端传输详细信息时,您只需要担心应用程序所使用的 conduit。运行时如何处理 conduit 的基本语义,通常是开发人员需要担心的。
但是,了解相应行为可能会有帮助的情况:
- 实施自定义传输
- 高级应用程序调整以管理有限资源
conduit 生命周期
conduits 由客户端实施对象管理。创建之后,在客户端实施对象的持续时间内保持一致。conduit 的生命周期为:
-
创建客户端实施对象时,它会获得对
ConduitSelector
对象的引用。 当客户端需要发送消息是请求对 conduit 选择器的 conduit 的引用时。
如果消息用于新端点,则 conduit 选择器会创建一个新的 conduit,并将它传递到客户端实施。否则,它会把客户端对目标端点的 conduit 的引用传递。
- 在需要时,conduit 会发送消息。
- 当客户端实施对象被销毁时,与它关联的所有行为都会被销毁。
conduit weight
conduit 对象的权重取决于传输的实现。HTTP conduits 非常轻巧。JMS conduits 非常重,因为它们与 JMS Session
对象相关联,以及一个或多个 JMSListenerContainer
对象。
部分 IV. 配置 Web 服务端点
本指南论述了如何在红帽 Fuse 中创建 Apache CXF 端点。
第 17 章 配置 JAX-WS 端点
摘要
JAX-WS 端点使用三个 Spring 配置元素之一进行配置。正确的元素取决于您要配置的端点类型以及您要使用的功能。对于使用 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.JaxWsServerFactoryBean
对象来支持端点。EndpointImpl
对象将配置数据传递给 JaxWsServerFactoryBean
对象。JaxWsServerFactoryBean
对象用于创建实际服务对象。因为任何一个配置元素都会配置服务端点,因此您可以根据您喜欢的语法进行选择。
17.1.2. 使用 jaxws:endpoint Element
概述
jaxws:endpoint
元素是配置 JAX-WS 服务提供商的默认元素。其属性和子项指定实例化服务提供商所需的所有信息。许多属性都映射到服务合同中的信息。子进程用于配置拦截器和其他高级功能。
识别正在配置的端点
要使运行时将配置应用到正确的服务提供商,它必须能够识别它。识别服务供应商的基本方法是指定实施端点的类。这可以通过使用 jaxws:endpoint
元素的 implementor
属性来完成。
对于不同端点共享常见实现的实例,可以为每个端点提供不同的配置。在配置中,有两种方法可用于区分特定端点:
serviceName
属性和endpointName
属性的组合serviceName
属性指定定义服务端点的wsdl:service
元素。endpointName
属性指定定义服务端点的特定wsdl:port
元素。这两个属性都以 QNames 指定,格式为ns:name
。ns 是元素的命名空间,name 是元素的name
属性的值。注意如果
wsdl:service
元素只有一个wsdl:port
元素,则可以省略endpointName
属性。name
属性name
属性指定定义服务端点的特定wsdl:port
元素的 QName。QName 以{ns}localPart格式提供
。ns 是wsdl:port
元素的命名空间,localPart 是wsdl:port
元素的name
属性的值。
属性
jaxws:endpoint
元素的属性配置端点的基本属性。这些属性包括端点的地址、实施端点的类,以及托管端点的 总线
。
表 17.1 “使用 jaxws:endpoint 元素配置 JAX-WS 服务提供商的属性” 描述 jaxws:endpoint
元素的属性。
属性 | 描述 |
---|---|
指定唯一标识符,其他配置元素可用于引用端点。 | |
指定实施该服务的类。您可以使用类名称或对 Spring bean 配置实施类的 ID 引用来指定实施类。此类必须在 classpath 上。 | |
指定实施该服务的类。当为 | |
指定 HTTP 端点的地址。这个值会覆盖服务合同中指定的值。 | |
指定端点 WSDL 合同的位置。WSDL 合同的位置相对于部署该服务的文件夹。 | |
指定服务的 | |
指定服务的 | |
指定是否应自动发布该服务。如果它被设置为 | |
指定 Spring bean 配置用于管理服务端点的总线的 ID。这在将多个端点配置为使用一组通用的功能时很有用。 | |
指定服务使用的消息绑定 ID。第 23 章 Apache CXF Binding ID 中提供了有效绑定 ID 列表。 | |
指定服务的 | |
指定 bean 是抽象 bean。抽象 bean 作为 concrete bean 定义的父项,它们不会被实例化。默认值为 | |
指定端点在实例化前依赖的 Bean 列表。 | |
指定使用 Apache CXF API 创建的用户,如
默认值为
把它设置为
| |
放入生成的 WSDL |
除了 表 17.1 “使用 jaxws:endpoint 元素配置 JAX-WS 服务提供商的属性” 中列出的属性外,您可能需要使用多个 xmlns:shortName
属性来声明 endpointName
和 serviceName
属性使用的命名空间。
示例
例 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
元素。这两个属性都以 QNames 指定,格式为ns:name
。ns 是元素的命名空间,name 是元素的name
属性的值。注意如果
wsdl:service
元素只有一个wsdl:port
元素,则可以省略endpointName
属性。name
属性name
属性指定定义服务端点的特定wsdl:port
元素的 QName。QName 以{ns}localPart格式提供
。ns 是wsdl:port
元素的命名空间,localPart 是wsdl:port
元素的name
属性的值。
属性
jaxws:server
元素的属性配置端点的基本属性。这些属性包括端点的地址、实施端点的类,以及托管端点的 总线
。
表 17.2 “使用 jaxws:server 元素配置 JAX-WS 服务提供商的属性” 描述 jaxws:server
元素的属性。
属性 | 描述 |
---|---|
指定唯一标识符,其他配置元素可用于引用端点。 | |
指定实施该服务的类。您可以使用类名称或对 Spring bean 配置实施类的 ID 引用来指定实施类。此类必须在 classpath 上。 | |
指定实施该服务的类。当为 | |
指定 HTTP 端点的地址。这个值将覆盖服务合同中指定的值。 | |
指定端点 WSDL 合同的位置。WSDL 合同的位置相对于部署该服务的文件夹。 | |
指定服务的 | |
指定服务的 | |
指定是否应自动发布该服务。如果它被设置为 | |
指定 Spring bean 配置用于管理服务端点的总线的 ID。这在将多个端点配置为使用一组通用的功能时很有用。 | |
指定服务使用的消息绑定 ID。第 23 章 Apache CXF Binding ID 中提供了有效绑定 ID 列表。 | |
指定服务的 | |
指定 bean 是抽象 bean。抽象 bean 作为 concrete bean 定义的父项,它们不会被实例化。默认值为 | |
指定端点在实例化端点之前实例化的 Bean 列表。 | |
指定使用 Apache CXF API 创建的用户,如
默认值为
把它设置为
|
除了 表 17.2 “使用 jaxws:server 元素配置 JAX-WS 服务提供商的属性” 中列出的属性外,您可能需要使用多个 xmlns:shortName
属性来声明 endpointName
和 serviceName
属性使用的命名空间。
示例
例 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:endpoint
和 jaxws:server
元素提供实例化服务提供商所需的基本配置信息。要为您的服务提供商添加功能或执行高级配置,您必须在配置中添加子元素。
通过子元素,您可以执行以下操作:
元素
表 17.3 “用于配置 JAX-WS 服务提供程序的元素” 描述 jaxws:endpoint
支持的子元素。
element | 描述 |
---|---|
指定用于处理消息的 JAX-WS 处理程序列表。有关 JAX-WS 处理程序实施的更多信息,请参阅 第 43 章 编写处理程序。 | |
指定处理入站请求的拦截器列表。更多信息请参阅 第 VII 部分 “开发 Apache CXF Interceptors”。 | |
指定处理入站错误信息的拦截器列表。更多信息请参阅 第 VII 部分 “开发 Apache CXF Interceptors”。 | |
指定处理出站回复的拦截器列表。更多信息请参阅 第 VII 部分 “开发 Apache CXF Interceptors”。 | |
指定处理出站错误消息的拦截器列表。更多信息请参阅 第 VII 部分 “开发 Apache CXF Interceptors”。 | |
指定 bean 配置端点使用的消息绑定。使用 | |
| 指定实施端点使用的数据绑定的类。这可以通过一个嵌入式 bean 定义来指定。 |
指定用于该服务的 Java executor。这可以通过一个嵌入式 bean 定义来指定。 | |
指定配置 Apache CXF 高级功能的 Bean 列表。您可以提供 bean 参考列表或嵌入式 Bean 列表。 | |
指定服务使用的 org.apache.cxf.service.Invoker 接口的实施。[c] | |
指定传递给端点的属性的 Spring 映射。这些属性可用于控制启用 MTOM 支持等功能。 | |
指定用来实例化该服务的 | |
[a]
SOAP 绑定使用 soap:soapBinding bean 配置。
[c]
Invoker 实施控制如何调用服务。例如,它控制每个请求是否由服务实施的新实例处理,或者是否在调用期间保留状态。
|
17.1.5. 在 JAX-WS 端点上启用 Schema Validation
概述
您可以设置 schema-validation-enabled
属性,以在 jaxws:endpoint
元素或 jaxws:server
元素中启用 schema 验证。启用架构验证后,检查客户端和服务器之间发送的消息是否符合该架构。默认情况下,模式验证处于关闭状态,因为它对性能有严重影响。
示例
要在 JAX-WS 端点上启用架构验证,请在 jaxws:endpoint
元素或 jaxws:server
元素的 jaxws:properties
子元素中设置 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. 配置消费者端点
概述
JAX-WS 消费者端点使用 jaxws:client
元素进行配置。元素的属性提供创建消费者所需的基本信息。
要将其他功能(如 WS-RM)添加到 jaxws:client
元素的使用者中。子元素也用于配置端点的日志记录行为,并将其他属性注入端点的实现中。
基本配置属性
表 17.4 “用于配置 JAX-WS Consumer 的属性” 中描述的属性提供了配置 JAX-WS consumer 所需的基本信息。您只需要为您要配置的特定属性提供值。大多数属性都有合理的默认值,或者它们依赖于端点合同提供的信息。
属性 | 描述 |
---|---|
指定消费者要发出请求的端点的 HTTP 地址。这个值覆盖合同中设置的值。 | |
指定消费者使用的消息绑定 ID。第 23 章 Apache CXF Binding ID 中提供了有效绑定 ID 列表。 | |
指定管理端点的 Spring bean 配置总线的 ID。 | |
指定消费者发出请求的服务的 | |
指定消费者发出请求的服务的 | |
指定用于简单用户名/密码身份验证的用户名。 | |
指定用于简单用户名/密码身份验证的密码。 | |
指定服务端点接口(SEI)的名称。 | |
指定端点 WSDL 合同的位置。WSDL 合同的位置相对于部署客户端的文件夹。 | |
指定消费者发出请求的服务的 | |
指定 bean 是抽象 bean。抽象 bean 作为 concrete bean 定义的父项,它们不会被实例化。默认值为 | |
指定端点在实例化前依赖的 Bean 列表。 | |
指定使用 Apache CXF API (如
默认值为
把它设置为
|
除了 表 17.4 “用于配置 JAX-WS Consumer 的属性” 中列出的属性外,可能需要使用多个 xmlns:shortName
属性来声明 endpointName
和 serviceName
属性使用的命名空间。
添加功能
要向使用者添加功能或执行高级配置,您必须在配置中添加子元素。
通过子元素,您可以执行以下操作:
表 17.5 “配置消费者端点的元素” 描述可用于配置 JAX-WS 使用者的子元素。
element | 描述 |
---|---|
指定 bean 配置端点使用的消息绑定。使用 | |
指定实施端点使用的数据绑定的类。您可以使用嵌入式 bean 定义来指定这一点。实施 JAXB 数据的类是 | |
指定配置 Apache CXF 高级功能的 Bean 列表。您可以提供 bean 参考列表或嵌入式 Bean 列表。 | |
指定用于处理消息的 JAX-WS 处理程序列表。有关 JAX-WS 处理程序实施的更多信息,请参阅 第 43 章 编写处理程序。 | |
指定处理入站响应的拦截器列表。更多信息请参阅 第 VII 部分 “开发 Apache CXF Interceptors”。 | |
指定处理入站错误信息的拦截器列表。更多信息请参阅 第 VII 部分 “开发 Apache CXF Interceptors”。 | |
指定处理出站请求的拦截器列表。更多信息请参阅 第 VII 部分 “开发 Apache CXF Interceptors”。 | |
指定处理出站错误消息的拦截器列表。更多信息请参阅 第 VII 部分 “开发 Apache CXF Interceptors”。 | |
指定传递给端点的属性映射。 | |
为要使用的客户端指定 org.apache.cxf.endpoint.ConduitSelector 实施。ConduitSelector 实施将覆盖用于选择用于处理出站请求的 | |
[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 consumer 上启用模式验证
要在 JAX-WS consumer 上启用模式验证,请在 jaxws:client
元素的 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 服务器端点,您需要至少指定以下内容:
-
jaxrs:server
元素,用于在 XML 中定义端点。请注意,jaxrs:
命名空间前缀在 Blueprint 和 Spring 中分别映射到 不同的命名空间。 JAX-RS 服务的基本 URL 使用
jaxrs:server
元素的address
属性。请注意,可以指定地址 URL 的方法有两种,这会影响如何部署端点:作为相对 URL- 例如:
/customers
.在这种情况下,端点会部署到默认 HTTP 容器中,并通过将 CXF servlet 基本 URL 与指定的相对 URL 合并来隐式获取端点的基本 URL。例如,如果您将 JAX-RS 端点部署到 Fuse 容器,指定的
/customers
URL 将解析为 URL,http://Hostname:8181/cxf/customers
(假设容器使用默认的8181
端口)。-
例如
http://0.0.0.0:8200/cxf/customers
,作为绝对 URL PlacementBinding-SOURCE。在本例中,为 JAX-RS 端点打开了新的 HTTP 侦听器端口(如果还没有打开)。例如,在 Fuse 上下文中,会隐式创建新的 Undertow 容器来托管 JAX-RS 端点。特殊 IP 地址0.0.0.0
作为通配符,匹配分配给当前主机的任何主机名(对于多主页主机机器非常有用)。
-
一个或多个 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 命名空间:
prefix | 命名空间 |
---|---|
(默认) | |
| |
|
Spring 示例
以下 Spring XML 示例演示了如何定义 JAX-RS 端点,该端点指定了相对地址 /customers
(使其部署到默认 HTTP 容器中),并由 service.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 命名空间:
prefix | 命名空间 |
---|---|
(默认) | |
| |
|
Spring XML 中的自动发现
(仅Spring) 用来显式指定 JAX-RS 根资源类,Spring XML 可让您配置自动发现,以便搜索具体的 Java 软件包(由 @Path
标注的类)以及所有发现的资源类都自动附加到端点。在这种情况下,您只需要在 jaxrs:server
元素中指定 address
属性和 basePackages
属性。
例如,要定义一个 JAX-RS 端点,它使用 a.b.c
Java 软件包下的所有 JAX-RS 资源类,您可以在 Spring XML 中定义端点,如下所示:
<jaxrs:server address="/customers" basePackages="a.b.c"/>
自动发现机制也会发现并安装到端点(在指定的 Java 软件包下找到的 JAX-RS 提供程序类)。
Spring XML 中的生命周期管理
(仅Spring) Spring XML 允许您通过设置 bean
元素上的 scope
属性来控制 Bean 的生命周期。Spring 支持以下范围值:
singleton
- (默认) 创建单个 bean 实例,它在 Spring 容器的整个生命周期内使用并持续使用。
prototype
-
每次将 bean 注入到另一 bean 时,或通过调用 bean 注册表的
getBean ()
来创建一个新的 Bean 实例。 request
- (只在 Web 感知容器中可用) 为每个在 bean 上调用的每个请求创建一个新的 Bean 实例。
会话
- (只在 Web 感知容器中可用) 在单个 HTTP 会话的生命周期中创建一个新的 Bean。
globalSession
- (只在 Web 感知容器中可用) 在 portlets 之间共享的单个 HTTP 会话生命周期中创建一个新的 Bean。
如需有关 Spring 范围的详细信息,请参阅 Bean 范围的 Spring 框架文档。
请注意,如果通过 jaxrs:serviceBeans
元素指定 JAX-RS 资源 Bean,则 Spring 范围 无法正常工作。如果您在此例中指定 resource Bean 的 scope
属性,则有效忽略 scope
属性。
要使 bean 范围在 JAX-RS 服务器端点内正常工作,您需要一系列由服务工厂提供的间接化。配置 Bean 范围最简单的方法是,使用 jaxrs:server
元素中的 beanNames
属性来指定资源 Bean,如下所示:
<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,即 customerBean1
和 customerBean2
。beanNames
属性指定为以空格分隔的资源 bean ID 列表来指定。
为了获得灵活性,您可以选择使用 jaxrs:serviceFactories
元素在配置 JAX-RS 服务器端点时 显式 定义服务工厂对象。这种更详细的方法具有优势,您可以将默认服务工厂实施替换为您的自定义实施,从而让您最终掌控 bean 生命周期。以下示例演示了如何使用此方法配置两个资源 Bean、client Bean1
和 customerBean2
:
<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 文档关联,并且您希望在传入消息中启用模式验证,您可以指定关联的 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
元素中可用的属性。
属性 | 描述 |
---|---|
| 指定唯一标识符,其他配置元素可用于引用端点。 |
| 指定 HTTP 端点的地址。这个值将覆盖服务合同中指定的值。 |
| (仅 Spring) 启用自动发现,具体方法是指定以逗号分隔的 Java 软件包列表,用于发现 JAX-RS 根资源类和/或 JAX-RS 提供程序类和/或 JAX-RS 提供程序类。 |
|
指定 JAX-RS 根资源 Bean 的 bean ID 空格分隔的列表。在 Spring XML 上下文中,可以通过设置 root 资源 bean 元素的 |
| 指定服务使用的消息绑定 ID。第 23 章 Apache CXF Binding ID 中提供了有效绑定 ID 列表。 |
| 指定 Spring bean 配置用于管理服务端点的总线的 ID。这在将多个端点配置为使用一组通用的功能时很有用。 |
| 指定外部 WADL 文档的位置。 |
|
将模型模式指定为类路径资源(例如,格式为 |
|
指定是否应自动发布该服务。如果设置为 |
|
指定 URL 基本地址,它被插入到自动生成的 WADL 接口的 |
|
(仅Spring) 指定 Spring 中自动发现的服务注解类名称。与 |
|
指定 JAX-RS 根资源类(实施 JAX-RS 服务)的名称。在这种情况下,该类由 Apache CXF 进行实例化,而不是由 Blueprint 或 Spring 进行实例化。如果要在 Blueprint 或 Spring 中实例化类,请使用 |
|
在特殊情况下,在使用 JMS 传输时指定 JAX-RS 端点的 service QName (使用 |
|
如果为 |
|
选择非标准传输层(代替 HTTP)。特别是,您可以通过将此属性设置为 |
|
(仅 Spring) 如果 bean 是一个抽象 bean,则指定。抽象 bean 作为 concrete bean 定义的父项,它们不会被实例化。默认值为 |
| (仅Spring) 指定端点依赖在端点实例化前实例化的 Bean 列表。 |
18.1.3. jaxrs:server Child Elements
子元素
表 18.2 “JAX-RS 服务器端点子元素” 描述 jaxrs:server
元素的子元素。
element | 描述 |
---|---|
|
指定用于该服务的 Java |
| 指定配置 Apache CXF 高级功能的 Bean 列表。您可以提供 bean 参考列表或嵌入式 Bean 列表。 |
| 未使用. |
| 指定实施端点使用的数据绑定的类。这可以通过一个嵌入式 bean 定义来指定。如需了解更多详细信息,请参阅 “指定数据绑定”一节。 |
| 指定处理入站请求的拦截器列表。更多信息请参阅 第 VII 部分 “开发 Apache CXF Interceptors”。 |
| 指定处理入站错误信息的拦截器列表。更多信息请参阅 第 VII 部分 “开发 Apache CXF Interceptors”。 |
| 指定处理出站回复的拦截器列表。更多信息请参阅 第 VII 部分 “开发 Apache CXF Interceptors”。 |
| 指定处理出站错误消息的拦截器列表。更多信息请参阅 第 VII 部分 “开发 Apache CXF Interceptors”。 |
| 指定服务使用的 org.apache.cxf.service.Invoker 接口的实施。[a] |
|
为您提供了与此端点关联的 JAX-RS root 资源生命周期的最大控制程度。此元素的子项(必须是 |
| 指定传递给端点的属性的 Spring 映射。这些属性可用于控制启用 MTOM 支持等功能。 |
|
此元素的子项是( |
|
由一个或多个 |
|
在此端点中直接定义资源模型(即,此 |
|
允许您将一个或多个自定义 JAX-RS 提供程序注册到此端点。此元素的子项是 ( |
|
当 REST 调用的 URL 以文件扩展结尾时,您可以使用这个元素自动将其与特定内容类型关联。例如, |
|
当 REST 调用的 URL 以语言后缀结尾时,您可以使用此元素将它映射到特定的语言。例如, |
|
指定用于验证 XML 消息内容的一个或多个 XML 模式。此元素可以包含一个或多个 |
| 允许您注册自定义资源比较器,它实施用于匹配特定资源类或方法的传入 URL 路径的算法。 |
|
(仅限蓝色打印) 如果想要从类名称创建多个资源,而不使用 |
[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) | |
Spring |
基本客户端端点定义
以下示例演示了如何在 Blueprint XML 或 Spring XML 中创建客户端代理 bean:
<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
元素中可用的属性。
属性 | 描述 |
---|---|
| 指定消费者要发出请求的端点的 HTTP 地址。这个值覆盖合同中设置的值。 |
| 指定消费者使用的消息绑定 ID。第 23 章 Apache CXF Binding ID 中提供了有效绑定 ID 列表。 |
| 指定管理端点的 Spring bean 配置总线的 ID。 |
|
指定从这个代理创建子资源代理时是否会继承此代理的标头。默认为 |
| 指定用于简单用户名/密码身份验证的用户名。 |
| 指定用于简单用户名/密码身份验证的密码。 |
|
将模型模式指定为类路径资源(例如,格式为 |
|
指定服务接口的名称或资源类(使用 |
|
在特殊情况下,在使用 JMS 传输时指定 JAX-RS 端点的 service QName (使用 |
|
指定客户端代理是否为 thread-safe。默认为 |
|
选择非标准传输层(代替 HTTP)。特别是,您可以通过将此属性设置为 |
|
(仅 Spring) 如果 bean 是一个抽象 bean,则指定。抽象 bean 作为 concrete bean 定义的父项,它们不会被实例化。默认值为 |
| (仅Spring) 指定端点在实例化前取决于实例化的 Bean 列表。 |
18.2.3. jaxrs:client Child Elements
子元素
表 18.4 “JAX-RS 客户端端点子元素” 描述 jaxrs:client
元素的子元素。
element | 描述 |
---|---|
| |
| 指定配置 Apache CXF 高级功能的 Bean 列表。您可以提供 bean 参考列表或嵌入式 Bean 列表。 |
| 未使用. |
| 指定实施端点使用的数据绑定的类。这可以通过一个嵌入式 bean 定义来指定。如需了解更多详细信息,请参阅 “指定数据绑定”一节。 |
| 指定处理入站响应的拦截器列表。更多信息请参阅 第 VII 部分 “开发 Apache CXF Interceptors”。 |
| 指定处理入站错误信息的拦截器列表。更多信息请参阅 第 VII 部分 “开发 Apache CXF Interceptors”。 |
| 指定处理出站请求的拦截器列表。更多信息请参阅 第 VII 部分 “开发 Apache CXF Interceptors”。 |
| 指定处理出站错误消息的拦截器列表。更多信息请参阅 第 VII 部分 “开发 Apache CXF Interceptors”。 |
| 指定传递给端点的属性映射。 |
|
允许您将一个或多个自定义 JAX-RS 提供程序注册到此端点。此元素的子项是 ( |
|
由一个或多个 |
|
在此端点中直接定义资源模型(即 |
| 用于设置传出消息上的标头。详情请查看 “指定标头”一节。 |
|
指定用于验证 XML 消息内容的一个或多个 XML 模式。此元素可以包含一个或多个 |
18.3. 使用模型定义 REST 服务
不含注解的 RESTful 服务
JAX-RS 模型架构使得定义 RESTful 服务成为可能,无需 注解 Java 类。也就是说,您可以使用模型模式在单独的 XML 文件中添加 @Path
、@PathParam
、@Consumes
、@Produces
等注释,而是直接在 Java 类(或接口)中提供所有相关 REST 元数据。例如,当您无法修改实现服务的 Java 源时,这很有用。
模式 schema 示例
例 18.1 “JAX-RS Model Schema 示例” 显示为 BookStoreNoAnnotations
根资源类定义服务元数据的模型模式示例。
例 18.1. JAX-RS Model Schema 示例
<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) | |
Spring |
如何将模型模式附加到端点
要将模型模式定义并附加到端点,请执行以下步骤:
- 定义模型架构,使用您选择的注入平台(Blueprint XML 或 Spring XML)的适当 XML 命名空间。
将模型模式文件添加到您的项目的资源中,以便 schema 文件可在最终软件包(JAR、WAR 或 OSGi 捆绑包文件)中的 classpath 上可用。
注意另外,还可以使用端点的
jaxrs:model
子元素直接将模型模式嵌入到 JAX-RS 端点中。-
将端点配置为使用模型模式,将端点的
modelRef
属性设置为类路径上模型模式的位置(使用类路径 URL)。 -
如有必要,使用
jaxrs:serviceBeans
元素明确实例化 root 资源。如果模型模式引用 root 资源类(而不是引用基本接口),您可以跳过此步骤。
引用类的模型模式配置
如果模型架构直接应用到根资源类,则不需要使用 jaxrs:serviceBeans
元素定义任何根资源 Bean,因为模型模式会自动实例化根资源 Bean。
例如,如果 customer-resources.xml
是一种模型模式,将元数据与客户资源类相关联,您可以按照如下所示实例化 customerService
服务端点:
<jaxrs:server id="customerService" address="/customers" modelRef="classpath:/org/example/schemas/customer-resources.xml" />
引用接口的模型模式配置
如果模型架构适用于 Java 接口(这是 root 资源的基本接口),则必须使用端点中的 jaxrs:serviceBeans
元素实例化根资源类。
例如,假设 customer-interfaces.xml
是一种将元数据与客户接口关联的模型模式,您可以按照如下所示实例化 customerService
服务端点:
<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"/>
Model Schema Reference
模型模式使用以下 XML 元素定义:
model
-
模型架构的根元素。如果您需要引用模型模式(例如,使用
modelRef
属性从 JAX-RS 端点),您应该设置此元素上的id
属性。 model/resource
资源
元素用于将元数据与特定根资源类(或与对应的接口)关联。您可以在resource
元素上定义以下属性:属性 描述 + name
应用此资源模型的资源类(或对应接口)的名称。
+
path
映射到此资源的 REST URL 路径的组件。
+
使用
指定此资源使用的内容类型(Internet 介质类型),如
application/xml
或application/json
。+
生成
指定此资源生成的内容类型(Internet 介质类型),如
application/xml
或application/json
。+
model/resource/operation
操作
元素用于将元数据与 Java 方法关联。您可以在操作
元素上定义以下属性:属性 描述 + name
应用此元素的 Java 方法的名称。
+
path
映射到此方法的 REST URL 路径的组件。此属性值可以包含参数引用,例如:
path="/books/{id}/chapter"
,其中{id}
从路径中提取id
参数的值。+
verb
指定映射到此方法的 HTTP 动词。通常之一:
GET
、POST
、PUT
或DELETE
。如果没有指定 HTTP 动词,则假设 Java 方法是一种 子资源定位器,这将返回对子资源对象的引用(其中,必须使用资源
元素提供子资源类)。+
使用
指定此操作使用的内容类型(Internet 介质类型),例如
application/xml
或application/json
。+
生成
指定此操作生成的内容类型(Internet 介质类型),例如
application/xml
或application/json
。+
oneway
如果为
true
,请将操作配置为 单向,表示不需要回复消息。默认值为false
。+
model/resource/operation/param
使用
param
元素从 REST URL 中提取值并将其注入到方法参数之一中。您可以在param
元素上定义以下属性:属性 描述 + name
应用此元素的 Java 方法参数的名称。
+
type
指定从 REST URL 或消息中提取参数值的方式。它可设置为以下值之一:
PATH
,QUERY
,MATRIX
,HEADER
,COOKIE
,FORM
,CONTEXT
,REQUEST_BODY
.+
defaultValue
要注入参数的默认值,如果无法从 REST URL 或消息中提取值。
+
encoded
如果为
true
,则参数值使用 URI 编码格式注入(即使用%nn
编码)。默认为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 示例应用程序中日志消息的日志级别和输出目的地,请完成以下步骤:
使用
InstallDir/samples/wsdl_first
目录中的README.txt
文件的 java 部分,运行示例服务器,如运行演示 中所述。请注意,服务器启动命令
指定默认的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 日志记录器,以将WARNING
级别日志消息打印到控制台。因此,您会看到很少打印到控制台。-
按照
README.txt
文件中所述停止服务器。 -
复制默认的
logging.properties
文件,将它命名为mylogging.properties
文件,并将它保存为默认的logging.properties
文件。 通过编辑以下配置行,将
mylogging.properties
文件中的全局日志记录级别和控制台日志记录级别更改为INFO
:.level= INFO java.util.logging.ConsoleHandler.level = INFO
使用以下命令重启服务器:
平台 命令 + 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 &
+
由于您已将全局记录和控制台日志记录器配置为记录 level
INFO
的信息,所以您会看到很多日志消息被打印到控制台。
19.3. 默认日志配置文件
19.3.1. 日志配置概述
默认日志记录配置文件 logging.properties
位于 InstallDir/etc
目录中。它配置 Apache CXF 日志记录器,以将 WARNING
级别消息打印到控制台。如果此级别的日志记录适用于您的应用程序,则不需要在使用该文件前对该文件进行任何更改。但是,您可以在日志消息中更改详情级别。例如,您可以更改日志消息是否发送到控制台,并发送到文件或两者。另外,您可以在单个软件包的级别指定日志记录。
本节讨论默认的 logging.properties
文件中出现的配置属性。但是,您还可设置许多其他 java.util.logging
配置属性。有关 java.util.logging
API 的更多信息,请访问 java.util.logging
javadoc :
19.3.2. 配置日志输出
概述
Java 日志记录实用程序 java.util.logging
使用处理程序类输出日志消息。表 19.1 “java.util.logging Handler 类” 显示默认 logging.properties
文件中配置的处理程序。
处理程序类 | 输出到 |
---|---|
| 输出到控制台的日志消息 |
| 输出日志消息到文件 |
处理程序类必须在系统类路径上,以便在 Java 虚拟机启动时由 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
。
指定控制台处理程序类用于格式化日志消息的 java.util.logging
格式ter 类。默认设置为 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
格式ter 类。默认设置为 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. 子系统和服务的日志记录
概述
您可以使用 “在独立软件包中配置日志记录”一节 中描述的 com.xyz.foo.level
配置属性为指定的 Apache CXF 日志记录子系统设置精细的日志记录。
Apache CXF 日志记录子系统
表 19.2 “Apache CXF Logging Subsystems” 显示可用 Apache CXF 日志记录子系统列表。
子系统 | 描述 |
---|---|
| Aegis 绑定 |
| 共存绑定 |
| HTTP 绑定 |
| JBI 绑定 |
| Java 对象绑定 |
| SOAP 绑定 |
| XML 绑定 |
| Apache CXF 总线 |
| 配置框架 |
| 服务器和客户端端点 |
| 拦截器 |
| JAX-WS 风格的消息交换的前端、JAX-WS 处理程序处理以及与 JAX-WS 和配置的拦截器 |
| JBI 容器集成类 |
| JCA 容器集成类 |
| JavaScript 前端 |
| HTTP 传输 |
| 使用 HTTPS 的安全 HTTP 传输版本 |
| JBI 传输 |
| JMS 传输 |
| 使用本地文件系统进行传输 |
| 用于将 JAX-WS 端点加载到 servlet 容器中的 HTTP 传输和 servlet 实施 |
| WS-Addressing 实现 |
| WS-Policy 实现 |
| WS-ReliableMessaging (WS-RM)实施 |
| WSS4J 安全实现 |
示例
WS-Addressing 示例包含在 InstallDir/samples/ws_addressing
目录中。日志记录在位于该目录中的 logging.properties
文件中进行配置。相关的配置行在 例 19.9 “为 WS-Address 配置日志记录” 中显示。
例 19.9. 为 WS-Address 配置日志记录
java.util.logging.ConsoleHandler.formatter = demos.ws_addressing.common.ConciseFormatter ... org.apache.cxf.ws.addressing.soap.MAPCodec.level = INFO
例 19.9 “为 WS-Address 配置日志记录” 中的配置启用了与 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 信息。
设置日志记录以记录 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 示例应用程序,如下所示:
将 例 19.13 “Logging SOAP 消息的端点配置” 中显示的
jaxws:features
元素添加到位于 wsdl_first 示例目录中的cxf.xml
配置文件中:例 19.13. Logging 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>
-
示例使用默认的
logging.properties
文件,该文件位于InstallDir/etc
目录中。制作此文件的副本,并将其命名为mylogging.properties
。 在
mylogging.properties
文件中,通过编辑.level
和java.util.logging.ConsoleHandler.level
配置属性将日志记录级别更改为INFO
:.level= INFO java.util.logging.ConsoleHandler.level = INFO
使用
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 &
+
使用以下命令启动 hello 全局客户端:
平台 命令 + 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 支持 JAX-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” 所述。
拦截器 | 描述 |
---|---|
| 负责聚合用于传出消息的消息地址属性(MAPs)的逻辑拦截器。 |
| 负责将消息寻址属性(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 和 Adding 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 和 Adding 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 属性” 中描述的两个属性。
属性名称 | 值 |
---|---|
|
确定是否容忍重复的 MessageID 的布尔值。默认设置为 |
|
指明 WSDL 中是否存在 |
配置 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” 中,寻址策略断言来启用非匿名响应,并嵌入在 策略
元素中。
例 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-可靠Messaging (WS-RM)是一种协议,可确保在分布式环境中可靠地传送消息。它使得在存在软件、系统或网络故障的分布式应用程序之间可靠传递消息。
例如,WS-RM 可用于确保网络只按正确的顺序传送正确的消息。
WS-RM 的工作原理
WS-RM 可确保在源和目标端点之间可靠发送消息。源是消息的初始发件人,目的地是最终接收器,如 图 21.1 “Web 服务可靠消息传递” 所示。
图 21.1. Web 服务可靠消息传递
WS-RM 消息的流可以如下所述:
-
RM 源向 RM 目的地发送
CreateSequence
协议消息。它包含接收确认的端点的引用(wsrm:AcksTo
端点)。 -
RM 目的地将
CreateSequenceResponse
协议消息发送回 RM 源。此消息包含 RM 序列会话的序列 ID。 -
RM 源在应用程序源发送的每个消息中添加 RM
Sequence
标头。此标头包含序列 ID 和唯一消息 ID。 - RM 源将每条消息传输到 RM 目的地。
-
RM 目的地通过发送包含 RM
SequenceAcknowledgement
标头的消息来确认来自 RM 源的消息。 - RM 目的地以精确的顺序向应用程序目的地提供消息。
RM 源重新传输尚未收到确认的消息。
第一个重新传输尝试会在基本重新传输间隔后进行。默认情况下,连续重新传输尝试会按指数避退间隔,或者以固定间隔进行。如需了解更多详细信息,请参阅 第 21.5 节 “配置 WS-RM”。
这整个过程对请求和响应消息都进行对称;即,在响应消息的情况下,服务器充当 RM 源,客户端充当 RM 目的地。
WS-RM 交付保证
WS-RM 可在分布式环境中保证可靠的消息交付,无论使用的传输协议如何。如果无法可靠交付,则源或目的地端点会记录错误。
支持的规格
Apache CXF 支持以下 WS-RM 规格版本:
- WS-ReliableMessaging 1.0
(默认) Corresp onds 到 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-寻址版本中的第一个版本(这是 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-ReliableMessaging 的每个版本并对其做出相应的响应。
- 客户端
- 在客户端一端,WS-RM 版本由您在客户端配置中使用的命名空间(请参阅 第 21.5 节 “配置 WS-RM”)或者在运行时覆盖 WS-RM 版本(请参阅 第 21.4 节 “运行时控制”)。
21.2. WS-RM 拦截器
概述
在 Apache CXF 中,WS-RM 功能实施为拦截器。Apache CXF 运行时使用拦截器来截获和处理正在发送和接收的原始消息。当传输收到消息时,它会创建一个消息对象,并通过拦截器链发送该消息。如果应用的拦截器链包含 WS-RM 拦截器,应用程序可以参与可靠的消息传递会话。WS-RM 拦截器处理消息块的集合和聚合。他们还处理所有确认和重新传输逻辑。
Apache CXF WS-RM 拦截器
Apache CXF WS-RM 实施由四个拦截器组成,该拦截器在 表 21.1 “Apache CXF WS-ReliableMessaging Interceptors” 所述。
拦截器 | 描述 |
---|---|
| 处理为外发消息提供可靠性保证的逻辑方面。
负责发送 另外,还负责聚合序列 properties-ID 和消息编号(用于应用程序消息)。 |
|
负责截获和处理 RM 协议消息和 |
| 缓存持久存储的传入消息。 |
| 确保向应用交付消息。 |
| 负责将可靠性属性编码和解码为 SOAP 标头。 |
| 负责为将来的重新发送创建应用程序消息副本。 |
启用 WS-RM
在拦截器链上存在 WS-RM 拦截器可确保在必要时会交换 WS-RM 协议消息。例如,当截获出站拦截器链上的第一条应用程序消息时,RMOutInterceptor
发送 CreateSequence
请求并等待处理原始应用程序消息,直到它收到 CreateSequenceResponse
响应。此外,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:明确添加拦截器
要启用 WS-RM,将 WS-RM 和 WS-Addressing 拦截器添加到 Apache CXF 总线,或使用 Spring bean 配置将 WS-RM 和 WS-Addressing 拦截器添加到消费者或服务端点。这是在 WS-RM 示例中执行的方法,可在 InstallDir/samples/ws_rm
目录中找到。配置文件 ws-rm.cxf
显示了 WS-RM 和 WS-Addressing 拦截器被添加一站为 Spring Bean (请参阅 例 21.1 “使用 Spring Bean 启用 WS-RM”)。
例 21.1. 使用 Spring Bean 启用 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 Bean 启用 WS-RM” 中显示的代码可以按如下方式进行说明:
Apache CXF 配置文件是一个 Spring XML 文件。您必须包含一个打开 Spring Bean
元素,用于声明由 Bean
元素封装的子元素的命名空间和 schema 文件。
配置每个 WS-Addressing interceptors-MAPAggregator
和 MAPCodec
。有关 WS-Addressing 的更多信息,请参阅 第 20 章 部署 WS-Addressing。
配置每个 WS-RM 拦截器-RMOutInterceptor
、RMInInterceptor
、RMSoapInterceptor
。
将 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 Services Policy 1.5-Framework 和 Web Services Policy 1.5-Attachment 规格。
要使用 Apache CXF WS-Policy 框架启用 WS-RM,请执行以下操作:
在您的客户端和服务器端点中添加策略功能。例 21.2 “使用 WS-RM 配置 WS-Policy” 显示
jaxws:feature
元素内嵌套的 bean 引用。reference bean 指定AddressingPolicy
,它定义为同一配置文件中的一个单独的元素。例 21.2. 使用 WS-RM 配置 WS-Policy
<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>
将可靠的消息传递策略添加到
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.ws.rm.RMManager
类中的公共常数定义。
运行时控制选项
下表列出了 org.apache.cxf.ws.rm.RMManager
类定义的密钥。
键 | 描述 |
---|---|
|
字符串 WS-RM 版本命名空间( |
|
字符串 WS-Addressing 版本命名空间( |
|
布尔值 |
| 以毫秒为单位进行长期不活跃超时。 |
| 较长的基础重新传输间隔(以毫秒为单位)。 |
| 布尔值 exponential back-off 标志。 |
| 长期确认间隔(以毫秒为单位)。 |
通过 JMX 控制 WS-RM
您还可以使用 Apache CXF 的 JMX 管理功能监控和管理 WS-RM 的许多方面。JMX 操作的完整列表由 org.apache.cxf.ws.rm.ManagedRMManager
和 org.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。在您的配置文件中添加以下内容:
-
到命名空间列表的
http://cxf.apache.org/ws/rm/manager
命名空间。 -
用于您要配置的特定属性的
rmManager
Spring bean。
例 21.4 “配置 Apache CXF 特定 WS-RM 属性” 显示一个简单的示例。
例 21.4. 配置 Apache CXF 特定 WS-RM 属性
<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"> ... <wsrm-mgr:rmManager> <!-- ...Your configuration goes here --> </wsrm-mgr:rmManager>
rmManager Spring bean 的子项
表 21.2 “rmManager Spring Bean 的子项” 显示 http://cxf.apache.org/ws/rm/manager
命名空间中定义的 rmManager
Spring bean 的子元素。
element | 描述 |
---|---|
|
类型的 |
|
一个类型为 |
|
一个类型为 |
|
一个类型为 |
示例
例如,请参阅 “最多未确认的消息阈值”一节。
21.5.2. 配置标准 WS-RM 策略属性
概述
您可以使用以下方法之一配置标准 WS-RM 策略属性:
WS-Policy RMAssertion Children
表 21.3 “WS-Policy RMAsertion Element 的子项” 显示 http://schemas.xmlsoap.org/ws/2005/02/rm/policy
命名空间中定义的元素:
名称 | 描述 |
---|---|
| 指定在端点可以视为因为不活跃而终止的 RM 序列前必须收到消息前必须经过的时间长度。 |
|
设置确认在 RM Source 中给定邮件必须接收的间隔。如果 |
| 表示将使用通常已知的 exponential backoff 算法(Tanenbaum)调整重新传输间隔。 如需更多信息,请参阅 Computer Networks, Andrew S. Tanenbaum, Prentice Hall PTR, 2003。 |
| 在 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 中添加 RMAssertion
来配置标准 WS-RM 策略属性。如果您想在同一配置文件中保留所有 WS-RM 配置,这是最佳的方法。也就是说,如果要在同一文件中配置特定于 Apache CXF 的属性和标准 WS-RM 策略属性。
例如,例 21.5 “在 rmManager Spring Bean 中使用 RMAsertion 配置 WS-RM 属性” 中的配置会显示:
-
使用
rmManager
Spring bean 中的 RMAsertion 配置的标准 WS-RM
策略属性BaseRetransmissionInterval
。 -
同一配置文件中配置的 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 属性。如果属性是 http://schemas.xmlsoap.org/ws/2005/02/rm/policy/ 命名空间中定义的标准 WS-RM 策略属性,则只显示在 rmManager
Spring bean 中的 RMAssertion
中设置它的示例。有关如何在功能内设置这样的属性 ; 在 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>
重新传输的 exponential backoff
ExponentialBackoff
元素确定是否以指数级间隔执行非确认的消息尝试连续重传输尝试。
存在 ExponentialBackoff
元素可启用此功能。默认会使用 exponential backoff 比率为 2
。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 致谢 Interval” 显示如何设置 WS-RM 确认间隔。
例 21.10. 设置 WS-RM 致谢 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>
最多未确认的消息阈值
maxUnack
nowled 属性设置在终止序列前可以获取每个序列的最大未确认消息数。
例 21.11 “设置 WS-RM Maximum Unacknowled Message Threshold” 显示如何设置 WS-RM 最大无法确认的消息阈值。
例 21.11. 设置 WS-RM Maximum Unacknowled 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 序列的长度为 unbound。
当设置了此属性时,RM 端点会在达到限制时创建一个新的 RM 序列,并在收到之前发送的消息的所有确认后。新消息使用新的排序发送。
例 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 目标配置为使用以下发送保证策略:
例 21.13 “设置 WS-RM 消息发送保证策略” 介绍如何设置 WS-RM 消息发送保证。
例 21.13. 设置 WS-RM 消息发送保证策略
<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 存储属性” 中显示的属性。
属性名称 | 类型 | 默认设置 |
---|---|---|
|
| |
| null | |
| null | |
| jdbc:derby:rmdb;create=true |
例 21.15 “为 WS-RM Persistence 配置 JDBC 存储” 中显示的配置启用了基于 JDBC 的存储,该存储与 Apache CXF 一同启用,同时将 driverClassName
和 url
设置为非默认值。
例 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. 使用 Static Failover 启用 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
,在三个端口上公开:
-
Replica1
-
Replica2
-
Replica3
定义 Replica1
以通过 HTTP 端点在端口 9001
上公开 ClusterService
作为 SOAP。
定义 Replica2
将 ClusterService
公开为通过 HTTP 端点在端口 9002
上的 SOAP。
定义 Replica3
以通过 HTTP 端点在 9003
上公开 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. 使用 Static Failover 配置 HA
概述
默认情况下,如果客户端通信的原始服务不可用,具有静态故障转移的 HA 会使用一个后续策略。顺序策略会在每次使用时以相同的顺序选择副本服务。选择由 Apache CXF 的内部服务模型决定,从而产生确定的故障转移模式。
配置随机策略
您可以使用静态故障转移配置 HA,以便在选择副本时使用随机策略而不是后续策略。随机策略在每次服务不可用时选择随机副本服务,或者失败时。从集群中的 surviving 成员中选择故障转移目标是完全随机的。
要配置随机策略,请将 例 22.3 “为 Static Failover 配置随机策略” 中显示的配置添加到您的客户端配置文件中。
例 22.3. 为 Static Failover 配置随机策略
<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 “为 Static Failover 配置随机策略” 中显示的配置可以按如下方式进行说明:
定义实施随机策略的 Random
bean 和实施类。
指定在选择副本时使用随机策略。
第 23 章 Apache CXF Binding ID
绑定 ID 表
绑定 | ID |
---|---|
CORBA | |
HTTP/REST | |
SOAP 1.1 | |
SOAP 1.1 w/ MTOM | |
SOAP 1.2 | |
SOAP 1.2 w/ MTOM | |
XML |
附录 A. 使用 Maven OSGi 工具
摘要
为大型项目手动创建捆绑包或捆绑包集合可能会非常繁琐。Maven bundle 插件通过自动化流程并提供多个快捷方式来指定捆绑包清单的内容,使作业变得更加容易。
A.1. Maven Bundle Plug-In
红帽 Fuse OSGi 工具使用来自 Apache Felix 的 Maven 捆绑包插件。bundle 插件基于 Peter Kriens 中的 bnd 工具。它通过内省要打包在捆绑包中的类的内容来自动构建 OSGi 捆绑包清单。利用捆绑包中包含的类知识,插件可以计算正确的值来填充捆绑包清单中的 Import-Packages
和 Export-Package
属性。该插件也具有用于捆绑包清单中其他必要属性的默认值。
要使用 bundle 插件,请执行以下操作:
- 第 A.2 节 “设置红帽 Fuse OSGi 项目” 项目的 POM 文件的 bundle 插件。
- 第 A.3 节 “配置捆绑插件” 插件可正确填充捆绑包的清单。
A.2. 设置红帽 Fuse OSGi 项目
概述
构建 OSGi 捆绑包的 Maven 项目可以是一个简单的单级项目。它不需要任何子项目。但是,它需要您进行以下操作:
您可以使用多个 Maven archetypes 来使用适当的设置设置项目。
目录结构
构建 OSGi 捆绑包的项目可以是单一级别的项目。它仅要求您拥有顶级 POM 文件和 src
文件夹。如在所有 Maven 项目中,您要将所有 Java 源代码放在 src/java
文件夹中,并将任何非 Java 资源放在 src/resources
文件夹中。
非 Java 资源包括 Spring 配置文件、JBI 端点配置文件和 WSDL 合同。
使用 Apache CXF、Apache Camel 或其他配置的 Spring bean 的红帽 Fuse OSGi 项目还包括位于 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 文件的 打包
元素设置为 捆绑包 来实现此目的
。
有用的 Maven archetypes
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
。如果 artifactId 以 groupId 的最后一个部分开头,则删除该部分。
例如,如果 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
。
要为捆绑包版本指定您自己的值,在插件的 instructions
元素中添加 Bundle-Version
子,如 例 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>
指定导出的软件包
默认情况下,OSGi 清单的 Export-Package
列表由本地 Java 源代码中的所有软件包(在 src/main/java
下)填充,但 默认软件包 . . 以及包含
.impl
或 .internal
的任何软件包。
如果您在插件配置中使用 Private-Package
元素,且您没有指定要导出的软件包列表,则默认行为仅包括捆绑包中列出的 Private-Package
元素中列出的软件包。没有导出软件包。
默认行为可能会导致非常大的软件包,并导出应保持私有的软件包。要更改导出的软件包列表,您可以将 Export-Package
子级添加到插件的 instructions
元素中。
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
元素与 中的 Export-Package
元素的工作方式与您在捆绑包中包含的软件包列表类似。bundle 插件使用 list 来查找要包含在捆绑包中的项目类路径上的所有类。这些软件包打包在捆绑包中,但不导出(除非它们也由 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
子添加到插件的 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 注解,您可以添加服务启用 Java 类所需的信息。您还可以创建一个可用于取代 WSDL 合同的服务端点 接口 (SEI)。如果您需要 WSDL 合同,Apache CXF 提供从注释的 Java 代码生成合同的工具。
24.1. JAX-WS 服务开发简介
要创建从 Java 启动的服务,您必须执行以下操作:
第 24.2 节 “创建 SEI” 一个 Service Endpoint Interface (SEI),用于定义您要公开为服务的方法。
注意您可以直接从 Java 类工作,但建议从接口中工作。界面更适合与负责开发服务的应用程序的开发人员共享。接口比较小,不提供任何服务的实施详细信息。
- 第 24.3 节 “为代码添加注解” 代码所需的注解。
第 24.4 节 “生成 WSDL” 面向服务的 WSDL 合同。
注意如果您希望使用 SEI 作为服务合同,则不需要生成 WSDL 合同。
- 第 31 章 发布服务 服务作为服务提供商。
24.2. 创建 SEI
概述
服务端点接口 (SEI)是 Java 代码的一部分,在服务实施和在该服务上发出请求的用户之间共享。SEI 定义服务实施的方法,并提供有关如何将服务公开为端点的详细信息。从 WSDL 合同开始,SEI 由代码生成器生成。但是,从 Java 开始时,开发人员负责创建 SEI。 创建 SEI 有两种基本模式:
绿色字段开发 - 在这个模式中,您正在没有现有 Java 代码或 WSDL 的情况下开发新服务。最好先创建 SEI。然后,您可以将 SEI 分发给负责实施使用 SEI 的服务提供商和消费者的任何开发人员。
注意推荐执行绿色字段服务开发方式,即首先创建一个定义服务及其接口的 WSDL 合同。请参阅 第 26 章 启动点 WSDL 合同。
服务启用 - 在这种模式中,您通常具有作为 Java 类实施的现有功能集合,并且您希望启用该服务。这意味着您必须执行两个操作:
- 创建一个 SEI,仅包含 作为服务一部分公开的操作。
修改现有的 Java 类,使其实施 SEI。
注意虽然您可以将 JAX-WS 注解添加到 Java 类中,但不推荐这样做。
编写接口
SEI 是标准的 Java 接口。它定义了类实施的一组方法。它还可以定义多个成员字段,以及实施类可访问的常量。
如果定义的方法为 SEI,应当映射到服务公开的操作。SEI 对应于 wsdl:portType
元素。SEI 定义的方法对应于
元素。
wsdl:
portType
JAX-WS 定义了一个注解,允许您指定没有公开为服务一部分的方法。但是,最佳实践是将这些方法离开 SEI。
例 24.1 “简单 SEI” 为库存更新服务显示简单的 SEI。
例 24.1. 简单 SEI
package com.fusesource.demo; public interface quoteReporter { public Quote getQuote(String ticker); }
实现接口
因为 SEI 是标准的 Java 接口,所以实施它的类是标准的 Java 类。如果以 Java 类开头,您必须进行修改以实施接口。如果您从 SEI 开始,实施类将实施 SEI。
例 24.2 “简单实施类” 显示在 例 24.1 “简单 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); } }
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
Properties”
属性 | 描述 |
---|---|
指定服务接口的名称。此属性映射到 | |