当前位置: 首页 > 知识库问答 >
问题:

REST检索特定元素子集的最佳实践

戈曾琪
2023-03-14

好的,我们都知道获取所有实体列表的其他方法是http/get/entities,获取单个实体的最佳方法是http/get/entities/{entityId},获取一些实体的最佳方法是http/get/entities/{entityId}?where=condition(*)对吗?

(*)我实际上是指/实体?where=condition

但是,当我们需要获取一组特定的实体时,如果多个HTTP/get实体/{entityId}由于延迟而不是一个选项,那么当我们需要获取一组特定的实体(相当于SQLSelect...where id在(id1,ID2...)时,什么是一个好的方法呢?

特别是我怎么能用RESTEasy来做呢

共有1个答案

农弘毅
2023-03-14

虽然你已经找到了一个解决方案,但我会发布一个答案,因为我不是一个公认的答案的大粉丝,原因我将在下面解释。诚然,这是一个相当固执己见的答案,因为HTTP规范允许多种方式来实现类似的事情,而REST并没有规定特定的URI样式,也为语义解释留下了大量的回旋余地。

超文本传输协议(HTTP)对于可能的URI参数的语义没有很好的描述性。pathquery参数是众所周知的,headermatrix参数经常被忽略,尽管JAX-RS(正如您最初要求的RESTeasy)可以像其他参数一样轻松地处理它们。

此外,REST是一种体系结构风格,而不是一种协议。要调用RESTful的服务(或API),它必须遵守几个约束,并尊重底层HTTP协议。由于REST是面向资源的,所以使用唯一的资源标识符来调用相应的资源(因此是URI)。但是,REST并没有对URI的设计方式设置任何约束。人类倾向于在一个好的URI设计中加入一些语义意义,尽管对于计算机来说,它只是一个进一步的字符串。

你在评论中写道:

我不是真的这么看。我所面对的大多数API都像我描述的那样工作(也许我用错了)。

根据我的评论,/entites/{entityId}?where=condition返回一个指定实体的子集,而不是实体的子集。通过在URI中指定{entityId}作为路径参数,您已经将结果集限制为单个实体。如果您打算首先返回一组与某个实体属性匹配的实体,为什么还要提供{entityId}

如果您有一个ID为user1的用户实体的JSON表示形式,如下所示:

{
    "firstName": "Tim",
    "lastName": "Sample",
    "address": {
        "street": "...",
        "zip": "...",
        "city": "...",
        "country": "..."
    }
}

调用get/user/user1?filter=lastname我希望查询在按地址f.e筛选时仅返回{“lastname”:“sample”}。我希望只返回address子资源,尽管在这种情况下我会使用/users/user1/address。类似get/user/user1?lastname=sample的内容可能被解释为检查所标识的用户是否具有所提供的名称,因此应该返回true或false作为响应。正如您所看到的,人类从语义上解释URI或其参数,而对于计算机来说,URI只包含子字符串,他们并不关心参数是作为路径参数、查询参数、矩阵参数还是头参数提供的。它们只是依赖于一些预定义的html" target="_blank">指令,这些指令告诉它们从哪里提取所需的信息。

对于被接受的解决方案,我担心的是,使用post时,您可以将任何内容发送到服务器。因此,您需要明确地记录需要发送到服务的预期表示以及服务器在接收到请求时将执行的行为。此外,在对查询使用post时,您将失去缓存响应的能力。后一个是REST拥有的为数不多的约束条件之一。虽然某些缓存框架不会在包含查询参数的URI上缓存响应,但是这个链接和这个答案都表明这更多的是一个城市传说,而不是现实。

但是,当我们需要获得一组特定的实体时,什么是好的方法呢?相当于SQL select...where id in(id1,id2...)当多个HTTP/GET实体/{entityId}由于延迟而不是一个选项时?

如另一篇文章所述,矩阵参数可以在路径段上指定,而不是像查询参数那样在整个URI上指定。这使得它们对于筛选URI的某些部分非常有用。如果你想退F.E.所有由灰色头发的教授开设的课程,您可以使用类似get/professors;haircolor=grey/courses的内容。当然,您可以将结构颠倒过来,使用类似/courses/professors?haircolor=grey,这在语法上是完全可以的,但如果您考虑哪种资源可以更容易地不存在其他资源,并且在更依赖的资源之前使用这些资源,那么您最终可能会使用前一种URI。

因此,您的问题的一个可能的解决方案可以是:get/entity;id={id1};id={id2};...。正如本答案中所解释的,在单个资源上使用查询或矩阵参数可能没有很大的区别,但如果您F.E.要仅返回指定用户集的所有地址,您可以使用以下命令:get/users;id={id1};id={id2}/addresss。这允许在使用HTTP GET时进行响应缓存,您还在语义上使用resource-subresource语法,其中在引用的资源之前使用更可能存在而不存在另一个的语法。

由于RESTeasy能够使用JAX-RS,因此可以使用@MatrixParam注释轻松地将矩阵参数注入到方法参数中。与@queryparam@pathparam参数一样,基础JAX-RS框架将尽力转换参数。

@GET
public Response getSomething(@MatrixParam List<String> ids) {
    ...
}

如果参数不能自动封送到对象中,您还可以使用@context批注注入uriinfo对象,然后通过相应的pathsegment批注该参数,检索矩阵参数,然后自行将其封送到对象中。

@GET
public Response getSomething(@Context UriInfo info) {
    for (PathSegment segment : info.getPathSegments()) {
        MultivaluedMap matrixParameters = segment.getMatrixParameters();
        ...
    }
}

由于PathSegment返回一个MultiValuedMap,所以同一个键能够返回多个值(作为列表),就像您想要插入DB查询的多个ID一样。uriinfo还在查找路径和查询参数时提供了multivaluedmap

因此,选择什么参数样式取决于您,REST并不指定特定的URI设计或语义。但是,我建议使用post,而不是使用get来减少向服务发送查询所需的文档开销,并获得缓存返回的响应的能力。

 类似资料:
  • 当单击的elemenet是父元素的最后一个子元素时,我要显示报警。我的HTML结构: 在本例中,我希望在单击该元素(父行的最后一个元素)时显示报警: 我知道我可以使用这样的somethink获得最后一个元素(但我不能在我的例子中使用这个): 我想试着做这样的事,但每次都是假的

  • 我最近在一次面试中进行了一次编码测试。我被告知: 有一个100万int的大型未排序数组。用户想要检索K个最大的元素。您将实现什么算法? 在这期间,有人强烈暗示我需要对数组进行排序。 所以,如果性能真的很重要,我建议使用内置的或自定义实现。然后我被告知,使用或数组来存储最大和for循环,可以实现大约,事后看来,我认为这是,因为每次迭代都需要与大小的数组进行比较以找到要替换的最小元素,而对数组进行排序

  • 问题内容: Java中是否有一种方法,只需指定开始索引和结束索引,即可将对象列表从Arraylist获取到另一个ArrayList? 问题答案: 是的,您可以使用以下方法: 这将返回原始列表那部分的视图,它不会复制数据。 如果要复制:

  • 我有以下问题,例如:给定一个带有符号 的桶和一本菜谱来创建配对,例如: 从桶中选择最佳配对,在桶中保留尽可能少的符号。因此,使用上面的示例值,最佳配对将是: ,它将使用给定的所有符号。 从桶中简单地选取可能导致类似于: 使得和不匹配。和无法匹配,因为该书不包含该特定连接的制作方法 注: 实际问题平均包含:桶中500个元素,约30种符号。 我们已经尝试使用bruteforce算法来实现这个解决方案,

  • 但是,有一种情况是,指定的时间落在该时区的夏令时内。在上述时区中,从4月到10月遵循夏令时,偏移量为(+10.30)。那么,如果我必须获得9月份的数据,客户是否应该提供基于日期的必要的偏移(2月的日期为+9.30,9月的日期为+10.30)? 或者客户端是否应该以当前时区的偏移量发送日期(不受日光影响),服务器是否应该负责识别夏令时的日期,并在处理之前将该日期标准化一小时?怎样处理这样的案件才是适