zoukankan      html  css  js  c++  java
  • RESTful Web API 实践

     

    REST 概念来源

      网络应用程序,分为前端和后端两个部分。当前的发展趋势,就是前端设备层出不穷(手机、平板、桌面电脑、其他专用设备...)。 因此,必须有一种统一的机制,方便不同的前端设备与后端进行通信。这导致 API 构架的流行,甚至出现"API First"的设计思想。

    2000 年,Roy Thomas Fielding 博士在他那篇著名的博士论文 《Architectural Styles and the Design of Network-based Software Architectures》中提出了几种软件应用的架构风格。 REST 作为其中的一种架构风格在这篇论文的第5章中进行了概括性的介绍。

    REST 是一种很笼统的概念,它代表一种架构风格。 对于多个 Web 应用采用的架构,我们只能说其中某一个比其它的更具有 REST 风格, 而不能简单粗暴地说:“它采用了 REST 架构而其它的没有”。 为了将 REST 真正地落地,Lenoard Rechardson & Sam Ruby 在《RESTful Web Services》一书中 提出了一种名为“面向资源的架构(ROA: Resource Oriented Architecture)”。 该书中介绍了一些采用 ROA 架构的 Web 服务应该具备的基本特征。

    RESTful Web API 设计只是 REST 风格架构设计中的一个环节,并没有统一的标准。下面介绍的是一些比较没有争议的实践原则。

    实践原则

    1.版本化你的 API

      应该尽量将 API 部署在专用域名之下。

        https://api.example.com
    

      如果确定 API 很简单,不会有进一步扩展,可以考虑放在主域名下。

        https://example.org/api/
    

      应该将 API 的版本号放入 URL。

        https://api.example.com/v1/
    

      另一种做法是,将版本号放在 HTTP 头信息中,但不如放入 URL 方便和直观。Github 采用这种做法。

    2.URI 使用名词和 ID 而不是动词

      在 RESTful 架构中,每个网址代表一种资源(resource),所以网址中不能有动词,只能有名词, 而且所用的名词往往与数据库的表格名对应。 一般来说,数据库中的表都是同种记录的"集合"(collection),所以 API 中的名词也应该使用复数。

    举例来说,有一个 API 提供动物园(zoo)的信息,还包括各种动物和雇员的信息,则它的路径应该设计成下面这样。

        https://api.example.com/v1/zoos
        https://api.example.com/v1/animals
        https://api.example.com/v1/employees
    

    3.使用 HTTP 协议标准动词改变状态

      使用 PUT, POST 和 DELETE 方法 而不是 GET 方法来改变状态。 对于资源的具体操作类型,由 HTTP 动词表示。

      常用的 HTTP 动词有下面五个(括号里是对应的 SQL 命令)。

        GET(SELECT):从服务器取出资源(一项或多项)。
        POST(CREATE):在服务器新建一个资源。
        PUT(UPDATE):在服务器更新资源(客户端提供改变后的完整资源)。
        PATCH(UPDATE):在服务器更新资源(客户端提供改变的属性)。
        DELETE(DELETE):从服务器删除资源。
    

      还有两个不常用的 HTTP 动词。

        HEAD:获取资源的元数据。
        OPTIONS:获取信息,关于资源的哪些属性是客户端可以改变的。
    

      下面是一些例子。

        GET /zoos:列出所有动物园
        POST /zoos:新建一个动物园
        GET /zoos/ID:获取某个指定动物园的信息
        PUT /zoos/ID:更新某个指定动物园的信息(提供该动物园的全部信息)
        PATCH /zoos/ID:更新某个指定动物园的信息(提供该动物园的部分信息)
        DELETE /zoos/ID:删除某个动物园
        GET /zoos/ID/animals:列出某个指定动物园的所有动物
        DELETE /zoos/ID/animals/ID:删除某个指定动物园的指定动物
    

    4.过滤信息不涉及状态改变

      如果记录数量很多,服务器不可能都将它们返回给用户。API 应该提供参数,过滤返回结果。 常用的过滤包括分页、排序等等。 下面是一些常见的参数。

        ?limit=10:指定返回记录的数量
        ?offset=10:指定返回记录的开始位置。
        ?page=2&per_page=100:指定第几页,以及每页的记录数。
        ?sortby=name&order=asc:指定返回结果按照哪个属性排序,以及排序顺序。
        ?animal_type_id=1:指定筛选条件
    

      参数的设计允许存在冗余,即允许 API 路径和 URL 参数偶尔有重复。 比如,GET /zoo/ID/animals 与 GET /animals?zoo_id=ID 的含义是相同的。

    5.使用 Http 头声明请求和响应的格式

      在客户端和服务端,双方都要知道通讯的格式,格式在 HTTP-Header 中指定

        Content-Type 定义请求格式,比如 URL 格式
        Accept 定义系列可接受的响应格式,JSON,XML 等等
    

      这个并不强制,实践中也可以通过参数来指定返回内容的格式

    6.优先使用 JSON 格式返回结果

      当设计 API 返回结果时,优先使用 JSON 格式,但不强制。 当请求的 URL 表明的是一个集合时,则返回结果为数组形式。 例如:

            {
                "data":[
                    {
                        "login": "jerry1",
                        "id": 1,
                        "avatar_url": "https://...."
                    },
                    {
                        "login": "jerry2",
                        "id": 2,
                        "avatar_url": "https://...."
                    },
                    {
                        "login": "jerry3",
                        "id": 3,
                        "avatar_url": "https://....",
                    }
                ]
            }
    

      当请求为单个对象时,则返回结果为 MAP 形式。例如,访问 https://api.test.com/users/test 时:

            {
                "login": "jerry4",
                "id": 1,
                "avatar_url": "https://avatars.githubusercontent.com/u/1?v=3"
            }
    

    7.使用超媒体链接来组织文档

      Hypermedia as the Engine of Application State 超媒体作为应用状态的引擎,超文本链接可以建立更好的文本浏览体验。

      RESTful API 最好能做到 Hypermedia,即返回结果中提供链接,连向其他 API 方法,使得用户不查文档,也知道下一步应该做什么。

      比如,当用户向 api.example.com 的根目录发出请求,会得到这样一个文档。

            {
                "link": {
                    "rel":   "collection https://www.example.com/zoos",
                    "href":  "https://api.example.com/zoos",
                    "title": "List of zoos",
                    "type":  "application/vnd.yourformat+json"
                }
            }
    

      上面代码表示,文档中有一个 link 属性,用户读取这个属性就知道下一步该调用什么 API 了。 rel表示这个 API 与当前网址的关系(collection 关系,并给出该 collection 的网址), href 表示 API 的路径,title 表示 API 的标题,type 表示返回类型。

    Hypermedia API 的设计被称为 HATEOAS。Github 的 API 就是这种设计,访问 api.github.com 会得到一个所有可用 API 的网址列表。

            {
                "current_user_url": "https://api.github.com/user",
                "authorizations_url": "https://api.github.com/authorizations",
                // ...
            }
    

    从上面可以看到,如果想获取当前用户的信息,应该去访问 api.github.com/user,然后就得到了下面结果。

            {
                "message": "Requires authentication",
                "documentation_url": "https://developer.github.com/v3"
            }
    

    8.使用 Http 状态码处理错误

      如果你的 API 没有错误处理是很难的,只是返回 500 和出错堆栈不一定有用

      Http 状态码提供 70 个出错,我们只要使用 10 个左右:

        200 OK - [GET]:服务器成功返回用户请求的数据,该操作是幂等的(Idempotent)。
        201 CREATED - [POST/PUT/PATCH]:用户新建或修改数据成功。
        202 Accepted - [*]:表示一个请求已经进入后台排队(异步任务)
        204 NO CONTENT - [DELETE]:用户删除数据成功。
        400 INVALID REQUEST - [POST/PUT/PATCH]:用户发出的请求有错误,服务器没有进行新建或修改数据的操作,该操作是幂等的。
        401 Unauthorized - [*]:表示用户没有权限(令牌、用户名、密码错误)。
        403 Forbidden - [*] 表示用户得到授权(与 401 错误相对),但是访问是被禁止的。
        404 NOT FOUND - [*]:用户发出的请求针对的是不存在的记录,服务器没有进行操作,该操作是幂等的。
        406 Not Acceptable - [GET]:用户请求的格式不可得(比如用户请求 JSON 格式,但是只有 XML 格式)。
        410 Gone -[GET]:用户请求的资源被永久删除,且不会再得到的。
        422 Unprocesable entity - [POST/PUT/PATCH] 当创建一个对象时,发生一个验证错误。
        500 INTERNAL SERVER ERROR - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。
    

      使用详细的错误包装错误:

            {
                "errors":[
                    {
                        "userMessage": "Sorry, the requested resource does not exist",
                        "internalMessage": "No car found in the database",
                        "code": 34,
                        "more info": "http://dev.mwaysolutions.com/blog/api/v1/errors/12345"
                    }
                ]
            }



    just here , jerry

  • 相关阅读:
    面向对象(三大特性)
    SQL Server数据库(SQL Sever语言 事务)
    面向对象(简介)
    SQL Server数据库(SQL Sever语言 存储过程及触发器)
    SQL Server数据库(SQL Sever语言 函数以及SQL编程)
    SQL Server数据库(作业讲解和复习)
    SQL Server语言 函数以及SQL编程
    数据库(作业讲解和复习)
    SQL中CRUD C——create 添加数据 R——read 读取数据 U——update 修改数据 D——delete 删除数据
    SQL server数据库基础
  • 原文地址:https://www.cnblogs.com/mbailing/p/java-restful.html
Copyright © 2011-2022 走看看