-
SpringBoot使用接口架构风格RESTful
-
概述
-
REST — 前后台间的通信方式
-
设计统一的 RESTful 风格的数据接口
-
用 RestTemplate 发起请求
-
总结
概述
RESTful 是非常流行的架构设计风格。首先介绍 REST 的特征、HTTP方法与CRUD动作映射;然后讲解如何基于Spring Boot 设计统一的 RESTful 风格的数据接口;最后讲解在 Spring Boot 下如何使用 RestTemplate 访问 RESTful 接口。
REST — 前后台间的通信方式
什么是 REST
-
REST(Representational State Transfer)表述性状态转换,REST指的是一组架构约束条件和原则。
-
如果一个架构符合REST的约束条件和原则,我们就称它为RESTful 架构。
-
REST本身并没有创造新的技术、组件或服务,而隐藏在RESTful背后的理念就是使用Web的现有特征和能力,更好地使用现有Web标准中的一些准则和约束。
REST 是软件架构的规范体系结构,它将资源的状态以适合客户端的形式从服务器端发送到客户端(或相反方向)。在 REST 中,通过 URL 进行资源定位,用 HTTP 动作(GET、POST、DELETE、PUT等)描述操作,完成功能。
遵循 RESTful 风格,可以使开发的接口通用,以便调用者理解接口的作用。基于 REST 构建的 API 就是 RESTful(REST风格)API 。
各大机构提供的 API 基本都是 RESTful 风格的。这样可以统一规范,减少沟通、学习和开发的成本。
REST 的特征
-
客户-服务器(client-server):提供服务的服务器和使用服务的客户端需要被隔离对待。
-
无状态(stateless):服务器端不存储客户请求中的信息,客户的每一个请求必须包含服务器处理请求所需的所有信息,所有的资源都可以通过 URI 定位,而且这个定位与其他资源无关,也不会因为其他资源的变化而变化。
-
可缓存(cachable):服务器必须让客户知道请求是否可以被缓存。
-
分层系统(layered System):服务器和客户之间的通信必须被标准化。
-
统一接口(uniform interface):客户和服务器之间通信的方法必须统一,RESTful 风格的数据元操作 CRUD(create、read、update、delete)分别对应 HTTP 方法–GET用来获取资源,POST用来新建资源、PUT用来更新资源,DELETE用来删除资源,这样就统一了数据操作的接口。
-
HTTP 状态码:状态码在 REST 中都有特定的意义:200、201、202、204、400、401、403、500。如:401 表示用户身份认证失败;403 表示验证身份通过了,但资源没有权限进行操作。
-
支持按需代码(Code-On-Demand,可选):服务器可以提供一些代码或脚本,并在客户的运行环境中执行。
HTTP 连接最显著的特点是:客户端发送的每次请求都需要服务器回送响应;在请求结束后,主动释放连接。从建立连接到关闭连接的过程称为“一次连接”,前后的请求没有必然的联系,所以是无状态的。
认识 HTTP 方法与 CRUD 动作映射
RESTful 风格使用同一个 URL ,通过约定不同的 HTTP 方法来实施不同的业务。
普通的URL 和 RESTful 风格 URL:
-
查询:
-
普通URL:article/id=1 ,HTTP 方法:GET
-
RESTfull :article/{id} ,HTTP 方法:GET
-
添加:
-
普通URL:article?title=xx&body=xxx ,HTTP 方法:GET/POST
-
RESTfull :article ,HTTP方法:POST
-
修改:
-
普通URL:article/update?id=xx&body=xxx ,HTTP 方法:GET/POST
-
RESTfull :article/{id},HTTP方法:PUT 或 PATCH
-
删除:
-
普通URL:article/delete?id=xx ,HTTP 方法:GET
-
RESTfull :article/{id},HTTP 方法:DELETE
RESTful 方法的 CRUD 它通过 HTTP 方法来区分增加、修改、删除和查询。
Request
-
GET:查询
GET /zoos
GET /zoos/1
GET /zoos/1/employees
-
POST:创建单个资源。POST一般向“资源集合”型uri发起。
POST /animals //新增动物
POST /zoos/1/employees //为id为1的动物园雇佣员工
-
PUT:更新单个资源(全量),客户端提供完整的更新后的资源。
-
PATCH 负责部分更新,客户端提供要更新的那些字段。PUT/PATCH一般向“单个资源”型uri发起
PUT /animals/1
PUT /zoos/1
-
DELETE:删除
DELETE /zoos/1/employees/2
DELETE /zoos/1/employees/2;4;5
DELETE /zoos/1/animals //删除id为1的动物园内的所有动物
实现 RESTful 风格的数据增加、删除、修改和查询
在 Spring Boot 中,如果返回 JSON 数据,则只需要在控制器中用 @RestController
注解。使用注解 @RequestMapping
的 value 指定 URI、method 来指定 HTTP方法。
// 获取资源列表
@RequestMapping(value="/article",method=RequestMethod.GET)
public List<Article> list(){
...
}
// 根据ID获取资源
@RequestMapping(value="/article/{id}",method=RequestMethod.GET)
public Article findById(@PathVariable("id")Integer id){
...
}
// 增加资源
@RequestMapping(value="/article",method=RequestMethod.POST)
public String save(Article article){
...
}
// 修改资源
@RequestMapping(value="/article",method=RequestMethod.PUT)
public String update(Article article){
...
}
// 根据ID删除资源
@RequestMapping(value="/article/{id}",method=RequestMethod.DELETE)
public String deleteById(@PathVariable("id")Integer id){
...
}
设计统一的 RESTful 风格的数据接口
版本控制
随着业务需求的变更、功能的迭代,API的更改是不可避免的。当一个API修改时,就会出现很多问题,比如,可能会在 API 中新增参数、修改返回的数据类型。这就要考虑根据原先版本API编写的客户端如何保留或顺利过渡。所以,需要进行版本控制。
REST 不提供版本控制指南,常用的方法有 3 种:
-
1.通过URL :通过 URL 是最直接的方法,尽管它违背了 URI 应该引用唯一资源的原则。当版本更新时,还可以保障客户端不会受到影响。
-
API 版本 v1 : http://v1.xxx/api
-
API 版本 v2 : http://v2.xxx/api
-
API 版本 v1 : http://xxx/api/v1
-
API 版本 v2 : http://xxx/api/v2
-
二级目录的方式:
-
二级域名的方式:
-
还可以包括日期、项目名称或其他标识符。
-
2.通过自定义请求头:自定义头(例:accept-version)允许在版本之间保留 URL 。
-
3.通过 Accept 标头:客户端在请求资源之前,必须要指定特定头,然后 API 接口负责确定要发送哪个版本的资源。
过滤信息
如果记录数量很多,则服务器不可能一次都将它们返回给用户。API应该提供参数,实现分页返回结果。常用的参数:
-
limit=10 : 指定返回记录的数量。
-
?page=5&size=10 :指定第几页,以及每页的记录数。
-
?search_type=1 :指定筛选条件。
确定 HTTP 的方法
在 RESTful 中,HTTP 的方法有以下几种:
-
GET :代表请求资源
-
POST :代表添加资源
-
PUT :代表修改资源。PUT 是进行全部的修改。如果只修改一个或几个字段,则可以使用 PATCH 方法。
-
DELETE :代表删除资源。
-
HEAD :代表发送 HTTP 头消息, GET 中其实也带了 HTTP 头消息。
-
PATCH :PUT 用于替换资源,而 PATCH 用于更新部分资源。
-
OPTIONS :用于获取 URI 所支持的方法。返回的响应消息会在 HTTP 头中包含 “Allow” 的信息,其值是所支持的方法,如 GET 。
确定 HTTP 的返回状态
HTTP 的返回状态一般有以下几种:
-
200 :成功
-
400 :错误请求
-
404 :没找到资源
-
403 :禁止
-
406 :不能使用请求内容特性来响应请求资源,比如请求的是 HTML 文件,但是消费者的 HTTP 头包含了 JSON 要求。
-
500 :服务器内部错误。
错误处理
-
不要发生了错误但给2xx响应,客户端可能会缓存成功的http请求;
-
正确设置http状态码,不要自定义;
-
Response body 提供 1)错误的代码(日志/问题追查);2)错误的描述文本(展示给用户)。
-
Java 服务器端一般用异常表示 RESTful API 的错误。
-
API 可能抛出两类异常:业务异常和非业务异常。
-
业务异常由自己的业务代码抛出,表示一个用例的前置条件不满足、业务规则冲突等,比如参数校验不通过、权限校验失败。
-
非业务类异常表示不在预期内的问题,通常由类库、框架抛出,或由于自己的代码逻辑错误导致,比如数据库连接失败、空指针异常、除0错误等等。
-
业务类异常必须提供2种信息:
-
如果抛出该类异常,HTTP响应状态码应该设成什么;
-
异常的文本描述;
-
在Controller层使用统一的异常拦截器:
-
设置 HTTP响应状态码:对业务类异常,用它指定的 HTTP code;对非业务类异常,统一500;
-
Response Body 的错误码:异常类名
-
Response Body 的错误描述:对业务类异常,用它指定的错误文本;对非业务类异常,线上可以统一文案如“服务器端错误,请稍后再试”,开发或测试环境中用异常的 stacktrace,服务器端提供该行为的开关。
定义统一返回格式
为了保障前后端的数据交互的顺畅,建议规范数据的返回,并采用固定的数据格式封装。
例:
// 异常信息:
{
"code":10001,
"msg":"异常信息",
"data":null
}
// 成功信息:
{
"code":200,
"msg":"成功",
"data":{
"id":1,
"name":"xxx"
}
}
异步任务
-
对耗时的异步任务,服务器端接受客户端传递的参数后,应返回创建成功的任务资源,其中包含了任务的执行状态。客户端可以轮询该任务获得最新的执行进度。
提交任务:
POST /batch-publish-msg
[{"from":0,"to":1,"text":"abc"},{},{}...]
返回:
{"taskId":3,"createBy":"Anonymous","status":"running"}
GET /task/3
{"taskId":3,"createBy":"Anonymous","status":"success"}
-
如果任务的执行状态包括较多信息,可以把“执行状态”抽象成组合资源,客户端查询该状态资源了解任务的执行情况。
提交任务:
POST /batch-publish-msg
[{"from":0,"to":1,"text":"abc"},{},{}...]
返回:
{"taskId":3,"createBy":"Anonymous"}
GET /task/3/status
{"progress":"50%","total":18,"success":8,"fail":1}
用 RestTemplate 发起请求
认识 RestTemplate
在 Java 应用程序中访问 RESTful 服务,可以使用 Apache 的 HttpClient 来实现。不过此方法使用起来太烦琐。
Spring 提供了一种更简单便捷的模板类– RestTemplate 来进行操作。
RestTemplate 是 Spring 提供的用于访问 REST 服务的客户端,它提供了多种便捷访问远程 HTTP 服务的方法,能够大大提高客户端的编写效率。
RestTemplate 用于同步 Client 端的核心类,简化与 HTTP 服务的通信。在默认情况下,RestTemplate 默认依赖 JDK 的 HTTP 连接工具。也可以通过 setRequestFactory 属性切换到不同的 HTTP 源,比如 Apache HttpComponents、Netty和 OkHttp 。
RestTemplate 简化了提交表单数据的难度,并附带自动转换为 JSON 格式数据的功能。
RestTemplate 方法:
-
delete , HTTP 方法 DELETE
-
getForObject ,HTTP 方法 GET
-
getForEntity ,HTTP 方法 GET
-
headForHeaders ,HTTP 方法 HEAD
-
optionsForAllow ,HTTP 方法 OPTIONS
-
postForLocation ,HTTP 方法 POST
-
postForObject , HTTP方法 POST
-
put ,HTTP 方法 PUT
-
exchange ,HTTP 方法 any
-
execute , HTTP 方法 any
RestTemplate 默认使用 HttpMessageConverter 将 HTTP 消息转换成 POJO ,或从 POJO 转换成 HTTP 消息,默认情况下会注册主 MIME 类型的转换器,但也可以通过 setMessageConverters 注册其他类型的转换器。
总结
REST(Representational State Transfer)表述性状态转换,REST指的是一组架构约束条件和原则。
如果一个架构符合REST的约束条件和原则,我们就称它为RESTful 架构。
REST本身并没有创造新的技术、组件或服务,而隐藏在RESTful背后的理念就是使用Web的现有特征和能力,更好地使用现有Web标准中的一些准则和约束。
REST 是软件架构的规范体系结构,它将资源的状态以适合客户端的形式从服务器端发送到客户端(或相反方向)。在 REST 中,通过 URL 进行资源定位,用 HTTP 动作(GET、POST、DELETE、PUT等)描述操作,完成功能。
遵循 RESTful 风格,可以使开发的接口通用,以便调用者理解接口的作用。这样可以统一规范,减少沟通、学习和开发的成本。
REST 的特征
-
客户-服务器(client-server)
-
无状态(stateless)
-
可缓存(cachable)
-
分层系统(layered System)
-
统一接口(uniform interface)
-
支持按需代码(Code-On-Demand,可选)
RESTful 风格使用同一个 URL ,通过约定不同的 HTTP 方法来实施不同的业务。
在 RESTful 中,HTTP 的方法有以下几种:
-
GET :代表请求资源
-
POST :代表添加资源
-
PUT :代表修改资源。PUT 是进行全部的修改。
-
DELETE :代表删除资源。
-
HEAD :代表发送 HTTP 头消息。
-
PATCH :PUT 用于替换资源,而 PATCH 用于更新部分资源。
-
OPTIONS :用于获取 URI 所支持的方法。
设计统一的 RESTful 风格的数据接口
版本控制
-
随着业务需求的变更、功能的迭代,API的更改是不可避免的。这就要考虑根据原先版本API编写的客户端如何保留或顺利过渡。所以,需要进行版本控制。
-
REST 不提供版本控制指南,常用的方法有 3 种:
-
1.通过URL
-
2.通过自定义请求头
-
3.通过 Accept 标头
过滤信息
-
如果记录数量很多,则服务器不可能一次都将它们返回给用户。API应该提供参数,实现分页返回结果。
确定 HTTP 的方法
确定 HTTP 的返回状态
错误处理
-
不要发生了错误但给2xx响应,客户端可能会缓存成功的http请求;
-
正确设置http状态码,不要自定义;
-
Response body 提供 1)错误的代码(日志/问题追查);2)错误的描述文本(展示给用户)。
-
Java 服务器端一般用异常表示 RESTful API 的错误。
-
API 可能抛出两类异常:业务异常和非业务异常。
-
在Controller层使用统一的异常拦截器
定义统一返回格式
-
为了保障前后端的数据交互的顺畅,建议规范数据的返回,并采用固定的数据格式封装。
异步任务
-
对耗时的异步任务,服务器端接受客户端传递的参数后,应返回创建成功的任务资源,其中包含了任务的执行状态。客户端可以轮询该任务获得最新的执行进度。
-
如果任务的执行状态包括较多信息,可以把“执行状态”抽象成组合资源,客户端查询该状态资源了解任务的执行情况。
认识 RestTemplate
RestTemplate 是 Spring 提供的用于访问 REST 服务的客户端,它提供了多种便捷访问远程 HTTP 服务的方法,能够大大提高客户端的编写效率。
公众号
参考
《Spring Boot 实战派》 龙中华
原文始发于微信公众号(知行chen):SpringBoot使用接口架构风格RESTful
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/45913.html