46.6. 资源选择方法


概述

给定 URI 可以映射到一个或多个资源方法。例如,URI customerservice/12/ma 可以与模板 @Path ("customerservice/{id}")@Path ("customerservice/{id}/{state}/{state}") 匹配。JAX-RS 指定与请求匹配的资源方法的详细算法。该算法将规范化 URI、HTTP 动词和请求和响应实体的介质类型与资源类上的注解进行比较。

基本选择算法

JAX-RS 选择算法分为三个阶段:

  1. 确定 root 资源类。

    请求 URI 与使用 @Path 注释的所有类进行匹配。其 @Path 注释与请求 URI 相匹配的类是决定的。

    如果资源类 @Path 注释的值与整个请求 URI 匹配,则类的方法将用作第三个阶段的输入。

  2. 确定对象将处理请求。

    如果请求 URI 大于所选类的 @Path 注释的值,则使用资源方法的 @Path 注解的值来查找可以处理请求的子资源。

    如果一个或多个子资源方法与请求 URI 匹配,则这些方法将用作第三个阶段的输入。

    如果请求 URI 的唯一匹配是子资源定位器,则由子资源定位器创建的对象的资源方法与请求 URI 匹配。这个阶段会重复,直到子资源方法与请求 URI 匹配为止。

  3. 选择处理请求的资源方法。

    其 HTTP 动词注解与请求中的 HTTP 动词匹配的资源方法。另外,所选的资源方法必须接受请求实体正文的介质类型,并能够生成符合请求中指定的介质类型的响应。

从多个资源类中选择

选择算法的前两个阶段决定了将处理请求的资源。在某些情况下,资源由资源类实现。在其他情况下,它由使用同一 URI 模板的一个或多个子资源实现。当有多个资源与请求 URI 匹配时,资源类优先于子资源。

如果在资源类和子资源之间排序后,多个资源仍然与请求 URI 匹配,则以下条件用于选择单个资源:

  1. 优先选择在其 URI 模板中具有最多文字字符的资源。

    字面字符是不是模板变量一部分的字符。例如: /widgets/{id}/{color} 具有十个字面字符,/widgets/1/{color} 具有 eleven literal 字符。因此,请求 URI /widgets/1/red 将与具有 /widgets/1/{color} 的资源匹配,作为其 URI 模板。

    注意

    尾部斜杠(/)计为字面字符。因此,/joefred/ 将优先于 /joefred

  2. 首选资源在其 URI 模板中使用最多变量。

    请求 URI /widgets/30/green 可以同时匹配 /widgets/{id}/{color}/widgets/{amount}/。但是,将选择带有 URI 模板 /widgets/{id}/{color} 的资源,因为它有两个变量。

  3. 首选使用包含正则表达式的最多变量的资源。

    请求 URI /widgets/30/green 可以同时匹配 /widgets/{number}/{color}/widgets/{id:.}/{color}*。但是,将选择带有 URI 模板 */widgets/{id:.}/{color} 的资源,因为它有一个包含正则表达式的变量。

从多个资源方法中选择

在很多情况下,选择与请求 URI 匹配的资源会导致单个资源方法可以处理请求。该方法通过将请求中指定的 HTTP 动词与资源方法的 HTTP 动词匹配来确定。除了具有适当的 HTTP 动词注解外,所选的方法还必须处理请求中包含的请求实体,并且能够生成在请求的元数据中指定的正确响应类型。

注意

资源方法可以处理的请求实体的类型由 @Consumes 注释指定。资源方法可以生成的响应类型使用 @Produces 注释来指定。

在选择资源时,会生成可处理请求的多种方法,该条件用于选择处理请求的资源方法:

  1. 首选资源方法超过子资源。
  2. 首选子资源方法而不是子资源定位器。
  3. 首选使用 @Consumes 注释和 @Produces 注释中最具体值的方法。

    例如,具有注解 @Consumes ("text/xml") 的方法优先于带有注解 @Consumes ("textAttr") 的方法。这两种方法优先于没有 @Consumes 注释或注解 @Consumes ("\ consider") 的方法。

  4. 首选与请求正文实体的内容类型匹配的方法。

    注意

    请求正文实体的内容类型在 HTTP Content-Type 属性中指定。

  5. 优先选择与作为响应接受的内容类型匹配的方法。

    注意

    在 HTTP Accept 属性中指定作为响应接受的内容类型。

自定义选择过程

在某些情况下,开发人员报告了选择多个资源类的方式有一定的限制。例如,如果给定资源类匹配,并且此类没有匹配的资源方法,则算法将停止执行。它永远不会检查剩余的匹配资源类。

Apache CXF 提供 org.apache.cxf.jaxrs.ext.ResourceComparator 接口,可用于自定义运行时如何处理多个匹配资源类。ResourceComparator 接口(如 例 46.9 “用于自定义资源选择的接口” 所示)需要实施的方法。一个比较两个资源类,另一个则比较两个资源方法。

例 46.9. 用于自定义资源选择的接口

package org.apache.cxf.jaxrs.ext;

import org.apache.cxf.jaxrs.model.ClassResourceInfo;
import org.apache.cxf.jaxrs.model.OperationResourceInfo;
import org.apache.cxf.message.Message;

public interface ResourceComparator
{
  int compare(ClassResourceInfo cri1,
              ClassResourceInfo cri2,
              Message message);

  int compare(OperationResourceInfo oper1,
              OperationResourceInfo oper2,
              Message message);
}

自定义实现在两个资源之间进行选择,如下所示:

  • 如果第一个参数与第二个参数更匹配,则返回 1
  • 如果第二个参数与第一个参数匹配,则返回 -1

如果返回 0, 则运行时将继续默认的选择算法

您可以通过将 resourceComparator 子添加到服务的 jaxrs:server 元素来注册自定义资源Comparator 实现。

Red Hat logoGithubRedditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

© 2024 Red Hat, Inc.