Red Hat Training

A Red Hat training course is available for Red Hat Fuse

第 18 章 配置 JAX-RS 端点

摘要

本章论述了如何在 Blueprint XML 和 Spring XML 中实例化和配置 JAX-RS 服务器端点,以及如何在 XML 中实例化和配置 JAX-RS 客户端端点(客户端代理 Bean)

18.1. 配置 JAX-RS 服务器端点

18.1.1. 定义 JAX-RS 服务器端点

基本服务器端点定义

要在 XML 中定义 JAX-RS 服务器端点,您需要至少指定以下内容:

  1. jaxrs:server 元素,用于在 XML 中定义端点。请注意,jaxrs: 命名空间前缀在 Blueprint 和 Spring 中分别映射到 不同的命名空间
  2. 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 作为通配符,匹配分配给当前主机的任何主机名(对于多主页主机机器非常有用)。
  3. 一个或多个 JAX-RS 根资源类,提供 JAX-RS 服务的实施。指定资源类最简单的方式是在 jaxrs:serviceBeans 元素中列出它们。

蓝图示例

以下 Blueprint XML 示例演示了如何定义 JAX-RS 端点,该端点指定了相对地址 /customers (使其部署到默认 HTTP 容器中),并由 service.CustomerService 资源池实施:

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:jaxrs="http://cxf.apache.org/blueprint/jaxrs"
    xmlns:cxf="http://cxf.apache.org/blueprint/core"
    xsi:schemaLocation="
http://www.osgi.org/xmlns/blueprint/v1.0.0 https://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
http://cxf.apache.org/blueprint/jaxrs http://cxf.apache.org/schemas/blueprint/jaxrs.xsd
http://cxf.apache.org/blueprint/core http://cxf.apache.org/schemas/blueprint/core.xsd
">

    <cxf:bus>
        <cxf:features>
            <cxf:logging/>
        </cxf:features>
    </cxf:bus>

     <jaxrs:server id="customerService" address="/customers">
        <jaxrs:serviceBeans>
           <ref component-id="serviceBean" />
        </jaxrs:serviceBeans>
     </jaxrs:server>

     <bean id="serviceBean" class="service.CustomerService"/>
</blueprint>

蓝图 XML 命名空间

要在 Blueprint 中定义 JAX-RS 端点,您通常至少需要以下 XML 命名空间:

Spring 示例

以下 Spring XML 示例演示了如何定义 JAX-RS 端点,该端点指定了相对地址 /customers (使其部署到默认 HTTP 容器中),并由 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 命名空间:

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,即 customerBean1customerBean2beanNames 属性指定为以空格分隔的资源 bean ID 列表来指定。

为了获得灵活性,您可以选择使用 jaxrs:serviceFactories 元素在配置 JAX-RS 服务器端点时 显式 定义服务工厂对象。这种更详细的方法具有优势,您可以将默认服务工厂实施替换为您的自定义实施,从而让您最终掌控 bean 生命周期。以下示例演示了如何使用此方法配置两个资源 Bean、client Bean1customerBean2

<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 元素中可用的属性。

表 18.1. JAX-RS 服务器端点属性

属性描述

id

指定唯一标识符,其他配置元素可用于引用端点。

address

指定 HTTP 端点的地址。这个值将覆盖服务合同中指定的值。

basePackages

(仅 Spring) 启用自动发现,具体方法是指定以逗号分隔的 Java 软件包列表,用于发现 JAX-RS 根资源类和/或 JAX-RS 提供程序类和/或 JAX-RS 提供程序类。

beanNames

指定 JAX-RS 根资源 Bean 的 bean ID 空格分隔的列表。在 Spring XML 上下文中,可以通过设置 root 资源 bean 元素的 scope 属性来定义根资源 Bean 的生命周期。

bindingId

指定服务使用的消息绑定 ID。第 23 章 Apache CXF Binding ID 中提供了有效绑定 ID 列表。

bus

指定 Spring bean 配置用于管理服务端点的总线的 ID。这在将多个端点配置为使用一组通用的功能时很有用。

docLocation

指定外部 WADL 文档的位置。

modelRef

将模型模式指定为类路径资源(例如,格式为 classpath:/path/to/model.xml的 URL)。有关如何定义 JAX-RS 模型模式的详情,请参考 第 18.3 节 “使用模型定义 REST 服务”

publish

指定是否应自动发布该服务。如果设置为 false,则开发人员必须显式发布端点。

publishedEndpointUrl

指定 URL 基本地址,它被插入到自动生成的 WADL 接口的 wadl:resources/@base 属性中。

serviceAnnotation

(仅Spring) 指定 Spring 中自动发现的服务注解类名称。与 basePackages 属性结合使用时,此选项将自动发现类的集合 限制为仅 包含由此注解类型注释的类。guess!这是否正确?

serviceClass

指定 JAX-RS 根资源类(实施 JAX-RS 服务)的名称。在这种情况下,该类由 Apache CXF 进行实例化,而不是由 Blueprint 或 Spring 进行实例化。如果要在 Blueprint 或 Spring 中实例化类,请使用 jaxrs:serviceBeans 子元素。

serviceName

在特殊情况下,在使用 JMS 传输时指定 JAX-RS 端点的 service QName (使用 ns:name)。详情请查看 “使用 JMS 传输”一节

staticSubresourceResolution

如果为 true,则禁用静态子资源动态解析。默认为 false

transportId

选择非标准传输层(代替 HTTP)。特别是,您可以通过将此属性设置为 http://cxf.apache.org/transports/jms 来选择 JMS 传输。详情请查看 “使用 JMS 传输”一节

abstract

(仅 Spring) 如果 bean 是一个抽象 bean,则指定。抽象 bean 作为 concrete bean 定义的父项,它们不会被实例化。默认值为 false。把它设置为 true 会指示 bean 工厂不要实例化 bean。

depends-on

(仅Spring) 指定端点依赖在端点实例化前实例化的 Bean 列表。

18.1.3. jaxrs:server Child Elements

子元素

表 18.2 “JAX-RS 服务器端点子元素” 描述 jaxrs:server 元素的子元素。

表 18.2. JAX-RS 服务器端点子元素

element描述

jaxrs:executor

指定用于该服务的 Java Executor (线程池实现)。这可以通过一个嵌入式 bean 定义来指定。

jaxrs:features

指定配置 Apache CXF 高级功能的 Bean 列表。您可以提供 bean 参考列表或嵌入式 Bean 列表。

jaxrs:binding

未使用.

jaxrs:dataBinding

指定实施端点使用的数据绑定的类。这可以通过一个嵌入式 bean 定义来指定。如需了解更多详细信息,请参阅 “指定数据绑定”一节

jaxrs:inInterceptors

指定处理入站请求的拦截器列表。更多信息请参阅 第 VII 部分 “开发 Apache CXF Interceptors”

jaxrs:inFaultInterceptors

指定处理入站错误信息的拦截器列表。更多信息请参阅 第 VII 部分 “开发 Apache CXF Interceptors”

jaxrs:outInterceptors

指定处理出站回复的拦截器列表。更多信息请参阅 第 VII 部分 “开发 Apache CXF Interceptors”

jaxrs:outFaultInterceptors

指定处理出站错误消息的拦截器列表。更多信息请参阅 第 VII 部分 “开发 Apache CXF Interceptors”

jaxrs:invoker

指定服务使用的 org.apache.cxf.service.Invoker 接口的实施。[a]

jaxrs:serviceFactories

为您提供了与此端点关联的 JAX-RS root 资源生命周期的最大控制程度。此元素的子项(必须是 org.apache.cxf.jaxrs.lifecycle.ResourceProvider type)的实例用于创建 JAX-RS 根资源实例。

jaxrs:properties

指定传递给端点的属性的 Spring 映射。这些属性可用于控制启用 MTOM 支持等功能。

jaxrs:serviceBeans

此元素的子项是(bean 元素)或对(ref 元素) JAX-RS 根资源的引用。请注意,如果 bean 元素中存在 scope 属性 (仅适用于 Spring), 则忽略。

jaxrs:modelBeans

由一个或多个 org.apache.cxf.jaxrs.model.UserResource beans 的引用列表组成,它们是资源模型的基本元素(corresponding to jaxrs:resource 元素)。详情请查看 第 18.3 节 “使用模型定义 REST 服务”

jaxrs:model

在此端点中直接定义资源模型(即,此 jaxrs:model 元素可以包含一个或多个 jaxrs:resource 元素)。详情请查看 第 18.3 节 “使用模型定义 REST 服务”

jaxrs:providers

允许您将一个或多个自定义 JAX-RS 提供程序注册到此端点。此元素的子项是 (bean 元素)或对(ref 元素) JAX-RS 提供程序的引用。

jaxrs:extensionMappings

当 REST 调用的 URL 以文件扩展结尾时,您可以使用这个元素自动将其与特定内容类型关联。例如,.xml 文件扩展名可以与 application/xml 内容类型关联。详情请查看 “扩展映射和语言映射”一节

jaxrs:languageMappings

当 REST 调用的 URL 以语言后缀结尾时,您可以使用此元素将它映射到特定的语言。例如,.en 语言后缀可与 en-GB 语言关联。详情请查看 “扩展映射和语言映射”一节

jaxrs:schemaLocations

指定用于验证 XML 消息内容的一个或多个 XML 模式。此元素可以包含一个或多个 jaxrs:schemaLocation 元素,各自指定 XML 模式文件的位置(通常是 类路径 URL)。详情请查看 “模式验证”一节

jaxrs:resourceComparator

允许您注册自定义资源比较器,它实施用于匹配特定资源类或方法的传入 URL 路径的算法。

jaxrs:resourceClasses

(仅限蓝色打印) 如果想要从类名称创建多个资源,而不使用 jaxrs:server/@serviceClass 属性。jaxrs:resourceClasses 的子项必须是 元素,并且 name 属性设为资源类的名称。在这种情况下,这些类由 Apache CXF 进行实例化,而不是由 Blueprint 或 Spring 进行实例化。

[a] Invoker 实施控制如何调用服务。例如,它控制每个请求是否由服务实施的新实例处理,或者是否在调用期间保留状态。