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设计
- 动词的覆盖
有些客户端只能使用GET
和POST
两种方法。服务器必须接受POST
模拟其他三个方法(PUT
、PATCH
、DELETE
)。这时,客户端发出的 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" }
- ]}
- }
REST以及RESTful的更多相关文章
- Restful资源文章
理解RESTful架构 RESTful API设计指南 RESTful架构详解 NodeJs的RESTful API
- 【接口开发】浅谈 SOAP Webserver 与 Restful Webserver 区别
接口,强大,简单,交互,跨越平台 下面简单阐述这两大接口思想 一 REST: REST是一种架构风格,其核心是面向资源,REST专门针对网络应用设计和开发方式,以降低开发的复杂性,提高系统的可伸缩性. ...
- (转载) RESTful API 设计指南
作者: 阮一峰 日期: 2014年5月22日 网络应用程序,分为前端和后端两个部分.当前的发展趋势,就是前端设备层出不穷(手机.平板.桌面电脑.其他专用设备......). 因此,必须有一种统一的机制 ...
- angular中使用ngResource模块构建RESTful架构
ngResource模块是angular专门为RESTful架构而设计的一个模块,它提供了'$resource'模块,$resource模块是基于$http的一个封装.下面来看看它的详细用法 1.引入 ...
- Linux学习日记-WCF RestFul的部署(三)
一.关于WCF 的部署 默认的wshttp风格的wcf是很容易部署上去的,但是这里给个建议尽量不要使用WCF的配置文件去部署尽管 我们都已经很熟悉了,在使用配置文件你会发现各种蛋疼的问题. 二.WCF ...
- Node.js实现RESTful api,express or koa?
文章导读: 一.what's RESTful API 二.Express RESTful API 三.KOA RESTful API 四.express还是koa? 五.参考资料 一.what's R ...
- Restful WebApi项目开发实践
前言 踩过了一段时间的坑,现总结一下,与大家分享,愿与大家一起讨论. Restful WebApi特点 WebApi相较于Asp.Net MVC/WebForm开发的特点就是前后端完全分离,后端使用W ...
- Java——搭建自己的RESTful API服务器(SpringBoot、Groovy)
这又是一篇JavaWeb相关的博客,内容涉及: SpringBoot:微框架,提供快速构建服务的功能 SpringMVC:Struts的替代者 MyBatis:数据库操作库 Groovy:能与Java ...
- AngularJS Resource:与 RESTful API 交互
REST(表征性状态传输,Representational State Transfer)是Roy Fielding博士在2000年他的博士论文中提出来的一种软件架构风格.RESTful风格的设计不仅 ...
- Restful 介绍及SpringMVC+restful 实例讲解
restful不是一个框架,称为一种编码更烦更贴切吧,其核心类位于spring-web.jar中,即RestTemplate.class restful是rpc通过http协议的一种实现方式,和web ...
随机推荐
- Linux下删除文件名带有空格的文件
1.使用单引号将文件名括起来进行操作: rm '2018-08-07 17-29-48.png'
- Linux嵌入式学习-交叉编译mplayer
http://bbs.gkong.com/archive.aspx?ID=286721
- stm32之定时器彻底研究
分类: C/C++ 这里介绍两种方式使用stm32的定时器:直接操作寄存器和使用st的官方的库文件. 相比较而言,直接操作定时器比较简洁,对着寄存器看十分明了.而使用库文件有一点晕头转向. (个人观点 ...
- ThreadLocal源码深度剖析
ThreadLocal源码深度剖析 ThreadLocal的作用 ThreadLocal的作用是提供线程内的局部变量,说白了,就是在各线程内部创建一个变量的副本,相比于使用各种锁机制访问变量,Thre ...
- Lambda 表达式实例
public class Java8Tester {/*** 语法 lambda 表达式的语法格式如下: (parameters) -> expression 或 (parameters) -& ...
- 关于try catch块执行流程
代码: package test; public class FinallyTest { public static void main(String[] args) { try { // proce ...
- AtCoder Beginner Contest 187 F - Close Group
题目链接 点我跳转 题目大意 给你一张完全图,你可以删除任意数量的边 要求删除完后剩余的所有子图必须是完全图 问完全子图数量最少是多少 解题思路 定义 \(ok[i]\) 表示状态为 \(i\) 时所 ...
- .NET 云原生架构师训练营(模块二 基础巩固 MongoDB API实现)--学习笔记
2.5.7 MongoDB -- API实现 问题查询单个实现 问题查询列表实现 问题跨集合查询实现 问题创建实现 问题更新实现 问题回答实现 问题评论实现 问题投票实现 回答实现 QuestionC ...
- Java中常用修饰符浅谈
一.public.protected.default和private修饰符的作用域 public:在java程序中,如果将属性和方法定义为 public 类型,那么此属性和方法所在的类和及其子类,同一 ...
- Redis缓存篇(三)缓存污染
上一讲介绍了缓存满了,通过内存淘汰机制来淘汰掉数据.如果有的数据一直滞留在缓存中,但又没有应用使用,时间长了,就可能会占据大部分的缓存空间. 今天我们来学习一下缓存污染,以及如何解决缓存污染. 缓存污 ...