Grails 控制器中的异常处理
Posted
技术标签:
【中文标题】Grails 控制器中的异常处理【英文标题】:Exception handling in Grails controllers 【发布时间】:2013-06-19 13:20:40 【问题描述】:我知道如何在 Grails 中使用 UrlMappings 和 ErrorController 进行通用异常处理以进行通用异常处理,因此如果异常从控制器中转义,用户将被发送到通用错误页面并记录该异常。我也知道如何使用 try/catch 块来处理特定的异常并尝试从中恢复。
但是在大多数控制器中,如果发生异常,我只想给用户一个稍微更具体的错误消息。所以在创建动作中,我想告诉用户该项目没有被创建。或者在导入动作中,我想告诉用户导入失败。现在,控制器看起来像:
class ThingController
def create =
try
// The real controller code, which quickly hands it off to a service
catch (Exception e)
handleException(e, "There was an error while attempting to create the Thing")
def delete =
try
// The real controller code, which quickly hands it off to a service
catch (Exception e)
handleException(e, "There was an error while attempting to delete the Thing")
private void handleException(Exception e, String message)
flash.message = message
String eMessage = ExceptionUtils.getRootCauseMessage(e)
log.error message(code: "sic.log.error.ExceptionOccurred", args: ["$eMessage", "$e"])
redirect(action:index)
请注意,catch 块不会根据异常的类型或内容做任何不同的事情;他们只是根据控制器提供更具描述性的错误消息。 “真正的”控制器代码通常是 6-10 行,因此为了更改错误消息而额外增加 4 行代码似乎过多。此外,CodeNarc“CatchException”规则抱怨,这强化了我的观点,即必须有更好的方法来做到这一点。我假设其他 Grails 应用程序也有类似的要求。什么是惯用方法来根据异常冒出的操作指定不同的错误消息?
我对来自解决此问题的特定方法的经验的答案感兴趣,或者更好的是,链接到我可以在实践中看到解决方案的代码库。
【问题讨论】:
对于否决票,请说明需要对问题进行哪些更改,或者为什么它不适合 Stack Overflow。谢谢 【参考方案1】:Grails 具有处理控制器异常的一般机制。 您可以在专用的错误控制器中执行此操作。常规控制器不需要使用 try/catch。
控制器:
class ThingController
def create()
def id = params.id as Long
if (id == null)
throw new MissingPropertyException("thingId")
// The real controller code, which mostly parses things out and hands it
// off to a service.
// Service methods can throws exception
在 UrlMappings 中添加处理 500 错误:
class UrlMappings
static mappings =
// Exception handling in ErrorController
"500"(controller: "error")
错误控制器:
class ErrorController
def index()
def exception = request.exception.cause
def message = ExceptionMapper.mapException(exception)
def status = message.status
response.status = status
render(view: "/error", model: [status: status, exception: exception])
您可以使用这种方法处理 REST 和非 REST 异常。 还有Declarative Exception Handling插件,但我没有
更新
您可以在错误控制器中获取特定的错误消息。 当在控制器中抛出新的 RuntimeException(“尝试删除事物时出现错误”),然后在错误控制器中 request.exception.cause.message 将显示消息:“尝试删除事物时出现错误”。
【讨论】:
谢谢,但这看起来就像我们已经拥有的那样:一种用一个通用错误消息处理异常的方法。声明式异常处理很有趣,因为它允许您在一个地方处理某些类型的异常,但它仍然不能帮助我根据调用的控制器/操作提供更具体的错误消息。 我认为你可以在错误控制器中得到具体的错误信息。请参阅我的更新答案。【参考方案2】:另见How to know from where was thrown error 500 (Grails)
我根据控制器上的注释创建自定义错误页面,提供跨多个控制器的通用异常处理过程。
class ErrorsController
def index()
def initialController = request.exception?.className
if (initialController)
def controller = grailsApplication.getArtefact("Controller", initialController).getReferenceInstance()
// do some rendering based on the annotations
render "Controller: $initialController, annotations $controller.getClass().getDeclaredAnnotations()"
return
render 'no initial controller'
【讨论】:
以上是关于Grails 控制器中的异常处理的主要内容,如果未能解决你的问题,请参考以下文章