强类型接口设计
强、弱类型接口
服务 API 接口有强、弱类型之分。
强类型接口
传统的 RPC 服务(定制二进制协议,对消息进行编码和解码),采用 TCP 传输消息。RPC 服务通常有严格的契约,开发服务前需要使用 IDL(Interface description language)定义契约,最终通过契约自动生成强类型的服务器端、客户端的接口。服务调用直接使用强类型的客户端。(GRPC、Thrift)
- 优点:不需要手动的编码和解码、接口规范、自动代码生成、编译器自动类型检查。
- 缺点:服务端和客户端强耦合、任何一方升级改动可能会造成另一方 break。自动代码生成需要工具支持,开发这些工具的成本比较高。强类型接口开发测试不友好、浏览器、Postman 这些工具无法直接访问这些强类型接口。
弱类型
RESTFul 服务通常采用 JSON 作为传输消息,使用 HTTP 作为传输协议,没有严格契约的概念,使用普通的 HTTP Client 即可调用。调用方需要对 JSON 消息进行手动的编码和解码工作。(SpringBoot)
- 优点:服务端和客户端非强耦合、开发测试友好。
- 缺点:调用方手动编码解码,没有自动代码生成、没有编译期接口类型检查、相对不规范、容易出现运行期错误。
基于 Feign 的强类型接口
Spring Rest 弱类型接口的基础上,借助 Feign 支持的强类型接口的特性,实现强类型 Rest 接口调用机制。同时兼备强弱类型的优点。
封装消息 + 捎带
业界 RESTFul API 设计通常采用 HTTP 协议状态码来传递和表达错误语义。
封装消息 + 捎带 设计模式:将错误码打包在正常的 JSON 消息当中。这样的设计是为了支持强类型的客户端、同时简化和规范错误处理。使用 HTTP 协议状态码来开发,虽然也可以实现强类型客户端,但是内部调用逻辑就会变得复杂。(继承接口 ListAccountResponse,尽量不用使用泛型,除了 Collection 之外,不要使用泛型,否则会出现反序列化问题)。