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

关于业务异常的处理方式

  •  
  •   Dingjiangnan · 2020-11-14 17:43:57 +08:00 · 2854 次点击
    这是一个创建于 1470 天前的主题,其中的信息可能已经有所发展或是发生改变。

    新手提问:“关于业务异常的处理方式”,在 V 站搜了一下都是很久以前的旧帖子,所以开个新帖提问

    之前的公司是完全不用异常,比如用户名不正确的处理:

    
    public void login(String username,String password){
    
    	
        User user = db.getUsername(username);
      
        if(user==null){
        
        	//UnifyResponse 是统一响应实体类,参数 1:code,参数 2:message
    
        	return UnifyResponse.FAIL(400,"用户不存在");
        }
        
    }
    

    返回给前端的格式:

    http status : 200
    
    {
    	code: 400,
        message: "用户名不正确"
    }
    

    现在这家公司是这样的:

    
    public void login(String username,String password){
    
    	
        User user = db.getUsername(username);
      
        if(user==null){
        
        	//UnifyResponse 是统一响应实体类,参数 1:code,参数 2:message
            
        	throw new NotFoundException(400,"用户名不正确")
        }
        
    }
    

    返回给前端的格式:

    http status : 404
    
    {
    	code: 400,
        message: "用户名不正确"
        
    }
    

    两个问题:

    • 关于业务的处理,是这届 return,还是 throw 异常之后,全局进行捕获再 return ?
    • 关于 http status,是无论是否成功都返回 200,还是遵循 restful 规范,404 不存在,403 无权限?

    大家说说哪种处理更好?前端同学能否接受 restful 的 http status 规范

    14 条回复    2020-11-15 22:12:59 +08:00
    Dingjiangnan
        1
    Dingjiangnan  
    OP
       2020-11-14 17:46:39 +08:00
    这届 -> 直接
    cabing
        2
    cabing  
       2020-11-14 17:54:13 +08:00
    1 定义统一自有的状态码
    2 直接返回结果对象呢?
    bl
        3
    bl  
       2020-11-14 17:57:45 +08:00
    自己异常类,自定义 ErrorCode 。不在业务代码里面编写具体的异常信息
    imdong
        4
    imdong  
       2020-11-14 19:04:32 +08:00   ❤️ 1
    最近到新公司,带新项目,我计划全程用异常了。

    如果用 return 嵌套多层的代码,每一层都要判断 + return 太费事了。

    现在用异常,哪里出错哪里抛,外面再也不需要管这些了。

    还没开始做,未知可能出现的坑,如果需要包装,就 try 捕获一下再抛。
    dustinth
        5
    dustinth  
       2020-11-14 19:18:03 +08:00
    这个界限确实比较模糊, 因为不同的系统 part 之间, 对于异常是有不同的理解的: 比如要实现一个 Map 的 API, 如果 get 一个不存在的 key 是返回空值还是 throw exception 呢? 站在 API 实现方, 他可能倾向于把这个当做异常; 而站在 API 调用方则倾向于返回空值, 因为这样可以用比较轻量的方式处理这样的"异常"逻辑分支.

    总结一个不太实用的定义: "不要用异常来控制主业务逻辑分支". 说不太实用是因为, 不同人对什么是"主业务逻辑"的理解是不同的.

    LZ 举得例子就比较典型, 因为既可以把 UserNotFound 当做业务逻辑的一部分(和其他类型的异常, 比如网络错误,服务器错误等还是有些概念上的区别的), 也可以当做异常. 我个人觉得, 如果对 500/404/400 等前端处理逻辑都是一样的话(比如在某个地方显示 warning message),那么返回异常比较好; 如果对 404 有额外的逻辑业务处理, 则返回空值更好.
    hdfg159
        6
    hdfg159  
       2020-11-14 22:27:00 +08:00 via Android
    http status code + 业务错误码
    EminemW
        7
    EminemW  
       2020-11-15 00:43:41 +08:00
    @imdong #4 自定义异常不也要先判断再抛吗
    fewok
        8
    fewok  
       2020-11-15 01:03:14 +08:00
    我个人偏向错误码。但是多人合作,一定要用异常。
    个人我能搞一个贯穿所有方法的 BO 基类,自己造流程编排,控制下一步该怎么做。同步、异步、并发、响应式等等轻轻松松流程调度。
    而队友多了,难免出现调完你返回错误码的方法,还继续向下执行的猪队友(强制捕获很重要)。
    raysmond
        9
    raysmond  
       2020-11-15 01:06:56 +08:00   ❤️ 1
    我是这么干的:
    1 、全局 AOP 捕获异常,业务异常 base class 包含有业务含义的 code 、message 等字段
    2 、对异常分类,根据 restful 规范,返回同步的 http status,例如:
    400 参数错误; 401 无权限; 404 未找到; 500 系统错误,包括未知异常类; 429 限流;等等

    http status 代表的接口状态,对异常分大类;而 body 里的 code,代表的是具有业务含义的状态,比如用户被禁用 10025 、用户登录异常 10026 这些
    fewok
        10
    fewok  
       2020-11-15 01:10:53 +08:00
    关于 http status,restful 规范只是为了简化理解难度而增加实现复杂度而已,意义不大,可以丢弃。
    yogogo
        11
    yogogo  
       2020-11-15 08:37:58 +08:00 via Android
    我是混合使用,看场景!主要业务处理,比如事务处理的时候用异常处理,其他就 return !异常处理会消耗性能
    xuanbg
        12
    xuanbg  
       2020-11-15 10:12:15 +08:00
    throw 的好处是不需要管返回值,这在方法被其他方法调用时很有优势。被调用者不需要返回 null 什么的,调用者也不需要写相应的调用错误判断逻辑。
    zzl22100048
        13
    zzl22100048  
       2020-11-15 21:16:49 +08:00 via iPhone
    java 当然是用 problem-spring-web 库解决
    i4color
        14
    i4color  
       2020-11-15 22:12:59 +08:00
    少部分用 http status.大部分用业务 的 状态码。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2706 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 12:31 · PVG 20:31 · LAX 04:31 · JFK 07:31
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.