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

寻找更加优秀的设计,疑惑很久的问题:同一个 Service 接口如何返回不同的错误信息

  •  
  •   odirus · 2015-11-15 19:54:37 +08:00 · 4211 次点击
    这是一个创建于 3297 天前的主题,其中的信息可能已经有所发展或是发生改变。
    假如一个 Service 提供了一个登陆接口,该 Service 会调用各种验证组件,比如 验证用户是否已经登陆、验证用户的 IP 是否在黑名单中、验证用户是否属于异地登录等等,当一切处理完成并验证登陆成功的时候,该接口就会返回成功。

    问题是,在 Service 调用这些验证组件过程中如果产生了错误,那应该怎么返回给调用方最合适呢?

    我没有在 Controller 中对认证组件依次验证并返回错误给用户,我更愿意封装在 Service , Controller 中我不想写太多复杂的东西。

    我在 Java 中没有形成比较良好的思想体系,所以特来向各位请教,希望早日能让自己融入 Java 中,感谢你能分享优秀的方式、方法或者意见、建议,谢谢。

    另外,以前我的两种处理方式:
    ( 1 )当 Controller 调用 Service 中的某个方法的时候,我会为本次调用建立一个错误栈,用来保存应该返回给用户的系统错误状态码,在 Service 调用某个组件并返回错误的时候,我就会把这个错误压入错误栈中,当遇到致命错误的时候(有些组件即使验证错误,但不是关键性错误可以忽略并继续接下来的流程), Service 就会返回给调用方,即 Controller ,此时 Controller 会去错误栈中找到最近一次的错误状态信息并返回给用户,并且把栈中的其他信息写入日志中,方便日后跟踪某位用户并单独对其调试分析。

    ( 2 )这种方法更傻,直接新建一个异常类,专门用来处理用户的错误,当遇到致命错误的时候,我就抛出一个异常(异常的第一个参数就是系统错误状态码),此时代码不会往下继续执行,统一在最顶层捕获这种类型的异常,然后返回给用户,记录此次请求的错误信息,方便日后分析。这种方法会导致内存消耗比较大,因为使用异常来完成对程序的终止并返回。

    如果你有更好的姿势,麻烦教我一下,谢谢。
    15 条回复    2016-07-22 09:24:04 +08:00
    xujif
        1
    xujif  
       2015-11-15 23:34:22 +08:00 via iPhone
    2 是最常规的方法,怎么是傻了?
    inmyfree
        2
    inmyfree  
       2015-11-15 23:51:48 +08:00
    我这边都是第二种的,服务器会有一个错误编码表, app 使用一个常量类,结合接口判断使用就是了
    br00k
        3
    br00k  
       2015-11-16 01:33:03 +08:00 via Android
    2
    raysmond
        4
    raysmond  
       2015-11-16 01:50:36 +08:00 via iPhone
    我也觉得是 2 ,抛异常很普遍的方案。很多成熟的项目都是这么干的
    odirus
        5
    odirus  
    OP
       2015-11-16 07:31:49 +08:00
    @xujif 不好意思,第二种方案是很早之前,我刚入门的时候自己想出来的,当时真没什么经验,然后就造了个轮子,只是看到书上说异常的消耗会非常大,所以有这种感觉。谢谢哈。
    odirus
        6
    odirus  
    OP
       2015-11-16 07:32:22 +08:00
    @inmyfree
    @br00k
    @raysmond

    谢谢哈
    Bryan0Z
        7
    Bryan0Z  
       2015-11-16 10:02:31 +08:00 via Android
    看到你说第二种很傻的时候突然很惶恐,然后看到其他人的回复我放心了
    odirus
        8
    odirus  
    OP
       2015-11-16 10:12:33 +08:00
    @Bryan0Z 不用担心,因为据我观察,真的是各个项目千奇百怪的。。。所以特来请教有没有统一的办法。
    buliugu
        9
    buliugu  
       2015-11-16 13:20:23 +08:00
    直接抛不要虚,抛得越早越好
    odirus
        10
    odirus  
    OP
       2015-11-16 13:30:23 +08:00
    @buliugu 哈哈哈,好有川味儿的赶脚。
    zonghua
        11
    zonghua  
       2015-11-17 14:36:51 +08:00 via iPhone
    我是用二,手动校验数据。
    xujif
        12
    xujif  
       2015-11-17 14:40:56 +08:00
    @odirus 理论上来说返回错误的方法无非是:
    1.全局 errno ( c 经常用,配合非 0 等返回)
    2.异常( c++开始, java 等 c 系语言)
    3.rust 这种 enum 返回值
    4.go 这种多返回值
    其他我就不清楚了
    java 里就没有比抛异常更好的了,如果抛异常,每次方法返回的时候都要判断下返回值,性能反而更低
    palmers
        13
    palmers  
       2016-03-22 10:41:33 +08:00
    我比较常用的是: 使用错误消息对象封装错误码和错误消息,这个对象一般有下面三个成员:
    1. 状态 boolean 冗余这个成员是为了快速判断
    2. 错误码
    3. 错误消息
    一般使用枚举将错误码归类统计,同时默认错误消息,也提供一个错误消息设置接口,便于错误消息自定义, 然后返回该错误消息对象,根据状态判断是否调用通过,对应处理。

    但是有时候,又需要返回其他对象, 这个我暂时还没有很好的解决方案。目前处理的方式是 尽量将这种情况拆开。
    ooTwToo
        14
    ooTwToo  
       2016-07-22 08:58:20 +08:00 via iPhone
    service 满目的 throws 会让我看起来很慌…
    honam
        15
    honam  
       2016-07-22 09:24:04 +08:00
    两种都做过,有直接抛 Exception 的,有在 service 返回状态码的,但是我觉得返回状态码更复杂,因为你必须描述和定义所有的异常情况并将其分类,多起来的时候还有可能出现重复定义。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5810 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 06:30 · PVG 14:30 · LAX 22:30 · JFK 01:30
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.