关于Java中异常的设计

Java中异常分为checked 和 unchecked 两种.

首先, 什么时候使用checked,什么时候用unchecked?
1) checked本意是要求调用方处理这个异常, unchecked 本意就是这种异常调用方不需要处理, 如果出现了异常, 调用方不处理的话, 最终会在JVM中的某处捕获.
所以如果编写代码时,发现某一行可能会发生异常, 比如读数据库失败了, 如果你希望调用方在遇到这种情况时, 可以选择从其它地方读取, 那么这个错误,你可以
抛出checked异常, 让调用方去捕获它, 然后在catch中从其它地方读数据, 相反, 如果你觉得读db失败时, 调用方不需要处理, 而是应该直接让这个请求失败, 那你就
可以返回unchecked的异常, 调用方无需捕获, 异常最终会被JVM捕获.

如果抛出的是checked的异常, 那么我们要自定义自己的异常.
如果抛出的是unchecked的异常,通常我们建议, 继承RuntimeException, 而不是直接抛RuntimeException, 因为自定义的会更清晰,可以清楚的告诉调用方现在
导致问题的是什么异常.

2)异常可以帮助我们在出现问题时, 清楚的给出造成问题的原因, 但是光抛异常在直接面向客户端的这一层(API)层, 是不够的
因为我们服务层给出的异常信息, 和客户端直接想展示给客户的提示信息不是一一对应的, 所以服务端的API这一层通常是要针对service层的异常, 做一次封装.
(service层自己其实也可以返回带状态码的异常信息, 这里的异常信息并不是指调用栈, 通常仅仅是指造成异常的原因, 错误提示信息之类)

服务层如果可以返回带状态码的异常信息, 那么API层可以根据状态码, 建立一个面向客户端的异常信息表
当API层调用service返回某个异常时, 可以使用映射表, 转换成适合客户端给用户展示的错误信息.

总结:
1) 根据要不要让调用方处理来选择抛哪一类异常, 希望调用方处理则抛checked, 不希望则抛unchecked
2) 针对每一种异常情况, 自定义异常类, 代码更清晰
3) 面向客户的异常, 需要封装成response dto, 在dto中需要包含错误码和异常信息
4) 服务层的异常, 需要看调用方和服务层是不是在一个程序中, 如果在一个程序里, 那么服务层可以直接throw自定义的异常, 调用方直接try catch.
如果调用方和服务层不在一起, 那么双方需要协商好如何传递异常信息, 通常我们会采用类似response dto的方式, 自定义一套错误码, 把错误码和异常信息放在response dto里,
传回给调用方, 甚至可以吧异常实例也直接放到response dto里传回去.

猜你喜欢

转载自www.cnblogs.com/ctrlzhang/p/11681705.html