关于业务异常的处理方式

2020-11-14 17:43:57 +08:00
 Dingjiangnan

新手提问:“关于业务异常的处理方式”,在 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: "用户名不正确"
    
}

两个问题:

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

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

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

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

还没开始做,未知可能出现的坑,如果需要包装,就 try 捕获一下再抛。
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
2020-11-14 22:27:00 +08:00
http status code + 业务错误码
EminemW
2020-11-15 00:43:41 +08:00
@imdong #4 自定义异常不也要先判断再抛吗
fewok
2020-11-15 01:03:14 +08:00
我个人偏向错误码。但是多人合作,一定要用异常。
个人我能搞一个贯穿所有方法的 BO 基类,自己造流程编排,控制下一步该怎么做。同步、异步、并发、响应式等等轻轻松松流程调度。
而队友多了,难免出现调完你返回错误码的方法,还继续向下执行的猪队友(强制捕获很重要)。
raysmond
2020-11-15 01:06:56 +08:00
我是这么干的:
1 、全局 AOP 捕获异常,业务异常 base class 包含有业务含义的 code 、message 等字段
2 、对异常分类,根据 restful 规范,返回同步的 http status,例如:
400 参数错误; 401 无权限; 404 未找到; 500 系统错误,包括未知异常类; 429 限流;等等

http status 代表的接口状态,对异常分大类;而 body 里的 code,代表的是具有业务含义的状态,比如用户被禁用 10025 、用户登录异常 10026 这些
fewok
2020-11-15 01:10:53 +08:00
关于 http status,restful 规范只是为了简化理解难度而增加实现复杂度而已,意义不大,可以丢弃。
yogogo
2020-11-15 08:37:58 +08:00
我是混合使用,看场景!主要业务处理,比如事务处理的时候用异常处理,其他就 return !异常处理会消耗性能
xuanbg
2020-11-15 10:12:15 +08:00
throw 的好处是不需要管返回值,这在方法被其他方法调用时很有优势。被调用者不需要返回 null 什么的,调用者也不需要写相应的调用错误判断逻辑。
zzl22100048
2020-11-15 21:16:49 +08:00
java 当然是用 problem-spring-web 库解决
i4color
2020-11-15 22:12:59 +08:00
少部分用 http status.大部分用业务 的 状态码。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/725240

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX