Exception Grails控制器中的异常处理

Exception Grails控制器中的异常处理,exception,grails,exception-handling,controller,Exception,Grails,Exception Handling,Controller,我知道如何在Grails中使用UrlMappings和ErrorController进行一般异常处理,这样,如果异常从控制器中逃逸,用户将被发送到一般错误页面并记录异常。我还知道如何使用try/catch块来处理特定异常并尝试从中恢复 但是在大多数控制器中,如果发生异常,我只想给用户一个稍微更具体的错误消息。因此,在创建操作中,我想告诉用户该项没有创建。或者在导入操作中,我想告诉用户导入失败。现在,控制器看起来像: class ThingController { def create = {

我知道如何在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应用程序也有类似的需求。根据异常冒泡出的操作,指定不同错误消息的惯用方法是什么


我感兴趣的是从解决这个问题的特定方法的经验中得到的答案,或者更好的是,链接到代码库,在那里我可以在实践中看到解决方案。

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

    }
}
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])
    }
}
添加URL映射中的500错误处理:

class UrlMappings {

    static mappings = {
        // Exception handling in ErrorController
        "500"(controller: "error")
    }
}
错误控制器:

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

    }
}
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异常。 还有插件,但我没有

更新

您可以在错误控制器中获取特定的错误消息。 当in-controller抛出新的RuntimeException(“尝试删除对象时出错”)时,in-error controller request.exception.cause.message将显示消息:“尝试删除对象时出错”。

另请参见

我基于控制器上的注释创建自定义错误页,提供跨多个控制器的通用异常处理过程

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'
}

对于否决票,请解释该问题需要更改的内容,或者为什么不适合堆栈溢出。谢谢,但这看起来像是我们已经拥有的:一种用一条通用错误消息处理异常的方法。声明性异常处理很有趣,因为它允许您在一个位置处理某些类型的异常,但它仍然不能帮助我根据调用的控制器/操作提供更具体的错误消息。我认为您可以在error controller中获得具体的错误消息。请参阅我的最新答案。