V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Renco
V2EX  ›  程序员

看了一堆的 Restful 的介绍 还是没太理解

  •  
  •   Renco · 2020-05-12 14:41:48 +08:00 · 4949 次点击
    这是一个创建于 1438 天前的主题,其中的信息可能已经有所发展或是发生改变。

    对于我目前项目中的 请求地址

    /user/add 用户新增
    /user/delete 用户删除
    /user/pageQuery 用户列表拆线呢
    /user/detail 用户详情
    全是 post 请求,这种算是 Restful 风格嘛

    我查了下相关介绍
    GET /products : will return the list of all products
    POST /products : will add a product to the collection
    GET /products/4 : will retrieve product #4
    PATCH/PUT /products/4 : will update product #4

    大概是请求地址相同 然后是根据 GET POST PUT 这种做交互的才是 Restful 么

    37 条回复    2020-05-13 15:32:28 +08:00
    WittBulter
        1
    WittBulter  
       2020-05-12 14:55:30 +08:00
    1. 不算。
    2. 请求地址相同也不能严格的算 RESTful 。接口的方式变化只是操作资源的表达方式,并非是对 RESTful 的判断依据。

    不是你用上了 PUT PATCH 就是 RESTful,而是你使用资源的抽象方式的接口风格概括。建议可以学习一下 GitHub API v3 。
    Mithril
        2
    Mithril  
       2020-05-12 14:59:18 +08:00   ❤️ 1
    你这个显然不是。
    你说的请求地址在 RESTful 里面代表某种资源,通过不同的 HTTP 方法来表示对资源的操作。
    不过在实际项目里面并不会完全按照 RESTful 来设计全部 API 。总会在 RESTful API 和瞎胡搞 API 之间取得一个平衡。主要是全部用 RESTful 来做的话,有些逻辑就会变得很奇怪,而且很难设计。
    godgrp
        3
    godgrp  
       2020-05-12 15:01:23 +08:00
    不是单纯的请求地址相同哦,而是把请求的目标看作是一个资源,使一个请求更语意化。建议地址上尽量不出现动词,动作由 Http Method 来表达。当然这是一个理想化的约定,因为仅仅是个约定或者是规范,并不是一个协议,没有强制约束的。
    fengerzh
        4
    fengerzh  
       2020-05-12 15:02:20 +08:00
    不是。改成:

    GET /users 获取所有用户列表
    GET /users/1 获取单个用户详情
    POST /users 新增用户
    PUT /users/1 修改用户
    DELETE /users/1 删除用户

    这样才是 RESTful
    ericgui
        5
    ericgui  
       2020-05-12 15:09:03 +08:00   ❤️ 1
    GET /users 获取所有用户列表
    POST /users 新增用户

    你能分得清这俩 API 的区别么
    kiracyan
        6
    kiracyan  
       2020-05-12 15:59:58 +08:00
    感觉 RESTful 适合对外公用接口,让 API 调用者更方便使用,内部 API 感觉完全按照 RESTful 风格,有些接口会变得很奇怪,有完整的使用 API 文档是不是 RESTful 感觉应该没什么太大差别
    useben
        7
    useben  
       2020-05-12 16:03:22 +08:00
    @ericgui 所以是动作操作是通过请求方法来判断, url 只是表示资源
    EastLord
        8
    EastLord  
       2020-05-12 16:07:05 +08:00
    还有接口的返回格式
    strawberryBug
        9
    strawberryBug  
       2020-05-12 16:08:41 +08:00
    简单理解,REST 是一种理想化的约定,规范,实际设计 api 可以不按照这个来。REST 里 URL 路径代表对具体资源的访问,http 请求的方式代表对该资源的操作。

    比如 /users 这个路径代表的就是对 user 资源的访问,采用 get 请求就是获取用户信息,采用 post 请求就是新增。

    两两对比着看下面的例子。
    GET /users 获取所有用户列表
    POST /users 新增用户

    GET /users/1 获取 id 为 1 用户
    PUT/users/1 修改 id 为 1 用户信息
    taaaang
        10
    taaaang  
       2020-05-12 16:11:27 +08:00
    restful 还有个意思就是尽可能规范得设计 url, 使用 http 协议。
    VDimos
        11
    VDimos  
       2020-05-12 16:12:52 +08:00 via Android
    post 和 get 一把梭
    noobsheldon
        12
    noobsheldon  
       2020-05-12 16:29:00 +08:00
    wonderful, beautiful, restful
    lolizeppelin
        13
    lolizeppelin  
       2020-05-12 16:44:35 +08:00   ❤️ 2
    对外 url 表现,只是壳,所以你不理解

    包括外面的壳在内..服务端的代码和设计都是适合 restful 方式的才算 restful

    比如你可以参考 openstack 的 neutron,这个项目的就是完完全全的 restful
    但是 openstack 的 nova 就不是 restful

    一个原因是 nova 比较早,当时没有按照 restful 的方式设计,还有一个问题是 nova 的 api 不是那么适合完全用 restful 表达


    如果你的业务适合用 restful 表达..那么对外接口和代码设计上可以有很强的一致性
    否则,不应该被规范束缚,就像不应该完完全全用范式来束缚数据库设计一样


    其实之前论坛里有个人非常精准的形容了 restful——对 sql 的劣质模仿
    SpencerCJH
        14
    SpencerCJH  
       2020-05-12 16:51:25 +08:00
    namelosw
        15
    namelosw  
       2020-05-12 16:55:30 +08:00
    1 不算,2 可以算 REST,但是这个是简单情况,后面有很多很难判断的,要把各种动作建模成资源。
    比如登陆不叫登陆叫 POST /sessions
    REST 看个基本就可以了,不用太纠结,很多东西用 REST 没法建模,比如搜索之类的。
    murmur
        16
    murmur  
       2020-05-12 16:57:20 +08:00   ❤️ 1
    实际开发中严格的 restful 反倒是撕逼的根源,大家的所谓 restful 都是留了后手的
    fkdog
        17
    fkdog  
       2020-05-12 16:59:30 +08:00
    一个资源设计风格而已。
    v2 上有的是这类把 restful 当成圣经一样跪拜的人。

    “你这 url 一点也不 restful,对不起我们不是一类人,我们追求不一样”。
    上述言论多见于一些毕业不过一两年的人。
    lookas2001
        18
    lookas2001  
       2020-05-12 17:11:01 +08:00 via Android
    @fkdog 我看了半天楼上的回复没看到你说的那一类人啊。

    回楼主,我的感觉 restful 就是从面向过程编程跃迁到面向对象编程。不是所有接口都能 restful,看着来吧。
    whusnoopy
        19
    whusnoopy  
       2020-05-12 17:29:36 +08:00   ❤️ 4
    在项目里尝试过,在 HTTP 时代被宽带运营商强 * 得不能自理,最后还是自己定义接口路径,并且全走 POST

    用 GET 的很多缺点

    1. 缓存。GET 请求在浏览器和运营商层面都会认为是不变的,那么是可以被缓存的,但是如果你修改了某个实体后,再 GET 这个实体,怎么保证能拿到的是新的?也可能你自己设置了合理的缓存时间,但是会被某些无良运营商缓存。这个要么就是加一个 `t=timestamp` 的随机串在后面避免缓存,但这样 GET 的意义是啥
    2. 无状态。按 Restful 的定义,GET 是无状态和幂等的,但是有些 GET 就是会影响其他数据,比如微博的阅读量被拿一次就应该加一,比如某些已读状态的标记,是从 GET 请求算,还是 GET 后客户端再 POST 或 PUT 一个请求来更新?只用 GET 就违反了无状态和幂等的原则
    3. 请求体大小。这个是早期浏览器的限制,GET 请求的请求参数不能超过 1024 个字节,如果遇上复杂一点的请求结构就挂了,还是只能走 POST
    Flywith24
        20
    Flywith24  
       2020-05-12 17:31:31 +08:00
    貌似 RESTful 没有 明确的定义?我的理解就是正确地使用 http
    dddd1919
        21
    dddd1919  
       2020-05-12 17:34:20 +08:00
    restful 宗旨是在请求的方式上体现你要做的动作,url 表名被操作的资源,类似动宾短语的意思

    比如
    要获取所有用户列表:GET /users
    获取用户 a 的信息 GET /users/a
    新建用户 POST /users
    更新用户 a 的信息 PUT /users/a
    删除用户 a DELETE /users/a
    stevenkang
        22
    stevenkang  
       2020-05-12 17:38:27 +08:00
    简单版:

    GET 查询数据,只读请求,支持幂等调用,对数据不产生任何影响

    POST 修改数据,增删改请求,对数据产生影响

    没有完全按照 RESTful 的规范来,但用请求 METHOD 区分一下,还是非常有必要的。
    passerbytiny
        23
    passerbytiny  
       2020-05-12 17:48:53 +08:00 via Android
    信息系统要想完整的用 RESTful,必须与领域模型结合起来。
    这些是面向资源库的操作,分别对应增加、删除、查询实体:
    POST /users
    DELETE /users/{id}
    GET /users?k=v&k=v GET /users/{id}

    这些是介于面向资源库和面向实体之间的操作,对资源库来说是修改指定实体,对实体来说是“维修”行为:
    PUT /users/{id} “整体换新”
    PATCH /users/{id} “换零件”

    前面的这些,基本上是通的。即使不是信息系统或者不使用领域模型,例如内容管理系统,当然最典型的还是万维网( www )资源体系,都是这样用(但是不同的背景有不同的具体含义)。而下面这些,则是领域模型专用的,并且是最主要的。他们面向实体,表示实体的一个行为:
    POST /users/{id}/eat
    POST /users/{id}/drink
    POST /users/{id}/shit
    POST /users/{id}/xuxu
    POST /users/{id}/sleep
    POST /users/{id}/... ...


    必须纠正一个误区,RESTful 不禁止动词。对于万唯网资源和内容管理系统来说,他们是只对资源做操作从而不会有动词,并不是禁止动词。而信息系统,不只是管理资源,还要支撑业务,是要用到动词的。

    手机敲字真累
    jswh
        24
    jswh  
       2020-05-12 18:21:23 +08:00
    RESTful 的核心是资源抽象,用 url 对应对应一个具体的抽象资源,目的是为了语义化(我看到 url 就知道啥意思,我想对一个资源做啥基本不用文档)。另外一个好处是通过 RESTful 可以表达资源之间的关系。狭义的 RESTful api 只是借用了 HTTP 的动词来做相关约定,基本上是约定俗成了。当然也可以不借用 HTTP 动词,用自己的动词形式:

    POST /products.retrieve : will return the list of all products
    POST /products.add : will add a product to the collection
    POST /products/4.retrieve : will retrieve product #4
    POST /products/4.update: will update product #4

    只不过这种私有私有约定并不友好。
    一个简单的判定是不是 RESTful 的方法就是,去掉了动词之后,剩下的 url 是不是你们业务中的一种资源的抽象。你的项目中的例子明显就违背了这一点。

    /user/pageQuery 用户列表拆线呢
    /user/detail 用户详情

    去掉了动词之后,都是 /user/,但他们明显不是一个东西。
    liangjx
        25
    liangjx  
       2020-05-12 18:34:45 +08:00
    @whusnoopy 老哥理解深刻
    stillyu
        26
    stillyu  
       2020-05-12 18:53:45 +08:00
    @lookas2001
    从面向过程编程跃迁到面向对象编程
    同意这个说法,运用了这个思想,url 和 http method 怎么定义,都可以团队内自己协商,也都算 restful
    SaigyoujiYuyuko
        27
    SaigyoujiYuyuko  
       2020-05-12 19:11:11 +08:00
    http 动词 + 资源
    S4msara
        28
    S4msara  
       2020-05-12 19:15:57 +08:00
    相同 path,不同 method,不同行为
    nutting
        29
    nutting  
       2020-05-12 19:18:47 +08:00
    我感觉最初就是 url 体现参数的一种风格
    hantsy
        30
    hantsy  
       2020-05-12 19:21:32 +08:00
    @jswh 不使用 Http Verb 就不能说是 REST API,你可以自称是 Web API 或者 Http API 。

    @Renco
    @WittBulter 其实自己的 REST API 质量很容易判断,可以自行搜索 Richardson Mature Model (网上介绍太多了),这是一个公认的判断 REST 质量的检测规则。自己比较一下自已设计的 API 到了哪个 Level,Level 2 以下的基本不叫 REST,Level 3 描述的 Self-documentation 特性是比较理想的状态(无需文档基础上可以清楚整个 API 的 schema 的树形结构),实际国外很多公开 API 都做到了( Github,Heroku 等)。国内大厂很多都是在 Level0,或者 Level1,V 站很多人在谈技术的时候往往不讨论技术本身,而是迷信某些大厂怎么做的,所以我一直觉得某些大厂把国内技术带歪了。

    另外, 国外已经有相当一部分 API 开始提供 GraphQL,GraphQL 违反 REST 一些设计规则,但是很好的解决 REST 在交换数据上颗粒度的问题。
    lewinlan
        31
    lewinlan  
       2020-05-12 20:45:47 +08:00 via Android
    在标准个瞎搞之间取得平衡+1
    至少做到利用 http 四个动词和状态码
    JaguarJack
        32
    JaguarJack  
       2020-05-13 08:25:38 +08:00 via iPhone
    这种当然不算 restful 只是一种标准而已 用不用是你的事儿
    ZSeptember
        33
    ZSeptember  
       2020-05-13 08:46:50 +08:00
    RESTful,本质上是使用资源的状态转移来实现业务,表现出来的形式就是对外暴露对资源的 CRUD
    如果,你的业务能用这种状态转移能表达,用还是很不错的,统一,标准
    ChanKc
        34
    ChanKc  
       2020-05-13 12:46:16 +08:00
    我觉得回帖中九成的人没有看到 restful 的本质。

    想一下你浏览 V2EX 的这个过程:你在浏览器输入 v2ex.com 或者从别的网站跳过来。服务器向你发送超媒体文本标记语言(也就是 html ),浏览器渲染后你可以看到这个帖子的链接,于是你知道你可以点这个链接从而看到这个帖子。作为人类你是自我驱动地去看到各种各样的超媒体(图片,链接,表单等等)并去获取各种各样你所要的信息。

    理想情况下的 restful 是这样子:你的客户端向 v2ex.com 请求(协议和方法不限),服务器响应的也是一个超媒体,包括一些信息和客户端接下来可以进行的行为。在“人类”的例子里就是 html 和<a>。你的客户端想要看关于 restful 的信息所以它请求了这个帖子的接口,从而获取到了信息。

    http 和 http 的方法只是方便了机器之间约定了请求的方法。但是 restful 可以不依赖于具体的网络协议和方法。如果服务器和客户端之间的交流是基于超媒体的,那么即便你全用 post 和 200 也可以是 restful api 。
    Yelp
        35
    Yelp  
       2020-05-13 12:48:36 +08:00
    请求方法对应 CRUD,然后参数合理放置:

    select * from users

    insert into users values(...users)

    select * from users where id = 1 limit 1

    update users set name = name where id = 1

    delete users where id = 1


    进阶:

    获取用户的收藏

    /users/:user_id/coll

    user = select * from users where id = 1 limit 1

    coll = select * from coll where user_id = user.id
    karlkor
        36
    karlkor  
       2020-05-13 15:14:12 +08:00
    RESTful 其实是一个没有固定规范的约定或者说命名风格,就像驼峰命名和下划线命名一样,语法上不是严格要求的,但是一般会遵循这种风格。
    比如 Python 里面定义一个变量 amount_of_apple = 10,当然也可以写成 amountOfApple = 10,解释器并不会报错,但是一般会按照第一种风格来写。同样的 HTTP 接口定义成 GET /object/1 或者 GET /object?id=1 都是可以解析的,但是设计接口的时候一般用前者多一些。
    no1xsyzy
        37
    no1xsyzy  
       2020-05-13 15:32:28 +08:00
    见到一说,就是在模拟(类比) Unix 文件系统
    GET /users = cat /users/*
    GET /users/1 = cat /users/1
    PUT /users/1 = echo ... > /users/1
    GET /users?name=John+Smith = grep "name: John Smith" /users/*
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1528 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 17:01 · PVG 01:01 · LAX 10:01 · JFK 13:01
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.