Rest架构风格
参考:https://www.cnblogs.com/binbingg/p/13840808.html
什么是 REST 架构风格
REST(Representational State Transfer)即表述性状态转移,是由 Roy Fielding 在其博士论文中提出的一种分布式超媒体软件架构风格。它不是协议,也不是标准,而是基于 HTTP、URI 等广泛流行的协议和标准构建的一组架构约束。
简单理解就是,REST 是一种 Web 应用的架构风格,只要满足 REST 的约束和原则,就能获得这种架构风格带来的诸多优势,比如极高的可演化性、极强的扩展能力以及前后端的彻底解耦。
REST 的核心抽象概念
资源(Resource)。在 REST 架构中,资源扮演着主要角色。资源是任何可以被操作(获取、提交、更新、删除)的数据,比如一个文档、一张图片,甚至一个用户。资源的集合也是一种资源,比如 /users 表示用户集合。进行资源操作时,用 URI 来指定被操作的资源。如果一个 URI 不仅能标识网络上的资源,还能定位这个资源,那它就是我们熟知的 URL。资源是第一位的设计考量,而不是操作。
表示(Representation)。资源是一个抽象概念,无法被直接传输,网络只能传输资源的“表示”。一个资源可以有多种表示形式,比如 JSON、XML 或 HTML。具体传输哪种表示,取决于服务端的能力和客户端的要求(通过 HTTP 头协商)。总的来说,“表示”是“资源”的存储和传输形式,“资源”是“表示”的内容,不管用什么形式,始终描述的是同一个资源。
无状态(Stateless)。根据 REST 的架构限制,RESTful 服务器必须是无状态的,这意味着来自客户端的每一个请求必须包含服务器处理该请求所需的所有信息。服务器不能利用任何已经存储的“上下文”(即用户的会话状态)来处理新请求,会话状态只能由客户端保存,并在每次请求时一并提供。无状态让服务器系统的扩展性更强,天然支持集群和分布式,无需考虑节点之间的 Session 同步问题,服务器之间的沟通开销极低。
这里要注意两点常见误区:第一,服务器不能存储“上下文”不代表连数据库都不能有,“上下文”指那些在服务器内存中的、非持久化的临时数据。第二,无状态不代表不能有会话,无状态仅仅指服务器无状态,会话状态可以由客户端(如浏览器或 App)在每次请求时携带。
无状态与安全的矛盾:Token 机制
RESTful 提供的 API 是无状态的,下一次调用请求与当前调用完全无关,但这就导致服务器无法天然记住“你是谁”,无法保证系统资源的安全性。Token(令牌)认证机制就是用来解决无状态与安全性之间矛盾的核心方案。其实现原理是:用户首次发送用户名和密码请求验证;服务器验证通过后,返回一个加密的 Token 及过期时间;后续所有请求由客户端携带该 Token 即可通过验证。服务器只需要验证 Token 的有效性,无需在内存中保存任何用户登录状态,完美契合了 REST 的无状态约束。
REST 的约束与规范落地
用 URI 标识资源。每个资源都应该拥有一个唯一、全局的 ID,在 Web 中就是 URI,这意味着资源获得了明确的命名空间。
用 HTTP 方法操作资源。既然通过 URL 定位了资源,我们对这个资源使用不同的 HTTP 方法,就代表对这个资源的不同操作。GET 用于获取资源,POST 用于新建资源,PUT 用于更新完整资源,PATCH 用于部分更新,DELETE 用于删除资源。这些方法本身包含了明确的语义。
用 HTTP 状态码表示操作结果。服务器处理完请求后,必须用标准的 HTTP 状态码来表明结果,比如 200 表示成功,201 表示已创建,400 表示客户端请求错误,404 表示资源不存在,500 表示服务端内部错误,让客户端一眼就能明白处理结果。
什么是 RESTful API 及如何设计
RESTful API 就是满足 REST 架构风格的 API。具体而言就是用 URI 定位资源、用 HTTP 标准方法描述操作、用响应状态码表示结果。它有助于客户端和服务端的功能分离,服务器完全扮演“资源服务商”的角色,各种不同的客户端都能通过一致的 API 与资源互动。
过去的传统设计往往以“操作”为出发点,比如设计一个转账功能,可能会写出 POST /transfer/${amount}/to/${toUserID}。这种做法缺点很明显:一旦在 URL 中引入了动词,这个 URL 的功能就定死了,无法用于别的用途,且不同功能的 API 各有各的结构,一致性差,必须依赖庞大的文档才能使用。操作通常还带有副作用,很难使用缓存技术。
而设计 REST 风格的系统,资源是第一位的。我们将一个“动作”理解为“操作一个资源”。对于转账,可以理解为“新建一个转账事务”(事务是资源),API 设计为 POST /transactions;对于发消息,可以理解为“操作聊天记录”(消息是资源),API 设计为 POST /messages。这种设计克服了传统架构的缺陷:API 设计工作量大幅减少,因为资源一旦确定,URL 和操作方式就呼之欲出;操作之间没了强依赖,系统解耦;对资源的操作就那么几种,API 的一致性和自我描述性极强;尤其是 GET 请求代表获取数据,天然安全且幂等,非常适合使用缓存。
Spring MVC 如何支持 RESTful
Spring MVC 从 Spring 3.0 开始,提供了一套完整的机制来帮助开发者优雅地落地上述 REST 规范。
注解与控制器支持。Spring MVC 提供了 @RestController 注解,它等于 @Controller 加 @ResponseBody,意味着方法返回值不再被解析为视图,而是直接写入响应体(通常序列化为 JSON)。配合 @RequestMapping 以及 @GetMapping、@PostMapping、@PutMapping、@DeleteMapping,可以完美将 HTTP 方法语义与 Java 方法映射起来。这种方式声明式开发,代码极其简洁;但也要求开发者不能混用,忘记 @ResponseBody 会导致返回 JSON 变成 404 视图名。
参数绑定支持。为了适配 REST 的资源定位和请求体,Spring MVC 提供了 @PathVariable 绑定 URI 中的资源标识(如 /users/{id}),@RequestParam 绑定查询参数,@RequestBody 绑定请求体,@RequestHeader 绑定请求头。参数绑定极其灵活,减少了手工解析,但也要求开发者清楚每个注解对应哪部分请求数据,排查问题时更需细心。
消息转换与内容协商。Spring MVC 通过 HttpMessageConverter 自动完成请求体(JSON/XML)反序列化和响应体序列化,通常由 Jackson 实现。同时支持内容协商,通过 produces、consumes 以及 Accept、Content-Type 控制媒体类型。这极大地方便了前后端数据交互,不过也容易因配置不当报 406(无法接受)或 415(不支持的媒体类型)错误,日期格式等也需统一约定。
响应构造与异常处理。开发者可以使用 ResponseEntity 显式设置状态码、响应头和响应体,或用 @ResponseStatus 指定状态码,从而精确控制 REST 响应。同时,Spring MVC 提供了 @ExceptionHandler、@ControllerAdvice 和 @RestControllerAdvice 进行全局异常处理,把异常转换为合适的 HTTP 状态码和错误响应体。这能让前端统一处理错误,但也要求设计好错误码体系,避免所有异常都返回 500。
此外,Spring MVC 生态中还有 HiddenHttpMethodFilter(支持浏览器表单模拟 PUT/DELETE)、Validation(结合 @Valid 校验参数并返回 400)、Spring Data REST(基于 Repository 自动暴露资源)以及 Spring HATEOAS(支持超媒体链接,向 HATEOAS 靠拢)。这些辅助机制进一步丰富了 RESTful 的开发体验。
总结
REST 是一种面向资源、基于 HTTP 语义、无状态、统一接口的架构风格;RESTful 则是符合这种风格的 API 或服务;而 Spring MVC 通过注解映射、参数绑定、消息转换、内容协商、响应构造和统一异常处理等机制,完美地支持了这套架构风格在工程中的落地。

浙公网安备 33010602011771号