如何优雅的在 Java 方法同时返回 状态码 和 结果

2019-07-23 16:24:35 +08:00
 binbinyouliiii

写 Spring Web 的各位估计都写过返回 JSON 的项目,一般的结构都是这样的

{
    "status":200,
    "msg":"正常"
    "data":{
        ......
    }
}

{
    "status":201,
    "msg":"非正常"
}

按理说 Controller 层不参与业务的处理,顶多校验一下合法性之类的,所以大多数状态码都是交给 Service 层来返回的,可是 Java 的方法只能返回一个结果,想要返回多个结果只能包装成一个对象。但是包装成这样总感觉不舒服,照理说不应该由 service 层包装。

public Package<User> getUser(){
    User user = new User();
    
    if(user.getAge!=10){
        //返回非正常
        return new Package(201,null);
    }
    //返回正常
    return new Package(200,user);
}

我想到的还有一种方式就是用 Exception 来做,直接把状态码放到 Exception 中,非 200 状态的就让 Controller 层 catch 后处理,好处就语法上就会有强制性 catch,但是这样做就会出现遇到 如果有多个正常状态码,Controller 层无法处理的问题:

public User getUser() throws CustomException {
    User user = new User();
    
    if(user.getAge!=10){
        //返回异常
        throw new CustomException(201);
    }
    //返回正常
    return user;
}

请教大家平常用什么方法比较优雅。

7328 次点击
所在节点    Java
28 条回复
ke1e
2019-07-23 18:15:30 +08:00
一个简单的方法,所有方法都返回同一个类,假设是 TopContext,有状态码和 data 属性,再提供静态方法,例如 TopContext.ok(data),这样就可以实现。但是还是有点复杂
liuxey
2019-07-23 19:54:37 +08:00
我见过一个国内知名公司使用四层结构,在 controller 和 service 层增加 facade 层,然后 controller 就真只做接收校验和返回

虽然有人可能不喜欢,但使用异常来结束业务代码真的很精简,写起来及其飘逸

当然还有 http 状态码设计等东西,我觉的没有孰优孰劣,用好了用统一了都是值得肯定的
shipy
2019-07-23 19:56:31 +08:00
用元组呀
palmers
2019-07-23 20:12:21 +08:00
异常和状态码的作用目的是不一样的,你这么用是不对的, 再者 java 是面向对象语言,应该站在对象的角度来考虑 如果按照对象角度返回状态对象就是合理的, 再者 底层抛出异常代表这个是无法容忍的错误, 不应该继续后续逻辑,而不是应该用来设计不同的状态
springmarker
2019-07-23 20:28:49 +08:00
@Takamine #20 状态码的包装也由 service 层来处理的话,那碰到 service 之间的调用难道还得 get 出来 data 才行?
顺便问一下,你们的状态码 code 的枚举类是怎么维护的,是每个项目一个?还是所有项目共用?共用的话是怎么维护的,谢谢。

@ke1e #21 我之前就是这么做的,但是还是属于我说的第一种类型,就是包装,感觉不够清真。

@liuxey #22 写 4 层是真的要死了。

@shipy #23 元组在 Java 中并不原生,某种程度上来说跟包装差不多。

@palmers #24 绝大多数业务就是 一个正常状态+多个异常状态 ,我觉得 业务的抛出非正常状态代码也可以理解为“异常”,catch 的话,只需 catch 住我们自定义的异常就可以了,其他无法容忍的错误该怎么还是怎么样
lihongjie0209
2019-07-23 20:34:58 +08:00
业务层直接抛异常, controller 只处理正常情况, 异常情况同意用拦截器翻译异常类型以及异常信息发送给前端
lwd369
2019-07-23 20:41:31 +08:00
正好今天白天一直在纠结这个问题,在 service 层处理非正常响应时,直接抛出一个 exception,然后用 ExceptionHandler 里统一返回,不知道这样使用异常是否合理。如果使用普通的 ifelse 流程控制的话,要把错误状态返回给 controller 层似乎又有点麻烦。
Takamine
2019-07-24 00:15:07 +08:00
@springmarker 是的,只要是暴露出去的都做封装,不管是业务之间还是应用之间。
我们是不同系统用不同状态码,一般一个系统会分别领取分别代表业务异常、系统异常等的不同数字编号开头的 500-2000 个状态码。后面新增的系统再接着申请领取状态码,以此类推。所有系统的状态码有做统一维护。

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

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

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

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

© 2021 V2EX