寻找更加优秀的设计,疑惑很久的问题:同一个 Service 接口如何返回不同的错误信息 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
odirus
V2EX    Java

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

  •  
  •   odirus Nov 15, 2015 4689 views
    This topic created in 3817 days ago, the information mentioned may be changed or developed.
    假如一个 Service 提供了一个登陆接口,该 Service 会调用各种验证组件,比如 验证用户是否已经登陆、验证用户的 IP 是否在黑名单中、验证用户是否属于异地登录等等,当一切处理完成并验证登陆成功的时候,该接口就会返回成功。

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

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

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

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

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

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

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

    但是有时候,又需要返回其他对象, 这个我暂时还没有很好的解决方案。目前处理的方式是 尽量将这种情况拆开。
    ooTwToo
        14
    ooTwToo  
       Jul 22, 2016 via iPhone
    service 满目的 throws 会让我看起来很慌…
    honam
        15
    honam  
       Jul 22, 2016
    两种都做过,有直接抛 Exception 的,有在 service 返回状态码的,但是我觉得返回状态码更复杂,因为你必须描述和定义所有的异常情况并将其分类,多起来的时候还有可能出现重复定义。
    About     Help     Advertise     Blog     API     FAQ     Solana     3361 Online   Highest 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 53ms UTC 12:51 PVG 20:51 LAX 05:51 JFK 08:51
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86