首页 文章

REST - 支持多个可能的标识符

提问于
浏览
49

对于我正在处理的网站,我们正在改进一种资源的网址 - 特别是从数字ID转向唯一的描述性字符串 . 类似的例子是从通过数字数据库ID识别用户切换到通过用户名识别它们(不是我们的具体情况,而是类似的) . 因此,访问用户信息的URL看起来像:

/users/48573

现在它看起来像

/users/thisisausername.

对于API的传统消费者来说,唯一的问题是我们仍然需要能够以某种方式通过数字ID获取它们 . 我们不需要REST URL本身来重定向(例如 /users/48573 不应该重定向到 /users/thisisausername ),我们只需要一种方法来使用旧标识符获取正确的数据 . 该解决方案应该提供另一种方式来访问用户信息(方便地包括新标识符,用户名),或者通过ID访问用户名 . 一些可能的解决方案可能是

  • 使用节点指定一些替代识别方法,例如 /users/byid/48573

  • 使用查询参数指定一些替代的识别方法,例如 /users/48573?fetchby=id/users/48573?byid=true

  • 将id-id-id作为另一种资源处理,例如 /identifiers/username/48573

哪些(如果有的话)最接近正确的REST?你会如何处理这个问题?

5 回答

  • -3

    我认为添加路径段/前缀是最好的答案 . 由于这些是唯一的二级密钥,这与搜索(返回一组项目)不同,因此使用查询参数(未缓存)似乎不是最佳选择 .

    就个人而言,我打算使用由“=”分隔的路径段前缀,如“name =”或“email =”:

    user/123456
    user/name=john.doe
    user/email=john.doe@john.doe
    

    这在功能上等同于添加路径段(例如“user / name / john.doe”),但我觉得它更接近于概念模型 . 当然,这是一个无关紧要的细节,因为RESTful API无论如何都不应该指定固定的URI结构 .

    不使用查询参数也允许自然访问子资源:

    user/name=john.doe/inbox/df87bhJXrg63
    

    像Java的JAX-RS这样的框架支持使用你想要的任何分隔符:

    @GET
    @Path("user/{id}")
    User getUser(@PathParam("id") UUID id);
    
    @GET
    @Path("user/name={name}")
    User getUserByName(@PathParam("name") String name);
    
    @GET
    @Path("user/email={email}")
    User getUserByEmail(@PathParam("email") String email);
    
  • 29

    你的第一个选择可能是最好的 .

    按ID搜索用户:

    /users/id/48573
    

    按短名称搜索用户:

    /users/name/thisisausername
    

    如果他们省略了该路径参数,您可以始终默认使用新的短用户名格式 .

    我看到的另一个选项是使用如下的查询参数:

    /users?id=48573
    /users?name=thisisausername
    

    我认为第一个看起来更清洁,更具可读性 .

  • 0

    相当古老的问题,但我有同样的,并且finnaly找到了解决方案:在你的路径参数中使用正则表达式 .

    这是我编写该用例的方式

    @GET
    @Path("/{id : \\d+}")
    @Produces(APPLICATION_JSON)
    public Response getById(@PathParam("id") long id) {
     <<your code>>
    }
    
    @GET
    @Path("/{name}")
    @Produces(APPLICATION_JSON)
    public Response getByName(@PathParam("name") String name) {
     <<your code>>
    }
    
  • 15

    如果这是一个问题,那么您的API不是RESTful . 致quote Roy Fielding:

    REST API不能定义固定资源名称或层次结构(客户端和服务器的明显耦合) . 服务器必须能够自由控制自己的命名空间 . 相反,允许服务器通过在媒体类型和链接关系中定义这些指令来指示客户端如何构造适当的URI,例如在HTML表单和URI模板中完成的 . [这里的失败意味着客户端由于带外信息而假设资源结构,例如特定于域的标准,这是面向数据的,与RPC的功能耦合相当] . 应输入REST API,除了初始URI(书签)和适用于目标受众的标准化媒体类型集之外没有先验知识(即,任何可能使用API的客户端都应该理解) . 从那时起,所有应用程序状态转换必须由客户端选择服务器提供的选择来驱动,这些选择存在于接收的表示中或者由用户对这些表示的操纵所暗示 . 转换可以由客户端对媒体类型和资源通信机制的知识来确定(或限制),这两者都可以在运行中(例如,按需代码)进行改进 . [失败在这里意味着带外信息驱动交互而不是超文本 . ]

  • -3

    我会考虑使用可选后缀限定字符串:

    /users/48573/id
    
    /users/48573/name
    

    如果您收到不带后缀的字符串:

    /users/48573
    

    然后你检查字符串,看看它是一个ID或名称 .

    如果您只获得有效的ID而不是名称,那么它的ID是相当于以下内容的检索:

    /users/48573/id
    

    如果你只得到一个名字那么它是一个名称的检索,相当于:

    /users/48573/name
    

    如果您可以按ID或名称检索值,则返回300响应错误并返回指向客户端的两种可能性的链接:

    /users/48573/id
    
    /users/48573/name
    

    传统消费者继续“按原样”工作,除了偶尔出现重复的ID /名称对,他们收到新的300响应错误 .

相关问题