3

我从最新的 Java 开发中了解到,抛出 aRuntimeException并以面向方面的方式处理它是服务层错误处理的当前趋势。这意味着,如果出现任何问题,您只需抛出一个RuntimeException甚至更好的方法,让 Bean Validation 发挥作用。

优点是:你不会用try-catchif(entity.getName() == nil)检查阻塞你的代码。一切都在后台检查,这使您的代码更具可读性。

所以我想知道,这将如何在 Grails 中完成?当然,如果我使用.save(failOnError:true),我会得到一个不错的ValidationException. 但这会导致一个非常令人不快的默认错误页面,它根本不会提高 Web 应用程序的可用性。

我还需要把它try-catch放在控制器级别的块中吗?假设EntityService有一个方法,如下所示:

def toggleSomething(String entityId) = {
    if(!someOtherPrerequisite) {
        throw new EntityException("SomeOtherPrerequisite was not satisfied") // extends RuntimeException
    }

    Entity entity = Entity.get(entityId)
    entity.someProperty = somePropertyValue
    entity.save(failOnError:true) // throws a ValidationException
}

然后控制器会这样称呼它:

def toggle = {
    try {
        entityService.toggleSomething(params.id)
    }
    catch(e) {
        flashHelper.error 'I'm sorry, something went wrong.'
    }
}

但是,当 Grails 在很多方面都是如此新的学校时,这似乎是相当老派的。有没有办法在RuntimeExceptions不阻塞代码的情况下处理得更好一点try-catch

4

1 回答 1

2

我遵循的模式是:

  1. 如果错误可以包含在 Grails 域中,则不要直接处理异常处理。如果您的服务方法主要处理您的 grails 域,那么当出现错误时,它们会在 domain.errors 集合中结束。在控制器中,只需检查这些错误(hasErrors())。由于无论如何都会在幕后引发 RuntimeException,因此您的事务被回滚,没有伤害,也没有犯规。

  2. 如果您正在处理 3rd 方库(可能是外部 Web 服务等),那么不要害怕异常。仅仅因为 Grails (Groovy) 不需要您处理它们,它们仍然很好拥有/使用。

  3. 有时以上都不适用,也许您的服务方法应该只返回一些关于某些逻辑结果的真或假标志。举个例子,例如:

服务

    def toggleSomething(String entityId) = {
        if(!someOtherPrerequisite) {
            return false
        }
    }

        Entity entity = Entity.get(entityId)
        entity.someProperty = somePropertyValue
        entity.save() // throws a ValidationException
        return entity.hasErrors()
    }

控制器

    def toggle = {
        if (!entityService.toggleSomething(params.id)) {
            flashHelper.error 'I'm sorry, something went wrong.'
        }
    }

不幸的是,可能没有可靠的正确或错误方法来解决这个问题。所以期待与我不同的答案。

于 2012-03-18T22:07:53.690 回答