• 请不要在回答技术问题时复制粘贴 AI 生成的内容
Dingjiangnan
V2EX  ›  程序员

关于业务异常的处理方式

  •  
  •   Dingjiangnan · Nov 14, 2020 · 3391 views
    This topic created in 2030 days ago, the information mentioned may be changed or developed.

    新手提问:“关于业务异常的处理方式”,在 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 replies    2020-11-15 22:12:59 +08:00
    Dingjiangnan
        1
    Dingjiangnan  
    OP
       Nov 14, 2020
    这届 -> 直接
    cabing
        2
    cabing  
       Nov 14, 2020
    1 定义统一自有的状态码
    2 直接返回结果对象呢?
    bl
        3
    bl  
       Nov 14, 2020
    自己异常类,自定义 ErrorCode 。不在业务代码里面编写具体的异常信息
    imdong
        4
    imdong  
       Nov 14, 2020   ❤️ 1
    最近到新公司,带新项目,我计划全程用异常了。

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

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

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

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

    LZ 举得例子就比较典型, 因为既可以把 UserNotFound 当做业务逻辑的一部分(和其他类型的异常, 比如网络错误,服务器错误等还是有些概念上的区别的), 也可以当做异常. 我个人觉得, 如果对 500/404/400 等前端处理逻辑都是一样的话(比如在某个地方显示 warning message),那么返回异常比较好; 如果对 404 有额外的逻辑业务处理, 则返回空值更好.
    hdfg159
        6
    hdfg159  
       Nov 14, 2020 via Android
    http status code + 业务错误码
    EminemW
        7
    EminemW  
       Nov 15, 2020
    @imdong #4 自定义异常不也要先判断再抛吗
    fewok
        8
    fewok  
       Nov 15, 2020
    我个人偏向错误码。但是多人合作,一定要用异常。
    个人我能搞一个贯穿所有方法的 BO 基类,自己造流程编排,控制下一步该怎么做。同步、异步、并发、响应式等等轻轻松松流程调度。
    而队友多了,难免出现调完你返回错误码的方法,还继续向下执行的猪队友(强制捕获很重要)。
    raysmond
        9
    raysmond  
       Nov 15, 2020   ❤️ 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  
       Nov 15, 2020
    关于 http status,restful 规范只是为了简化理解难度而增加实现复杂度而已,意义不大,可以丢弃。
    yogogo
        11
    yogogo  
       Nov 15, 2020 via Android
    我是混合使用,看场景!主要业务处理,比如事务处理的时候用异常处理,其他就 return !异常处理会消耗性能
    xuanbg
        12
    xuanbg  
       Nov 15, 2020
    throw 的好处是不需要管返回值,这在方法被其他方法调用时很有优势。被调用者不需要返回 null 什么的,调用者也不需要写相应的调用错误判断逻辑。
    zzl22100048
        13
    zzl22100048  
       Nov 15, 2020 via iPhone
    java 当然是用 problem-spring-web 库解决
    i4color
        14
    i4color  
       Nov 15, 2020
    少部分用 http status.大部分用业务 的 状态码。
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   2847 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 55ms · UTC 08:07 · PVG 16:07 · LAX 01:07 · JFK 04:07
    ♥ Do have faith in what you're doing.