何时使用@QueryParam和@PathParam


276

我不是在问这里已经问过的问题: @PathParam和@QueryParam有什么区别

这是一个“最佳做法”或约定俗成的问题。

当你使用@PathParamVS @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) ;

/category/instance

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

?category+instance

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

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


Answers:


245

REST可能不是一个标准,但是阅读一般的REST文档和博客文章应该为您提供一些指导,以指导您构建API URL。大多数其余的API往往在路径中只有资源名称和资源ID。如:

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

某些REST API使用查询字符串进行过滤,分页和排序,但是由于REST不是严格的标准,因此我建议您检查一些REST API,例如githubstackoverflow,然后看看哪种方法可以很好地满足您的用例。

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


73
我建议在路径中放置任何必需的参数,并且任何可选参数当然应该是查询字符串参数。 ”-赞许+1是def
smeeb 2015年

1
如果此约定也应用于Put请求,可以说我们要更新db实体的特定版本,如果URI是PUT /depatments/{dept}/employees/{id}/{version},版本是可选的,还是应该是 PUT /depatments/{dept}/employees/{id}?version=12,版本是可选的
最好祝愿

在这种情况下,我建议:- PUT /depatments/{dept}/employees/{id}/versions/{version}创建具有所选版本POST /depatments/{dept}/employees/{id}/versions的员工- 创建具有由后端确定的版本的员工
Guillaume Vauvert

90

这就是我的工作。

如果存在根据ID检索记录的方案,例如,您需要获取ID为15的员工的详细信息,则可以使用@PathParam获取资源。

GET /employee/{id}

如果在某些情况下需要一次获取所有员工的详细信息,但一次只能获取10个,则可以使用查询参数

GET /employee?start=1&size=10

这表示起始员工ID 1获得10条记录。

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


'@PathParam'和'@QueryParam'是否提供相同的功能?“ @QueryParam”只是另一种写同一件事的方式吗?
Rishabh Agarwal

1
尽管@RishabhAgarwal都提供相同的功能,但是干净的代码习惯是建议将必需的参数作为路径变量,将任何可选的参数作为查询参数。
Akhil Ghatiki,

@RishabhAgarwal有关更多信息,请参阅我的文章Rest API Best Practices
Arun B Chandrasekaran

43

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

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

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

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

希望能有所帮助。:-)


8

我个人使用了“如果用户将包含这些参数的URL标记为书签,然后使用PathParam”的方法。

例如,如果用户个人资料的URL包含一些个人资料ID参数,由于它可以由用户添加书签和/或通过电子邮件发送,因此,我将该个人资料ID作为路径参数包含在内。另外,对此的另一个考虑是,由URL表示的包含路径参数的页面不会更改-用户将设置他/她的个人资料,将其保存,然后不太可能在那里进行大量更改;这意味着网络爬虫/搜索引擎/浏览器/等可以根据路径很好地缓存此页面。

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

希望这会有所帮助-我感谢解释可能有点模糊:)


我认为此答案使资源与路线混淆。问题是关于REST API的资源(通常返回JSON或XML),而不是Web应用程序的路由,它可以帮助您在应用程序中导航。
汉普斯


5

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

您可以同时使用它们,对此主题没有严格的规定,但是使用URI路径变量具有一些优点:

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

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

  • 层次结构:路径变量可以表示层次结构:/ City / Street / Place

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

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

/城市/经度,纬度

通常,在参数顺序重要时使用逗号,在顺序无关紧要时使用分号:

/ IconGenerator /红色;蓝色;绿色

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

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

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

综上所述,没有充分的理由使用其中一种方法,但是只要有可能,就使用URI变量。



2

来自维基百科:统一资源定位器

包含数据的路径通常以层次结构形式组织该数据,该数据显示为一系列由斜杠分隔的段。

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

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

以前的评论者写道:

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

另一个写道

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

另一个,

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

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

长的十六进制字符串会稀释/减小路径其余部分中关键字的值吗?可能值得考虑将变量/值放置在路径或查询中的潜在SEO含义,以及人机界面的含义,即我们是否希望用户能够通过编辑地址栏的内容来遍历/探索URL的层次结构。我的404找不到页面使用SSI变量自动将损坏的URL重定向到其父级!搜索机器人可能还会遍历路径层次结构。另一方面,就我个人而言,当我在社交媒体上共享URL时,我会手动去除所有私有唯一标识符-通常是通过截断URL中的查询,仅保留路径:在这种情况下,有一些实用程序可用于放置唯一标识符在路径而不是查询中。我们是否要促进将路径组件用作原始用户界面,可能取决于数据/组件是否为人类可读。人类可读性的问题在某种程度上与等级问题有关:通常,可以表示为人类可读关键字的数据也是分层的;而分层数据通常可以表示为人类可读的关键字。(搜索引擎本身可能被定义为增加URL作为用户界面的使用。)关键字或指令的层次结构可能没有严格排序,但是它们通常足够接近,因此我们可以涵盖路径中的其他情况,并且将一个选项标记为“规范”情况

从根本上讲,我们可以针对每个请求的URL回答几种问题:

  1. 我们要求/提供什么样的记录/东西?
  2. 我们对哪一个感兴趣?
  3. 我们如何展示信息/记录?

几乎可以肯定,路径或PathParams最好覆盖Q1。Q3(可能由一组任意排序的可选参数和默认值控制);几乎可以肯定,QueryParams可以最好地覆盖它。Q2:这取决于...


2

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

/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

1

原因实际上很简单。使用查询参数时,可以输入诸如“ /”之类的字符,并且客户端不需要对它们进行html编码。还有其他原因,但这只是一个简单的例子。至于何时使用路径变量。我想说的是,无论何时您要处理id或path变量是查询的方向。


1

我给一个例子,我们何时使用@Queryparam@pathparam

例如我正在上一carResource堂课

如果要强制使用resouce方法的输入,则将param类型用作@pathaparam,如果resource方法的输入应该是可选的,则将该参数类型保留为@QueryParamparam

@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 uri://address:2020/carWeb/car/search/swift

如果您这样提供req,则resoce方法将仅显示基于快速模型的汽车

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

如果您这样给出,我们将得到ResourceNotFound异常,因为在汽车资源类中我声明了carmodel,@pathPram因为您必须并且应该将汽车模型指定为reQ uri,否则它将无法通过req进行资源化,但是如果您不通过颜色它也会将req传递给资源,为什么因为颜色是@quetyParamreq中的可选颜色。


0
  1. @QueryParam 可以方便地与“默认值”注释一起使用,以便在没有传递查询参数的情况下避免出现空指针异常。

当您想解析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);
        }
    } 

在上述例子中,
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表单或媒体的任何请求中获取数据


0

简而言之,

@Pathparam 适用于通过资源和查询字符串传递值

  • /user/1
  • /user?id=1

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

  • /user?id=1
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.