聊一聊写 REST 接口时的一些比较烦人的问题

2019-04-24 17:03:05 +08:00
 qwerthhusn
  1. 其实最主要的一个问题就是查询接口的数据拼接问题。比如说一个博客的系统,查询一条博客信息,不仅要返回博客信息,还要去拼接上作者的信息。这样会定义一大堆数据组合类。然后查询逻辑里面有大量的数据组合代码。(有时可能会有三层到四层,而且有时是需要去其他服务去取数据)。例如下面的代码示例
class BlogModel {
    String authorUserID;
    ...
}

class BlogDomain extends BlogModel {
    private UserInfo authorInfo;
}

// 读取 BlogModel,然后去用户服务根据用户 ID 去取用户信息,最终拼接成 BlogDomain 返回
List<BlogDomain> getBlogList(int start, int limit) {
    List<BlogModel> blogModelList = dao.query(start, limit);
    
    // 批量去取
    Set<String> authorUserIDs = blogModelList.stream()
    		.map(BlogModel::getAuthorUserID)
            .collect(Collectors.toSet());
    Map<String, UserInfo> authorUserInfoMap = Collections.emptyMap();
    if (!auditUserIDs.isEmpty()) {
        authorUserIDs = userService.select(authorUserIDs);
    }
    
    return blogModelList.stream().map(blogModel -> {
        BlogDomain blogDomain = new BlogDomain();
        BeanUtils.copyProperties(blogModel, blogDomain);
        blogDoamin.setAuthorInfo(authorUserInfoMap.get(blogModel.getAuthorUserID()));
        return blogDomain;
    }).collect(Collectors.toList());
}
  1. REST 响应根据 HTTP 状态码作为错误码是不够的,一般接口还会再定义一个自定义的错误码(我看即使那些 GG,FB,INS,Twitter 的 API 文档也是这么玩的)。如果有了自定义的错误码,其实那个 HTTP 状态码实际显得有些鸡肋,唯一的作用就是使服务端和客户端的编码逻辑稍微变得更加复杂。

  2. 文档,现在用的最主要的文档工具就是 Swagger/OpenAPI,但是实际上会发现,无论是 code 自动生成文档,还是文档生成 code(客户端还好,主要是服务端,生成的 code 基本上没法用)都不好用。最后还是自己的手写文档。这样工作量又多了一些。

光这些问题,就让编码过程变得很烦了,也许可能需要一个能代替现有方式的东西。比如,GraphQL,gRPC 或者其他的东西。

4080 次点击
所在节点    Java
18 条回复
fishioon
2019-04-24 17:34:18 +08:00
结论是啥?
prasanta
2019-04-24 19:09:59 +08:00
用 python 吧
qwerthhusn
2019-04-24 19:43:45 +08:00
没有结论,就是抛出这个问题
wc951
2019-04-24 19:58:31 +08:00
第一个问题你需要一个中间服务去整合数据,比如流行的 nodejs 中间层
wc951
2019-04-24 20:00:03 +08:00
文档的话我现在用的是 spring restdoc 正好一并把单元测试也写了
lihongjie0209
2019-04-24 20:10:15 +08:00
ddd 了解一下

CQRS 了解一下
lihongjie0209
2019-04-24 20:10:34 +08:00
@prasanta 你觉得这是一个语言问题?
brickyang
2019-04-24 20:14:59 +08:00
那些大厂的 API 有复杂的自定义错误码是因为是公开 API,给开发者们调用的,需要返回具体的错误细节和说明。自用的 API HTTP 错误码足够用。
chendy
2019-04-24 20:26:06 +08:00
rest 接口还是偏底层,真正到了 UI 层其实很难 rest,因为页面上要展示的内容和 domain 可能并不严格对应,只能在后台组装数据
至于错误码,http 的错误码相当于 Exception,响应 body 的错误码相当于异常的详细信息,相辅相成并不冲突
qiuxiaojie
2019-04-24 20:36:45 +08:00
楼主可以看一下我写的这个,定义一个 dsl,把需要的键,传进去做查询,可以传多层,就不用这样了。https://github.com/orql/orql-executor
onetown
2019-04-24 21:08:50 +08:00
现在又开始流行 graphql 了
yim7
2019-04-24 21:15:34 +08:00
有的框架会帮你做这事情,如果字段是外键查询实体序列化。我觉得应该写成两个接口……
winglight2016
2019-04-24 21:20:35 +08:00
一个接口里面做太多事情是这样的,所以要么用 GraphQL 这种自动按需整合协议,要么客户端自行拼装或者缓存 /同步,所以这实际是个架构问题,你们需要一个架构师从全局角度来做权衡。
leon0903
2019-04-24 21:21:56 +08:00
1. 我一直觉得 rest 返回码不如自定义返回码, 自定义返回码可以携带很多信息。要是我主导项目,我肯定不会首选 rest。
2. 文档感觉 swagger 已经不错了啊,现在我们这把就是用的 swagger,然后甩给前段。
lz 代码里面体现的问题我也确实经常遇到,感觉没什么好的办法,你这还好是 java 8,可以用 stream,其实简化了不少了。我用 go 开发这样的,都没办法,只能一次一次的遍历。。。
cubecube
2019-04-24 22:17:39 +08:00
如果前端调用,http 错误码也不是不够用。但是,后端系统之间肯定要有清晰的错误信息表示方式。另外,一般,都得有个中间层组装返回的,至于中间层用啥,都可以
buzailianxi
2019-04-25 13:51:16 +08:00
GraphQL 需要前端厉害。否则就会滥用
reid2017
2019-04-26 12:15:16 +08:00
用 Jpa 做个实体关联就行了,框架全帮你做了
qwerthhusn
2019-04-26 16:28:35 +08:00
如果是微服务的情况下,就不好使了。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/558315

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX