在服务中抛出异常时加载grails消息的位置

时间:2014-01-31 22:26:29

标签: grails

如果grails服务抛出异常,UI消息元素的分隔应该在哪里?消息是否应该由服务加载并通过异常传递给控制器​​,还是控制器应该根据抛出的异常类型加载消息?这假设消息将包含一些需要填写的参数值。

这是一个例外:

class CustomException extends RuntimeException {
    String message
}

在捕获异常后从控制器加载消息源:

class MyService {
    void doSomething() {
        ...
        if (somethingBad) {
            String value = 'Mary Smith'
            throw new CustomException(value)
        }
        ...
    }
 }
 class MyController {
    def myService

    void processRequest() {
        try {
            myService.doSomething()
        }
        catch (CustomException e) {
            flash.error = g.message(code:'user.input.error', args:'[${e.value}]')
            render view:'some_gsp'
        }
        ...
    }
 }

从服务中的消息源加载错误,控制器从异常中提取消息字符串:

class MyService {
    def messageSource
    void doSomething() {
        ...
        if (somethingBad) {
            String value = 'Mary Smith'
            throw new CustomException(messageSource.getMessage('thread.inactive.user', [value]))
        }
        ...
    }
}
class MyController {
    def myService

    void processRequest() {
        try {
            myService.doSomething()
        }
        catch (CustomException e) {
            flash.error = e.message
            render view:'some_gsp'
        }
        ...
    }
}

1 个答案:

答案 0 :(得分:1)

坦率地说,这两个地方 你不需要翻译。 :)

分离关注
控制器应该只担心HTTP方法及其授权 服务应该处理事务和底层业务逻辑。

声明性错误处理
对于2.0.*及以上,Grails为您提供处理错误的最佳位置。你猜怎么着? Declarative Error Handling

所有与异常相关的代码都移动到一个单独的控制器(内部),在那里它们得到妥善处理,使您的业务控制器和服务保持清洁,并从锅炉板代码中抽象出来。

对于Grails 2.3.*,控制器本身中的added feature was to handle exception,但大部分锅炉板(尝试捕获东西)都是从控制器实现中抽象出来的。

<强>结论
如果您使用的是v2.0.*及以上,那么您的控制器将类似于:

class MyController {
    def myService

    def processRequest() {
        myService.doSomething()
        ...
    }
 }

//URL Mapping
static mappings = {
   "500"(controller: "errors", action: "customException",
         exception: CustomException)
}

//Error Controller
class ErrorsController {
    def customException() {
        def exception = request.exception
        // perform desired processing to handle the exception
    }
}

如果需要,您可以将错误处理的逻辑移动到单独的插件,以便处理各种错误/异常和不愉快的路径。将这种担忧分开是很优雅的。

如果您使用v2.3.*,那么您的控制器将类似于:

class MyController {
    def myService

    def processRequest() {
        myService.doSomething()
        ...
    }

    def handleCustomException(CustomException e) {
        //Move this translation to src/groovy/utility if feasible
        flash.error = g.message(code:'user.input.error', args:'[${e.value}]')
        render view:'some_gsp'
    }
 }

在这种情况下,服务也不需要处理,您只需要解决该异常。

如果你环顾四周并有兴趣使用这种模式,我想你会从各种来源获得更多的输入。