V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
qwerthhusn
V2EX  ›  Java

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

  •  
  •   qwerthhusn · 2019-04-24 17:03:05 +08:00 · 4045 次点击
    这是一个创建于 1800 天前的主题,其中的信息可能已经有所发展或是发生改变。
    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 条回复    2019-04-26 16:28:35 +08:00
    fishioon
        1
    fishioon  
       2019-04-24 17:34:18 +08:00
    结论是啥?
    prasanta
        2
    prasanta  
       2019-04-24 19:09:59 +08:00 via Android
    用 python 吧
    qwerthhusn
        3
    qwerthhusn  
    OP
       2019-04-24 19:43:45 +08:00
    没有结论,就是抛出这个问题
    wc951
        4
    wc951  
       2019-04-24 19:58:31 +08:00 via Android
    第一个问题你需要一个中间服务去整合数据,比如流行的 nodejs 中间层
    wc951
        5
    wc951  
       2019-04-24 20:00:03 +08:00 via Android
    文档的话我现在用的是 spring restdoc 正好一并把单元测试也写了
    lihongjie0209
        6
    lihongjie0209  
       2019-04-24 20:10:15 +08:00
    ddd 了解一下

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