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

[讨论] Java 异常处理方式?

  •  
  •   BuilderQiu · 2016-03-21 09:35:28 +08:00 · 4982 次点击
    这是一个创建于 3198 天前的主题,其中的信息可能已经有所发展或是发生改变。

    Java 中异常应该如何处理?

    • 哪些地方应该抛异常?基础服务的方法校验到参数不符合标准的时候是返回错误状态码还是抛出异常?
    • 哪些地方应该捕获异常?

    感觉现在代码中的异常处理很混乱,有些调用栈比较长,每一个方法都在捕获异常打印日志,一个方法抛出异常,接连的就会有一堆方法去捕获+打印日志,然后一堆日志都是同一个异常的。

    大家都是怎么处理的?

    13 条回复    2016-03-22 04:28:23 +08:00
    Lpl
        1
    Lpl  
       2016-03-21 09:59:30 +08:00 via Android
    不符合标准的话直接返回错误码。
    在对业务进行处理的时候,抛异常。比如接受到别的接口返回的错误码,直接就抛出; 与数据库相关的也抛出,不要 catch; 与文件相关的也抛出。一些感觉不重要的,不会影响也许逻辑的,直接 catch ,然后放到 info 中。

    应该是这样吧...错了拍砖
    fwrq41251
        2
    fwrq41251  
       2016-03-21 10:09:00 +08:00
    要么处理异常,要么抛出异常,不要都做。
    “一堆日志都是同一个异常的”显然违反了这个规则, LOG 的同时又往上抛了。
    还有一个比较简单的规则是异常应该尽可能早的抛出,尽可能晚的处理。
    BuilderQiu
        3
    BuilderQiu  
    OP
       2016-03-21 10:28:38 +08:00
    @Lpl
    返回错误码造成了现在的接口方法之类的,返回的数据都不单一,基本上方法的返回值都包括了:
    1.是否执行成功
    2.真正的返回值数据
    3.错误码
    4.错误信息
    ...疼...

    @fwrq41251
    每个地方都记录日志是因为怕异常抛出去了,调用的方法没有进行捕获,最后异常信息丢了没法排查。。
    Web 应用内部调用最后的出口一般都在 Controller ,那是不是只在这里捕获异常就好了?其他地方一般的异常(特殊情况除外)都可以直接抛出来不处理。。
    odirus
        4
    odirus  
       2016-03-21 10:31:22 +08:00
    http://v2ex.com/t/236371#reply12

    也许这条帖子对你有用
    crazyxin1988
        5
    crazyxin1988  
       2016-03-21 10:40:21 +08:00
    最近一次重构一个后端项目时,这样处理的。
    层层方法调用,不全用 checked exception ,层层都要 try catch ,代码看起来拖沓。
    内部使用 runtime exception
    在最后的外部调用接口使用 checked exception
    这样做强制外部系统在调用时,要 try catch ,也方便外部进行异常的转换
    fwrq41251
        6
    fwrq41251  
       2016-03-21 10:45:52 +08:00
    @BuilderQiu
    再晚一点,如果你用的是 spring mvc ,实现你自己的 HandlerExceptionResolver ,在这里做通用的返回。
    需要特殊处理的,就抛出需要捕获的异常,在业务代码里 catch 住处理。
    janxin
        7
    janxin  
       2016-03-21 10:50:51 +08:00
    这个基本上跟语言完全无关,现在基本上看需求决定:数据一致性要求高的,在数据库操作时 catch 后做回滚之类的操作;业务逻辑处理层大部分都是抛异常到顶层 Controller 统一处理。
    hantsy
        8
    hantsy  
       2016-03-21 10:56:19 +08:00
    Java 异常可以分为 Checked 和 UnChecked 异常,异常设计时如何选择,一直存在争议。

    Spring 内部全部使用 Unchecked Exception ,在你的代码中几乎不需要 try/catch 来捕捉,它内置一套机制来处理异常, ExceptionTranslator (异常转换), ExceptionHandler ( Web 异常处理), retry (一些批处理中可以设置遇到异常重新执行)。这种好处是不需要关心太多的异常处理,坏处很多异常到运行时才能发现。

    但从接口的设计角度看, Checked 异常有时会让接口看起来比较清晰。

    比如,在接口定义了一个方法中要求实现类中 **强制** 检测库存情况:
    addProductIntoCart(String product) throws OutOfStockException{}

    在实际项目,自己可以设计合理的异常类,在业务实现层面抛出来,如果是 Spring 程序用 ExceptionHanlder 来处理。其它 Web 框架也相应的 Exception 处理机制。

    异常可以与 Logger 结合起来,以便日后日志分析,一些第三方的 Cloud 服务,如 logentries 也提供日志分析能力,都提供了常用 Logger 的一些扩展方法,这样日志收集起来,完全可以做到可视化。
    BuilderQiu
        9
    BuilderQiu  
    OP
       2016-03-21 12:59:14 +08:00
    @odirus
    这个表示可以使用抛异常的方式处理业务异常等哇,现在不用异常就是一堆判断。。


    @crazyxin1988
    这个办法感觉不错,可以解决这一堆 trycatch 的问题,不过要区分哪些算作内部哪些算作外部的问题

    @fwrq41251
    嗯,现在基本就是 SpringMVC ,但是抛出异常的地方打印日志感觉能输出更多的业务数据信息,最外层统一处理的话有些数据就不好拿了,除非 catch 了异常,封装再抛出,不记录日志。

    @janxin
    是的,我指的是一般的业务上的异常,数据库这种涉及到事务处理的肯定就是当场抛出回滚解决了


    @hantsy
    感觉现在 checked exception 用的都比较少,方便编码。。
    hantsy
        10
    hantsy  
       2016-03-21 14:07:04 +08:00
    @BuilderQiu 跟方便编码一点关系都没有。。。看来你们从来没把异常设计加入到基础架构考虑中去。
    BuilderQiu
        11
    BuilderQiu  
    OP
       2016-03-21 14:14:36 +08:00
    @hantsy

    我说的是用 unchecked 编码起来不用刻意去 trycatch 。。

    然后,确实也没太设计异常这一块, so ,有了这个帖子。。
    qwepoidjdj
        12
    qwepoidjdj  
       2016-03-21 15:28:43 +08:00
    首先定义顶级异常类型 例如系统级 业务级等(用 uncheck 类型就行)
    此后如有需要定义新异常 必须去继承顶级异常 区分异常类型 区分处理方式 区分 LOG 级别 各种区别对待
    框架要有全局异常处理机制 所有异常底层都不要 catch 需要抛的全抛 统一由全局异常处理机制处理

    这个问题仔细一下就能明白
    在开发程序的时候不可能把所有问题都想清楚 想明白 不出问题
    落实到代码上来说 当你去调用一个方法的时候 难道要把所有出错的可能都处理了么?
    这明显是不可能的 错误的原因各种奇葩 大部分都是代码问题 只能事后分析修补
    SoloCompany
        13
    SoloCompany  
       2016-03-22 04:28:23 +08:00
    想不明白到现在怎么还会有人觉得 checked exception 可以使 api 更清晰的

    这简直是一个大毒瘤,尤其到了 java 8 这个问题就暴露的更彻底了,你试一下给每一个 SAM 接口都增加一套抛异常的版本试试?

    再想想为什么 Appenable 被迫声明为抛出 IOException 导致你不得不使用 StringBuilder 来处理个字符串拼接任务还不得不捕获 IOException 然后无意义的不处理的时候是什么感受
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2970 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 13:18 · PVG 21:18 · LAX 05:18 · JFK 08:18
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.