你好,我是朱晔。今天,我要和你分享的主题是,在做接口设计时一定要确保系统之间对话的语言是统一的。 我们知道,开发一个服务的第一步就是设计接口。接口的设计需要考虑的点非常多,比如接口的命名、参数列表、包装结构体、接口粒度、版本策略、幂等性实现、同步异步处理方式等。 这其中,和接口设计相关比较重要的点有三个,分别是包装结构体、版本策略、同步异步处理方式。今天,我就通过我遇到的实际案例,和你一起看看因为接口设计思路和调用方理解不一致所导致的问题,以及相关的实践经验。 ## 接口的响应要明确表示接口的处理结果 我曾遇到过一个处理收单的收单中心项目,下单接口返回的响应体中,包含了success、code、info、message等属性,以及二级嵌套对象data结构体。在对项目进行重构的时候,我们发现真的是无从入手,接口缺少文档,代码一有改动就出错。 有时候,下单操作的响应结果是这样的:success是true、message是OK,貌似代表下单成功了;但info里却提示订单存在风险,code是一个5001的错误码,data中能看到订单状态是Cancelled,订单ID是-1,好像又说明没有下单成功。 ``` { "success": true, "code": 5001, "info": "Risk order detected", "message": "OK", "data": { "orderStatus": "Cancelled", "orderId": -1 } } ``` 有些时候,这个下单接口又会返回这样的结果:success是false,message提示非法用户ID,看上去下单失败;但data里的orderStatus是Created、info是空、code是0。那么,这次下单到底是成功还是失败呢? ``` { "success": false, "code": 0, "info": "", "message": "Illegal userId", "data": { "orderStatus": "Created", "orderId": 0 } } ``` 这样的结果,让我们非常疑惑: - 结构体的code和HTTP响应状态码,是什么关系? - success到底代表下单成功还是失败? - info和message的区别是什么? - data中永远都有数据吗?什么时候应该去查询data? 造成如此混乱的原因是:这个收单服务本身并不真正处理下单操作,只是做一些预校验和预处理;真正的下单操作,需要在收单服务内部调用另一个订单服务来处理;订单服务处理完成后,会返回订单状态和ID。 在一切正常的情况下,下单后的订单状态就是已创建Created,订单ID是一个大于0的数字。而结构体中的message和success,其实是收单服务的处理异常信息和处理成功与否的结果,code、info是调用订单服务的结果。 对于第一次调用,收单服务自己没问题,success是true,message是OK,但调用订单服务时却因为订单风险问题被拒绝,所以code是5001,info是Risk order detected,data中的信息是订单服务返回的,所以最终订单状态是Cancelled。 对于第二次调用,因为用户ID非法,所以收单服务在校验了参数后直接就返回了success是false,message是Illegal userId。因为请求没有到订单服务,所以info、code、data都是默认值,订单状态的默认值是Created。因此,第二次下单肯定失败了,但订单状态却是已创建。 可以看到,如此混乱的接口定义和实现方式,是无法让调用者分清到底应该怎么处理的。**为了将接口设计得更合理,我们需要考虑如下两个原则:** - 对外隐藏内部实现。虽然说收单服务调用订单服务进行真正的下单操作,但是直接接口其实是收单服务提供的,收单服务不应该“直接”暴露其背后订单服务的状态码、错误描述。 - 设计接口结构时,明确每个字段的含义,以及客户端的处理方式。 基于这两个原则,我们调整一下返回结构体,去掉外层的info,即不再把订单服务的调用结果告知客户端: ``` @Data public class APIResponse<T> { private boolean success; private T data; private int code; private String message; } ``` 并明确接口的设计逻辑: - 如果出现非200的HTTP响应状态码,就代表请求没有到收单服务,可能是网络出问题、网络超时,或者网络配置的问题。这时,肯定无法拿到服务端的响应体,客户端可以给予友好提示,比如让用户重试,不需要继续解析响应结构体。 - 如果HTTP响应码是200,解析响应体查看success,为false代表下单请求处理失败,可能是因为收单服务参数验证错误,也可能是因为订单服务下单操作失败。这时,根据收单服务定义的错误码表和code,做不同处理。比如友好提示,或是让用户重新填写相关信息,其中友好提示的文字内容可以从message中获取。
  • success为true的情况下,才需要继续解析响应体中的data结构体。data结构体代表了业务数据,通常会有下面两种情况。