为什么写这篇文章?
相信不少 Java 开发都在项目中使用过类似 ApiResult
这样的对象来包装 Api 返回类型,这相比什么都不包装有一定的好处,但这真的就是最好的做法吗?
统一返回 ApiResult 还不是最佳实践,必须不断思考优化,就像 React 所提倡的 Rethinking Best Practices
。
ApiResult 现状
我们先看一个常见的 ApiResult 对象,代码如下:
@Data
public class ApiResult<T> implements Serializable {
private int code;
private String message;
private T data;
}
好处:客户端可以使用统一的处理方式。
存在的问题:
- 在统一返回 ApiResult 的情况下,即使是正常返回,也会带上 code、message 属性,属于冗余。
Controller
层代码存在重复,返回对象重复定义、包装调用编写重复。
public ApiResult<List<Data>> demo() {
return ApiResult.ok(getList());
}
当 API 越来越多时,这些存在的问题会被被放大,如何解决这些问题呢?请接着看。
使用 HTTP 状态码
有许多项目采用的方式是,在 API 调用成功时使用正常的数据模型,而在出现错误时,返回相应的 HTTP 错误码
和描述信息。我们看一段 jhipster
中的代码:
@GetMapping("/authors/{id}")
public ResponseEntity<AuthorDTO> getAuthor(@PathVariable Long id) {
Optional<AuthorDTO> authorDTO = authorService.findOne(id);
return ResponseUtil.wrapOrNotFound(authorDTO);
}
主要 HTTP 状态码的含义:
- 1XX – Informational
- 2XX – Success
- 3XX – Redirection
- 4XX – Client Error
- 5XX – Server Error
采用 HTTP 状态码就不再需要统一返回 ApiResult ,但问题也随之而来,那就是 ApiResult 中定义的 error code
很难跟 HTTP 错误码一一对应,光有 HTTP 错误码和描