• REST以及RESTful


      java作为一门后端语言,其厉害之处在于web,大家比较熟知的各种网络应用,java都能做,那么在这个移动优先的时代,如何继续发挥java的强大呢。通常是让java作为一个app的服务端,为app客户端提供数据,做业务逻辑,所以我们用java来写接口,app客户端访问接口返回json文件进行解析,最后实现业务逻辑。这种方式就是我们通常所说的restful架构风格的api。

      restful是一种架构思想,最初由Roy T. Fielding(HTTP/1.1协议专家组负责人)在其2000年的博士学位论文中提出。HTTP就是该架构风格的一个典型应用,其核心思想就是前后端分离,前端通过http请求,如www.xxxx.com/demo/username/password  来访问后端的接口,然后后端将处理好的数据封装为json返回,这样,后端只需关注具体逻辑 提供接口,而前端只关心界面,提高了程序解耦性。 

      在移动优先的时代,restful极为重要。通常一套后台可以让多种终端访问,包括移动端,pc端。

      在java中比较容易实现restful的是SpringMVC框架,他提供了一套处理json的注解。通过@ResponseBody返回json数据,通过@ResquestBody解析json。

      

    REST(Representational State Transfer)表象化状态转变(表述性状态转变),在2000年被提出,基于HTTP、URI、XML、JSON等标准和协议,支持轻量级、跨平台、跨语言的架构设计。是Web服务的一种新的架构风格(一种思想)

    什么是轻量级:

    代码不被侵入(正例:SpringMVC中不用接口和继承,仅用注解完成。反例:Struts中每一个Action都要继承核心控制器),轻量级跟包大小无关。耦合性越低,越轻量。

    REST架构的主要原则

    • 网络上每一个资源都有一个资源标志符,可以用来唯一地标识该资源

    • 对资源的操作不会改变标识符。

    • 同一资源有多种表现形式(xml、json)

    • 所有操作都是无状态的(Stateless)

    符合上述REST原则的架构方式称为 RESTful

    RESTful资源操作

    http方法 资源操作 幂等 安全
    GET SELECT 
    POST  INSERT 
    PUT  UPDATE 
    DELETE  DELETE 

    幂等性:对同一REST接口的多次访问,得到的资源状态是相同的。

    安全性:对该REST接口访问,不会使服务器端资源的状态发生改变。

    注意,默认情况下,PUT请求是无法提交表单数据的,在Spring MVC项目中需要在web.xml中添加过滤器解决:

    <!-- 解决PUT请求无法提交表单数据的问题 --> 
    <filter> 
    <filter-name>HttpMethodFilter</filter-name> 
    <filter-class>org.springframework.web.filter.HttpPutFormContentFilter</filter-class> 
    </filter> 
    <filter-mapping> 
    <filter-name>HttpMethodFilter</filter-name> 
    <url-pattern>/*</url-pattern> 
    </filter-mapping> 

    URL设计

    • 动词的覆盖

    有些客户端只能使用GETPOST两种方法。服务器必须接受POST模拟其他三个方法(PUTPATCHDELETE)。这时,客户端发出的 HTTP 请求,要加上X-HTTP-Method-Override属性,告诉服务器应使用哪一个动词,覆盖POST方法。

    POST /api/Person/4 HTTP/1.1  
    X-HTTP-Method-Override: PUT
    //上面代码中,X-HTTP-Method-Override指定本次请求的方法是PUT,而不是POST。
    • 宾语必须是名词

    宾语就是 API 的 URL,是 HTTP 动词作用的对象。它应该是名词,不能是动词。比如,/articles这个 URL 就是正确的,而下面的 URL 不是名词,所以都是错误的。

    /getAllCars
    /createNewCar
    /deleteAllRedCars
    • 复数 URL

    既然 URL 是名词,那么应该使用复数,还是单数,没有统一的规定,但是常见的操作是读取一个集合,比如GET /articles(读取所有文章),这里明显应该是复数。

    为了统一起见,建议都使用复数 URL,比如GET /articles/2要好于GET /article/2

    • 避免多级 URL

    常见的情况是,资源需要多级分类,因此很容易写出多级的 URL

    //比如获取某个作者的某一类文章。这种 URL 不利于扩展,语义也不明确,往往要想一会,才能明白含义。
    GET /authors/12/categories/
    //更好的做法是,除了第一级,其他级别都用查询字符串表达。
    GET /authors/12?categories=2
    
    //下面是另一个例子,查询已发布的文章。你可能会设计成下面的 URL。
    GET /articles/published
    //查询字符串的写法明显更好。
    GET /articles?published=true

    接口示例

    //传统URL请求格式:
    http://127.0.0.1/user/query/1 GET 根据用户id查询用户数据
    http://127.0.0.1/user/save POST 新增用户
    http://127.0.0.1/user/update POST 修改用户信息
    http://127.0.0.1/user/delete GET/POST 删除用户信息
    
    //RESTful请求格式:
    http://127.0.0.1/user/1 GET 根据用户id查询用户数据
    http://127.0.0.1/user POST 新增用户
    http://127.0.0.1/user PUT 修改用户信息
    http://127.0.0.1/user DELETE 删除用户信息

    服务器回应

    • 不要返回纯本文

    API 返回的数据格式,不应该是纯文本,应该是一个 JSON 对象,这样才能返回标准的结构化数据。所以,服务器回应的 HTTP 头的Content-Type属性要设为application/json

    客户端请求时,也要明确告诉服务器,可以接受 JSON 格式,即请求的 HTTP 头的ACCEPT属性也要设成application/json。如:

    GET /orders/2 HTTP/1.1 
    Accept: application/json
    • 发生错误时,不要返回 200 状态码
    //有一种不恰当的做法是,即使发生错误,也返回200状态码,把错误信息放在数据体里面,就像下面这样,解析数据体以后,才能得知操作失败。这张做法实际上取消了状态码,这是完全不可取的。
    HTTP/1.1 200 OK
    Content-Type: application/json
    
    {
      "status": "failure",
      "data": {
        "error": "Expected at least two items in list."
      }
    }
    
    //正确的做法是,状态码反映发生的错误,具体的错误信息放在数据体里面返回。
    HTTP/1.1 400 Bad Request
    Content-Type: application/json
    
    {
      "error": "Invalid payoad.",
      "detail": {
         "surname": "This field is required."
      }
    }
    • 提供链接

    API 的使用者未必知道,URL 是怎么设计的。一个解决方法是,在回应中,给出相关链接,便于下一步操作。这样的话,用户只要记住一个 URL,就可以发现其他的 URL,这种方法叫做 HATEOAS。

    //举例来说,GitHub 的 API 都在 api.github.com 这个域名。访问它,就可以得到其他 URL。
    {
      ...
      "feeds_url": "https://api.github.com/feeds",
      "followers_url": "https://api.github.com/user/followers",
      "following_url": "https://api.github.com/user/following{/target}",
      "gists_url": "https://api.github.com/gists{/gist_id}",
      "hub_url": "https://api.github.com/hub",
      ...
    }
    //上面的回应中,挑一个 URL 访问,又可以得到别的 URL。对于用户来说,不需要记住 URL 设计,只要从 api.github.com 一步步查找就可以了。 //HATEOAS 的格式没有统一规定,上面例子中,GitHub 将它们与其他属性放在一起。更好的做法应该是,将相关链接与其他属性分开。 HTTP/1.1 200 OK Content-Type: application/json { "status": "In progress", "links": {[ { "rel":"cancel", "method": "delete", "href":"/api/status/12345" } , { "rel":"edit", "method": "put", "href":"/api/status/12345" } ]} }
  • 相关阅读:
    MySQL —— 程序连接时的驱动名称和URL
    这该称作什么效应?
    Java 基础 面向对象之关键字内部类代码块修饰符
    Java 基础 面向对象之构造方法和关键字
    Java 基础 接口和多态
    Java 基础 面向对象和抽象类
    Java 基础 引用数据类型 ArrayList集合
    Java 基础 方法
    Java 基础 引用数据类型 和 流程控制
    Mongodb 基础 复制集原理和搭建
  • 原文地址:https://www.cnblogs.com/whatarewords/p/10655211.html
Copyright © 2020-2023  润新知