【发布时间】:2015-01-16 12:02:05
【问题描述】:
如果您使用控制器来实现 REST API,您希望处理任何抛出的异常并返回通用或特定格式良好的 REST 响应。
我们不能使用全局错误 URL 映射方法,因为应用程序有许多 API 和接口,响应要求不同,而且我们也不知道会抛出哪种类型的 Grails 的 HTTP 错误代码(例如 don '不知道它是否会是 400、422、500 等)。此外,如果我们使用错误页面映射,我们将无法将相关数据放入 JSON 响应中。
例如这将生成一个 GrailsRuntimeException:
class SomeController {
def payload = request.JSON
def someMethod() {
BigDecimal x = new BigDecimal(payload.notExists)
}
问题是,似乎无法捕捉到任何抛出的错误。
例如这种方法都不是:
def handleRuntimeException(RuntimeException e) {
render("some JSON error message")
}
也不是这种方法:
try {
:
}
catch (GrailsRuntimeException e) {
render("some JSON error message")
}
有效 - 它永远不会捕获错误。
尝试过 GroovyRuntimeException、Exception、MissingMethodException、Throwable 等
我们能想到的唯一解决方案是不在控制器中做任何工作,在服务中做所有事情,显然我们可以捕获错误。
这种方法:
static mappings = {
"500"(controller: "error")
}
不想要我们需要有几个原因:
- 我们在不同的控制器中有几个不同的 API,它们需要不同的响应格式。
- 我们还有 UI 控制器,它们需要显示堆栈跟踪等的默认错误系统。
- 我们希望在发生异常的控制器中处理错误,以便我们可以清理,或者至少可以记录或返回只有控制器知道的统计信息。
已决定唯一的方法是将所有代码移动到服务中,并且在控制器中除了传递请求并呈现结果字符串之外什么都不做。即所有参数处理,尤其是数字转换,都在服务中完成。
【问题讨论】:
-
你提到的两种技术——try/catch 和定义异常处理方法——在我的 2.3.5 应用程序和我的 2.4.4 应用程序中都可以正常工作。您绝对应该能够捕获和处理控制器中抛出的异常。你确定你没有遇到更早的错误吗?
-
谢谢埃德。即使我们将 try { 作为控制器方法的第一行,并将 } catch (xxx) {...} 作为最后一行,它仍然不会捕获任何错误。它对你有用是一个谜。根据我发现的一些 grails 文档,它说您无法在控制器中捕获错误,您必须使用 url 映射(在我们的案例中这不是解决方案)