何时使用@QueryParam vs @PathParam

时间:2012-07-19 00:18:57

标签: java rest jax-rs

我不是在问这里已经问过的问题: What is the difference between @PathParam and @QueryParam

这是“最佳做法”或惯例问题。

您何时使用@PathParam vs @QueryParam

我能想到的是,决定可能会使用这两者来区分信息模式。让我在下面说明我的LTPO - 不是完美的观察。

PathParam的使用可以保留给信息类别,它可以很好地融入信息树的一个分支。 PathParam可用于深入到实体类层次结构。

然而,可以保留QueryParam来指定属性以定位类的实例。

例如,

  • /Vehicle/Car?registration=123
  • /House/Colonial?region=newengland

/category?instance

@GET
@Path("/employee/{dept}")
Patient getEmployee(@PathParam("dept")Long dept, @QueryParam("id")Long id) ;

vs /category/instance

@GET
@Path("/employee/{dept}/{id}")
Patient getEmployee(@PathParam("dept")Long dept, @PathParam("id")Long id) ;

vs ?category+instance

@GET
@Path("/employee")
Patient getEmployee(@QueryParam("dept")Long dept, @QueryParam("id")Long id) ;

我不认为有这样做的标准惯例。在那儿?但是,我想知道人们如何使用PathParam与QueryParam来区分他们的信息,就像上面举例说明的那样。我也很想知道这种做法背后的原因。

17 个答案:

答案 0 :(得分:217)

REST可能不是这样的标准,但阅读一般REST文档和博客文章应该为您提供一些构建API URL的好方法的指南。大多数rest API往往只在路径中包含资源名称和资源ID。如:

/departments/{dept}/employees/{id}

某些REST API使用查询字符串进行过滤,分页和排序,但由于REST不是严格的标准,我建议您检查一些REST API,例如githubstackoverflow并查看什么可以很好地适用于您的用例。

我建议在路径中放置任何必需的参数,任何可选参数当然应该是查询字符串参数。在尝试编写匹配不同组合的URL处理程序时,将可选参数放在路径中会变得非常混乱。

答案 1 :(得分:79)

这就是我的工作。

如果存在基于id检索记录的方案,例如,您需要获取id为15的员工的详细信息,那么您可以拥有@PathParam的资源。

GET /employee/{id}

如果您需要获取所有员工的详细信息,但一次只能获取10个,您可以使用查询参数

GET /employee?start=1&size=10

这表示启动员工ID 1可获得10条记录。

总结一下,使用@PathParam进行基于id的检索。用户@QueryParam用于过滤器,或者如果您有任何用户可以传递的固定选项列表。

答案 2 :(得分:40)

我认为如果参数标识特定实体,则应使用路径变量。例如,要获取我的博客上的所有帖子,我请求

GET: myserver.com/myblog/posts

要获取id = 123的帖子,我会请求

GET: myserver.com/myblog/posts/123

但要过滤我的帖子列表,并获得自2013年1月1日起的所有帖子,我会要求

GET: myserver.com/myblog/posts?since=2013-01-01

在第一个示例中,“posts”标识特定实体(整个博客帖子集合)。在第二个示例中,“123”也表示特定实体(单个博客帖子)。但在最后一个示例中,参数“since = 2013-01-01”是过滤帖子集合而不是特定实体的请求。分页和排序是另一个很好的例子,即

GET: myserver.com/myblog/posts?page=2&order=backward

希望有所帮助。 : - )

答案 3 :(得分:7)

您可以使用查询参数进行过滤和路径参数进行分组。以下链接有关此When to use pathParams or QueryParams

的详细信息

答案 4 :(得分:7)

我个人使用“如果用户为包含这些参数的URL添加书签然后使用PathParam”的方法。

例如,如果用户配置文件的URL包含某个配置文件ID参数,由于这可以由用户添加书签和/或通过电子邮件发送,我将该配置文件ID作为路径参数包含在内。此外,另一个值得考虑的是,由URL表示的包含路径参数的页面不会改变 - 用户将设置他/她的个人资料,保存它,然后不太可能从那里改变那么多;这意味着webcrawlers / search engines / browsers / etc可以根据路径很好地缓存这个页面。

如果在URL中传递的参数可能会更改页面布局/内容,那么我将其用作查询参数。例如,如果配置文件URL支持指定是否显示用户电子邮件的参数,我会认为这是一个查询参数。 (我知道,可以说,你可以说&noemail=1或它的任何参数都可以用作路径参数并生成2个单独的页面 - 一个带有电子邮件,一个没有它 - 但从逻辑上讲,这是不是这样的:它仍然是显示或没有显示某些属性的相同页面。

希望这会有所帮助 - 我很欣赏这种解释可能有点模糊:)

答案 5 :(得分:4)

这是一个非常有趣的问题。

您可以同时使用它们,但没有关于此主题的任何严格规则,但使用URI路径变量有一些优点:

  • 缓存: 互联网上的大多数Web缓存服务在包含查询参数时不会缓存GET请求。 他们这样做是因为有很多RPC系统使用GET请求来更改服务器中的数据(失败!!获取必须是一种安全的方法)

但是如果你使用路径变量,所有这些服务都可以缓存你的GET请求。

  • 层次: 路径变量可以表示层次结构: /城市/街道/地点

它为用户提供了有关数据结构的更多信息。

但是如果您的数据没有任何层次结构关系,您仍然可以使用路径变量,使用逗号或分号:

/城市/经度,纬度

通常,当参数的排序很重要时使用逗号,当排序不重要时使用分号:

/ IconGenerator /红色;蓝色;绿色

除了这些原因之外,在某些情况下,使用查询字符串变量非常常见:

  • 当您需要浏览器自动将HTML表单变量放入URI
  • 当您处理算法时。例如,Google引擎使用查询字符串:

http:// www.google.com/search?q=rest

总而言之,没有任何强有力的理由使用其中一种方法,但只要有可能,请使用URI变量。

答案 6 :(得分:2)

正如人们所说,REST不是标准。但是,如果您希望实现基于标准的URI约定,则可以考虑使用oData URI convention。 Ver 4已经approved as an OASIS standard,并且存在用于各种语言的oData的库,包括通过Apache Olingo的Java。不要让它从微软产生的事实让你失望,因为它的gained support from other industry player's as well包括Red Hat,Citrix,IBM,Blackberry,Drupal,Netflix Facebook和SAP < / p>

More adopters are listed here

答案 7 :(得分:1)

原因其实很简单。使用查询参数时,您可以使用&#34; /&#34;等字符。并且您的客户端不需要对它们进行html编码。还有其他原因,但这是一个简单的例子。至于何时使用路径变量。我会说每当你处理id或路径变量是查询的方向时。

答案 8 :(得分:1)

  1. @QueryParam可以方便地与默认值注释一起使用,以便在没有传递查询参数时可以避免空指针异常。
  2. 当您想要从GET请求解析查询参数时,您可以简单地为将处理GET请求的方法定义相应的参数,并使用@QueryParam注释对其进行注释

    1. @PathParam提取URI值并匹配@Path。因此得到输入参数。 2.1 @PathParam可以多于一个,并设置为方法参数

      @Path("/rest")
      public class Abc {
      
          @GET
          @Path("/msg/{p0}/{p1}")
          @Produces("text/plain")
          public String add(@PathParam("p0") Integer param1, @PathParam("p1")  Integer param2 )
          {
              return String.valueOf(param1+param2);
          }
      } 
      
    2. 在上面的例子中,
      http://localhost:8080/Restr/rest/msg/{p0}/{p1}
      p0匹配param1p1匹配param2。所以对于URI
      http://localhost:8080/Restr/rest/msg/4/6
      我们得到结果10

      在REST服务中,JAX-RS提供@QueryParam@FormParam两者来接受来自HTTP请求的数据。 HTTP表单可以通过GET和POST等不同方法提交。

      @QueryParam:接受GET请求并从查询字符串中读取数据。

      @FormParam:接受POST请求并从HTML表单或媒体的任何请求中提取数据

答案 9 :(得分:1)

From Wikipedia: Uniform Resource Locator

路径,其中包含数据,通常以分层形式组织,显示为由斜线分隔的一系列段。

可选查询,与前一部分隔开一个问号(?),其中包含非分层数据的查询字符串。

- 根据URL的概念设计,我们可以为分层数据/指令/定位器组件实现PathParam,或者在数据不是分层时实现QueryParam。这是有道理的,因为路径是自然排序的,而查询包含可以任意排序的变量(无序变量/值对)。

之前的一位评论者写道,

  

我认为如果参数识别特定实体,则应使用路径变量。

另一位写道,

  

使用@PathParam进行基于id的检索。用户@QueryParam用于过滤器,或者如果您有任何用户可以传递的固定选项列表。

另一个,

  

我建议在路径中放置任何必需的参数,任何可选参数都应该是查询字符串参数。

- 但是,人们可能会实施灵活的非分层系统来识别特定实体!可能在SQL表上有多个唯一索引,并允许使用包含唯一索引的任何字段组合来标识实体!不同的组合(可能也以不同方式排序)可用于来自各种相关实体(引用者)的链接。在这种情况下,我们可能正在处理非分层数据,用于识别单个实体 - 或者在其他情况下,可能只指定某些变量/字段 - 唯一索引的某些组件 - 并检索列表/记录集。在这种情况下,将URL实现为QueryParams可能更容易,更合理,更合理。

长十六进制字符串是否可以稀释/减少路径其余部分中关键字的值?它可能值得considering the potential SEO implications of placing variables/values in the path, or in the query,以及我们是否希望用户能够通过编辑地址栏的内容来遍历/探索URL层次结构的人机界面含义。我的404 Not Found页面使用SSI变量自动将损坏的URL重定向到其父级!搜索机器人也可能遍历路径层次结构。 另一方面,当我在社交媒体上共享URL时,我手动删除任何私有唯一标识符 - 通常是通过从URL中截断查询,只留下路径:在这种情况下,放置唯一标识符有一些实用工具在路径中而不是在查询中。我们是否希望将路径组件的使用简化为粗略的用户界面,可能取决于数据/组件是否是人类可读的。人类可读性问题在某种程度上与层次结构问题有关:通常,可以表示为人类可读关键字的数据也是分层的;而分层数据通常可以表示为人类可读的关键字。 (搜索引擎本身可能被定义为增加URL作为用户界面的使用。)关键字或指令的层次结构可能没有严格的排序,但它们通常足够接近我们可以覆盖路径中的替代案例,{{{ 3}}

我们可能会根据每个请求的网址回答几种问题:

  1. 我们要求/服务的记录/事情是什么?
  2. 我们感兴趣的是哪一个?
  3. 我们如何呈现信息/记录?
  4. Q1几乎可以肯定是路径或PathParams最好的。 Q3(可能是通过一组任意排序的可选参数和默认值控制的);几乎可以肯定是QueryParams最好的。 Q2:这取决于......

答案 10 :(得分:1)

您可以支持查询参数和路径参数,例如,在资源聚合的情况下 - 当子资源的集合本身有意义时。

/departments/{id}/employees
/employees?dept=id

查询参数可以支持分层和非分层子集;路径参数只是分层的。

资源可以展示多个层次结构。如果您要查询跨越分层边界的广泛子集,则支持短路径。

/inventory?make=toyota&model=corolla
/inventory?year=2014

使用查询参数组合正交层次结构。

/inventory/makes/toyota/models/corolla?year=2014
/inventory/years/2014?make=toyota&model=corolla
/inventory?make=toyota&model=corolla&year=2014

在组合的情况下仅使用路径参数 - 当资源与其父项离婚时没有意义,并且所有子项的全局集合本身不是有用的资源。

/words/{id}/definitions
/definitions?word=id   // not useful

答案 11 :(得分:1)

路径参数 - 路径参数是 URL 路径中的一个变量,有助于指向某些特定资源。

Example - https://sitename.com/questions/115

这里,如果 115 是路径参数,则可以将其更改为其他有效数字,以获取/指向同一应用程序上的其他资源。

查询参数 - 查询参数是 URL 路径中的变量,用于从列表中过滤某些特定资源。

Example - https://sitename.com/questions/115?qp1=val1&qp2=val2&qp3=val3

这里的 qp1、qp2 和 qp3 是查询变量,它们的值分别为 val1、val2 和 val3。这些可用于在获取/保存我们的数据时用作过滤器。查询变量总是附加在 URL 中的问号 (?) 之后。

答案 12 :(得分:0)

我在使用@Queryparam@pathparam

的时候给出了一个问题。

例如,我正在接受一个资源是carResource

如果你想让你的资源方法的输入变为manadatory,那么使用param类型作为@pathaparam,如果你的资源方法的输入应该是可选的,那么保持那个param类型为@QueryParam param < / p>

@Path("/car")
class CarResource
{
    @Get
    @produces("text/plain")
    @Path("/search/{carmodel}")
    public String getCarSearch(@PathParam("carmodel")String model,@QueryParam("carcolor")String color) {
        //logic for getting cars based on carmodel and color
            -----
        return cars
    }
}

此资源传递请求

req uri ://address:2020/carWeb/car/search/swift?carcolor=red

如果你给这样的req,资源将提供基于汽车的型号和颜色

 req uri://address:2020/carWeb/car/search/swift

如果你给这样的req,resoce方法将只显示基于swift模型的汽车

req://address:2020/carWeb/car/search?carcolor=red

如果你这样给我们将获得ResourceNotFound异常,因为在汽车资源类中我将carmodel声明为@pathPram,你必须并且应该将carmodel作为reQ uri,否则它将不会将req传递给resouce但是如果你没有传递颜色,它也会将req传递给资源,因为颜色是@quetyParam,它在req中是可选的。

答案 13 :(得分:0)

简而言之,

@Pathparam适用于传递Resources和Query String的值

  • /用户/ 1
  • /用户?ID = 1

@Queryparam适用于仅传递查询字符串的值

  • /用户?ID = 1

答案 14 :(得分:0)

在讨论QueryParam和PathParam之前。首先让我们了解URL及其组成。 URL由端点+资源+ queryParam / PathParam组成。

例如,

URL: https://app.orderservice.com/order?order=12345678

URL: https://app.orderservice.com/orders/12345678

其中

端点:https://app.orderservice.com

资源:订单

queryParam:order = 12345678

PathParam:12345678

@QueryParam:

QueryParam用于要求基于某些条件/条件过滤请求的情况。用?指定标准。 URL中的资源之后。可以使用&符号在queryParam中指定多个过滤条件。

例如:

https://app.orderservice.com/orders?order=12345678 & customername=X

@PathParam:

PathParam用于要求根据guid / id选择特定订单的情况。 PathParam是URL中资源的一部分。

例如:

https://app.orderservice.com/orders/12345678

答案 15 :(得分:0)

对于资源名称和ID,我使用@PathParams。对于可选变量,我使用@QueryParams

答案 16 :(得分:0)

据我所知:

  1. 使用 @PathParam - 当它是一个必需项时,例如 Id

    GET /balloon/{id}

  2. 使用 @QueryParam - 当您拥有确切的资源但需要根据一些可选特征(例如颜色、大小等)对其进行过滤时。

    GET /balloon/123?color=red&size=large