真的需要自定义异常吗[重复]
Posted
技术标签:
【中文标题】真的需要自定义异常吗[重复]【英文标题】:Are Custom Exceptions really needed [duplicate] 【发布时间】:2020-06-17 07:39:57 【问题描述】:我对异常处理有一些基本的了解,但我仍然不明白什么时候真正需要创建自定义异常。
好吧,我知道如果自定义异常提供了一些额外的字段,那么自定义异常真的很有帮助,否则我们可以使用标准异常。
但我的问题是:
-
如果我们选择标准异常,假设我在多个微服务中使用
throw new RuntimeException("blah blah")
,那么我如何能够快速识别哪个微服务抛出了这个异常?当然,我可以通过查看日志来识别它,但是,抛出标准异常而不是使用自定义异常是一种好习惯吗?
在我的项目中,在每个微服务中,我都看到正在创建自定义异常,它们只是扩展 RuntimeException 并且在任何这些自定义异常中都没有额外的信息。您认为这种做法是好是坏?
如果我在 google 上搜索这个主题,常用的 sn-p 代码是这样的:
NameNotFoundException:
public class NameNotFoundException extends Exception
public NameNotFoundException(String message)
super(message);
您认为应该使用像这样的基本自定义异常吗?
【问题讨论】:
When should we create our own Java exception classes? john - 如果其中一个答案解决了您的问题,您可以通过将其标记为已接受来帮助社区。接受的答案有助于未来的访问者自信地使用该解决方案。查看meta.stackexchange.com/questions/5234/… 了解如何操作。 【参考方案1】:我们处理 REST 调用,很多(以至于我们编写了自己的 JDK 的 HTTP 客户端包装器);多次调用不仅是我们的端点。在与这些端点通信时,我们定义了一个自定义异常,例如:
class OurCustom extends ...
int httpCode;
String receivedMessage;
OffSetDateTime receivedAt;
我的意思是,这可以解决两个问题。
意图当我看到某个服务抛出这个OurCustom
时,我立即知道它的意图是什么,我明白我应该采取什么行动以及它有什么方法。如果那是一个普通的RuntimeException
,那就有点困难了。
您可以向自定义异常添加更多内容,而不仅仅是消息本身,例如 httpCode
或 message
。这简化了必须与此异常交互的人们的生活。但是,在没有任何附加信息的情况下简单地扩展它也可能是有价值的,这取决于。
所以是的,在某些情况下我觉得这非常有用。
【讨论】:
【参考方案2】:在错误情况下,JVM 本身也会抛出 RuntimeException。因此,如果您想在 catch-blocks 中处理您的异常,您将无法轻松区分。
如果我们选择标准异常,比方说,如果我在多个微服务中使用 throw new RuntTimeException("blah blah"),那么我们如何轻松快速地识别出这个异常来自哪个微服务? (假设我们有 30 个微服务)。当然,通过查看日志,我们可以确定是从哪个异常中获取的。但是,这是抛出标准异常而不是自定义异常的好习惯吗?
我猜微服务有某种 Web API(即 HTTP),所以调用者不能看到“裸”的 RuntimeExceptions - 否则你的 API 取决于你的编程语言,而你被困在 Java 上。 如果您的意思是您正在基于 RuntimeExceptions 进行异常映射,那么您可能不够精确 - 如果您使用的某个库抛出 RuntimeException 怎么办? 最好使用你自己的异常类。
最小的映射是将异常映射到 HTTP 错误代码恕我直言,即 200/OK、400/Bad Request 或 403/Forbidden。
2) 在我的项目中,在每个微服务中,我都看到了自定义异常 创建后,它们只是扩展了 RuntimeException 而没有额外的信息 在任何这些自定义异常中。你说,我们做错了吗?
这并没有错。错误代码或消息用于处理和/或显示它们。您可以看看 Jersey JAX-RS 服务here 的一些异常映射技术。
您是否认为根本不应该创建上述自定义异常?
我认为您需要在每个微服务中定义一个简单的方法来生成错误消息。一种非常简单的方法是将异常映射到 HTTP 状态代码(上例)。另一种方法是显式发送 HTTP 状态而不使用异常。传递状态码对于非常简单的代码来说是可以的:
return Response
.status(Response.Status.OK)
.build();
我的建议:从最简单的方法(直接状态代码)开始,如果需要,改用异常映射器等更抽象的方法(KISS - 保持健全和简单)。
【讨论】:
【参考方案3】:我在我的项目中总是使用自定义异常:
public class BaseAppException extends RuntimeException
public BaseAppException(String message)
super(message);
@Override
public synchronized Throwable fillInStackTrace()
// disable Stacktrace per default
return this;
public ResponseEntity<ErrorResponse> toResponseEntity()
return [...]
public UserNotFoundException extends BaseAppAxception
public UserNotFoundException(String idUsed)
super("No User found for ID:" + idUsed);
[...]
所以我可以用同样的方式处理我所有的异常(伪代码):
@ExceptionHandler(BaseAppException.class)
public final ResponseEntity<ErrorResponse> handleAppException(BaseAppException ex)
return ex.toResponseEntity();
@ExceptionHandler(Exception.class)
public final ResponseEntity<ErrorResponse> handleAppException(Exception ex)
ErrorResponse error = new ErrorResponse(ApplicationConstants.SERVER_ERROR, ex.getMessage());
return new ResponseEntity<>(error, HttpStatus.INTERNAL_SERVER_ERROR);
这只是一个例子,但我希望我能展示一下这个想法。
您还应该使用自定义异常来隐藏错误消息。见我的UserNotFoundException
【讨论】:
【参考方案4】:一般情况下,以下情况需要自定义异常:
-
标记不符合标准异常的错误/异常情况。
将其与标准异常区分开来。
添加对日志记录/调试等有用的附加信息。
在我的项目中,在每个微服务中,我都看到了自定义异常 创建后,它们只是扩展了 RuntimeException 而没有额外的信息 在任何这些自定义异常中。你说,我们做错了吗?
没有错,但如果不符合上述任何一种情况,则没有必要。
【讨论】:
【参考方案5】:您可以使用异常做更多的事情,而不仅仅是输出消息。即使您的自定义异常只不过是基类的包装器,它也为您提供了如何最好地处理各种异常的选项。有时您只需要更新一个 UI 组件。有时您需要记录错误以进行进一步检查。也许您需要强制关闭应用程序或窗口。例如,如果您有一个验证某些数据的方法,您可能会遇到无效数据异常,它只是将 UI 元素更改为错误样式。如果验证器本身抛出异常怎么办?然后,您需要记录它并通知用户出现严重错误。
【讨论】:
以上是关于真的需要自定义异常吗[重复]的主要内容,如果未能解决你的问题,请参考以下文章