qwerthhusn
V2EX  ›  Java

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

  •  
  •   qwerthhusn · Apr 24, 2019 · 5168 views
    This topic created in 2751 days ago, the information mentioned may be changed or developed.
    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 或者其他的东西。

    18 replies  •  2019-04-26 16:28:35 +08:00
    fishioon
    fishioon
    Apr 24, 2019
    1
    结论是啥?
    prasanta
    prasanta
    Apr 24, 2019 via Android
    2
    用 python 吧
    qwerthhusn
    qwerthhusn
    OP
    Apr 24, 2019
    3
    没有结论,就是抛出这个问题
    wc951
    wc951
    Apr 24, 2019 via Android
    4
    第一个问题你需要一个中间服务去整合数据,比如流行的 nodejs 中间层
    wc951
    wc951
    Apr 24, 2019 via Android
    5
    文档的话我现在用的是 spring restdoc 正好一并把单元测试也写了
    lihongjie0209
    lihongjie0209
    Apr 24, 2019
    6
    ddd 了解一下

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