如果你已经使用 Spring 来构建你的应用,并且你需要提供 REST API, 那么 Spring MVC 会是你编写 REST 端一个很好的选择。
  然而,由于 Spring MVC 常被用来构建用户接口,因此通过 RESTful 方式来清楚表示异常或问题并不是(那么)显而易见。因为在 REST APIs 中并没有直接的 UI 概念,那么你该如何使用 Spring MVC 简单直观的表示异常或问题呢?
  本文是系列文章两部分中的第一部分。在本文中,我们将涉及 RESTful 异常报告的佳实践。第二部分将会通过一个完整的 web 示例展示如何通过 Spring MVC 来实现它们。
  RESTful 异常设计
  一旦发生异常, RESETful 的实践期望我们在响应中设置一个 HTTP 状态码 概括的将请求失败原因进行分类。尽可能的重用 HTTP 规范中的状态码被认为是佳实践,因为许多现存的 HTTP 客户端知道这些异常,而且重用可确保行为的一致性,这对开发来说常常也是有益的。
  然而,仅有 24 个常用的 HTTP 状态码被用来表示异常;包括 18 个表示客户端异常的 4xx 编码和 6 个表示服务器端异常的 5xx 编码(在诸如 WebDav 的规范中还定义了其他编码,但那些编码并不是普遍存在的)。这里便有一个问题,这 24 个编码其实都是通用编码 —— 它们可能不会为某个特定问题描述所有信息。
  为尽可能帮助你的 REST API 客户,理想情况下,你想给他们尽可能的信息以便他们做出异常诊断并且好能将问题修复。游戏规则很简单:你的 REST API 越便于使用,他们越可能采用你的服务。
  REST 异常表示
  由于状态码可能不够清晰,那么当用户遇到异常时,我们还能为他们提供些别的有用信息呢?很明显,我们需要人类易读的异常信息,这可以帮助开发者。但我们还可以添加更多的信息来提供一个真正直观有用的异常表示。
  Apigee 的伙计们整理了关于 RESTful 异常表示的一篇不错的博客(以及许多很棒的视频)值得一看。我们也想做类似的事情。
  我们认为下面例子中REST错误响应表示是一个“佳实践”(本例为JSON, 当然也可以是XML,这取决于你的API提供的服务):
  {
  "status": 404,
  "code": 40483,
  "message": "Oops! It looks like that file does not exist.",
  "developerMessage": "File resource for path /uploads/foobar.txt does not exist.  Please wait 10 minutes until the upload batch completes before checking again.",
  "moreInfo": "http://www.mycompany.com/errors/40483"
  }
  接下来我们将详述这些属性。
  status
  status 属性仅仅与响应头中的 HTTP 状态码(integer)相同而已。这是个方便的机制:通过在消息体内包含状态码,处理该异常的任何 REST 客户端有且仅有一个地方去寻找(原因)充分理解该异常:异常表示自身。没有必要再查找头字段或其他地方来理解消息。
  code
  code 属性是针对你提供的特定 REST API 的异常编码。它通常传达有关问题域的非常具体的信息。
  因为仅有 24 个熟知的通用 HTTP 异常码存在局限性,有了这个属性将会很方便。通过使用自定义的编码,你可以传达更多具体更详尽的失败原因。同样, API 客户端能接受到的信息越多越好。
  上例中,代码属性值为 40483。同时通用状态码 404 意味着请求资源不存在,可能应用程序的特定编码 40483 意味着不仅资源不存在,而且还是由于该资源还未被上传到服务器的原因。
  的确,这个特定的“文件上传”示例有点不真实,但这里的关键点是如果你利用自定义的编码,你的 API 能传达更为丰富的异常信息。
  提示:如果你的应用某个特定异常没有指定的异常编码,那么默认该异常编码与对应的状态值保持一致会是个好主意。这样确保了客户端始终看到编码值且不需要去执行“这个属性真的存在么?”这样的逻辑。这对 API 使用者来说更清晰/容易,并且有助于被采用。
  message
  message 属性是一个可读性很好的异常消息,可能会被直接展示给应用程序端的用户(不是开发者)。异常消息应该友好并易于理解且传达简洁的异常发生原因。它不应该包含技术信息。技术信息应该包含在 developerMessage 属性中而不是这里。
  为什么这个有用?
  如果你有一个 REST API 使用者 (例如你的客户),并且该客户希望直接转发该消息给终端用户,他们可以这么做。这样做允许 API 使用者快速编写用户接口并帮助他们的终端用户,而不需要进行太多的工作。你为节省他们的时间并让他们乐于使用你的 API 而做的事情越多越好。
  developerMessage
  developerMessage 属性传达了所有对使用你 REST API 的开发者而言可能有用的技术信息。你可以在这里包含异常信息,跟踪堆栈,或者其他你认为对开发者有用的东西。
  moreInfo
  moreInfo 属性指定一个 URL, 任何看到该 URL 的人都可在浏览器中点击(或复制粘贴)。URL 的目标网页应该全面的描述出现的异常情况,以及潜在的解决方案,从而帮助他们解决异常情况。
  这可能是为重要的属性,因为目标网页可以格式自由的展示你希望展示的任何信息。你可以链接到你们的支持部门,“立刻获取帮助”聊天窗口,或其他你认为可能有用的任何东西。让开发者们看到你的关爱,那么他们会继续使用你的 API。
  比如 Twilio 有一个很棒的异常和警告字典充分说明了这个观点。了解它,爱上它,重复它。再次提醒,提供的信息越多越理想。提供你能想到的任何必要信息来帮助你的 API 使用者/客户并让他们开心。
  第二部分
  在第二部分,我们将为你展示如何确保这些异常信息很容易从一个基于 Spring MVC 的 REST API 返回。