如何确定异常处理程序的响应状态?

时间:2018-10-01 11:40:53

标签: java rest spring-mvc exception http-response-codes

我在控制器中使用异常处理程序,如下所示:

@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.CONFLICT)
@ResponseBody
public ApiError handleException(Exception e) {
    logger.error("Exception occurred {}", e.getMessage(), e);
    return new ApiError(HttpStatus.CONFLICT, e.getMessage());
}

现在,我考虑选择正确的响应状态取决于异常类型。最佳做法有什么关系?

现代的方法是在所有地方都使用Runtime异常,因此不确定对所有Runtime异常使用4XX响应代码总是正确的。

您能澄清吗?

P.S。

我强调4XX是客户端错误,而5XX是服务器错误。

3 个答案:

答案 0 :(得分:0)

恕我直言,它只是不依赖于运行时vs已检查的异常模式,而是取决于语义上的正确区分。

  • 默认情况下,异常类型不反映此语义。
  • 5xx告诉客户您这边出了问题。
  • 4xx告诉客户端,API的使用方式“错误”或未按预期方式使用。
  • 您可以使用运行时或已检查的异常来实现4xx或5xx状态代码。这仅取决于您自己的软件体系结构。
  • 我不会根据已检查异常或运行时异常(似乎会损害principle of least astonishment - POLA)的差异来确定4xx / 5xx

答案 1 :(得分:0)

就个人而言,当运行时出现问题时,我只是将自定义Exception抛回控制器,然后自动创建ResponseEntity,并使用HttpStatus代码返回我的Exception。我尝试尽可能多地保持逻辑,并返回更清晰的代码以及消息和异常字符串名称。

赞: 预处理失败时(不是由于客户端有效负载而导致的)HttpStatus.PRECONDITION_FAILED HttpStatus.BAD_REQUEST从客户端接收到的有效负载中出现问题时 HttpStatus.NO_CONTENT,当一切正常,但我们返回空响应,因为未找到结果  等等...

答案 2 :(得分:0)

您处在正确的轨道上。我认为,为所有未检查的异常返回4xx响应代码并不总是正确的。我宁愿将这些异常的已定义子集映射到4xx响应代码,其他任何内容都应该是内部服务器错误,因此应该是500响应代码。

@ResponseStatus(value=HttpStatus.NOT_FOUND)
public class EntityNotFoundException extends RuntimeException {
  // ...
}

如果找不到该实体,则可以从@Service带注释的类中引发此异常。对于其他情况,您也可以定义自定义例外。您还可以坚持使用@ExceptionHandler,但随后必须自己进行映射。

我应该将异常映射到相关的HTTP响应代码是一个好习惯:

  • 错误请求:400
  • 未找到:404
  • 禁止使用:403
  • 内部服务器错误:500

如果请求成功,请不要忘记返回以下(或任何其他)响应代码之一。

  • 好的:200
  • 创建时间:201

以上通常使用响应代码。当然,还有很多,但是大多数API只占用一小部分。使用正确的映射,客户可以更轻松地知道可能出了什么问题(或正确的问题),然后可以执行进一步的操作或显示客户必要的信息。例如:

  • 200:显示成功消息
  • 403:重定向到登录页面
  • 400:如果提交了表单,则显示错误

如果发生任何错误,在体内包含有意义的信息也是一种好习惯。这也回答了一个问题:“如果我无法将异常映射到现有响应代码,该怎么办?”。我问自己同样的问题,答案很简单。尝试将其映射到最接近的响应代码,并将其他内容包括在内。

如果客户端缺少参数,则可以使用以下参数:

{ "error" : "Bad Request - Your request is missing parameter 'id'. Please verify and resubmit." }

或对于上述表单错误(响应代码400):

{ 
    "errors": [
        "username": "AlreadyInUse",
    ]
}

在返回正文中的信息时,只需确保遵循一种格式即可。否则,工作起来很痛苦。