Grails 2.4.x。
我要求由grails create-service <xyz>
生成的所有Grails服务的所有方法都包含&#34; /截获以下逻辑:
try {
executeTheMethod()
} catch(MyAppException maExc) {
log.error(ExceptionUtils.getStackTrace(maExc))
myAppExceptionHandler.handleOrRethrow(maExc)
}
其中:
log.error(...)
是您使用@Slf4j
注释注释班级时获得的SLF4J提供的记录器;和ExceptionUtils
是来自org.apache.commons:commons-lang3:3.4
的人;和myAppExceptionHandler
的类型为com.example.myapp.MyAppExceptionHandler
;和显然,这个包装器代码也需要为这些类包含import
语句。
例如,如果我有WidgetService
,如下所示:
class WidgetService {
WidgetDataService widgetDataService = new WidgetDataService()
Widget getWidgetById(Long widgetId) {
List<Widget> widgets = widgetDataService.getAllWidgets()
widgets.each {
if(it.id.equals(widgetId)) {
return it
}
}
return null
}
}
然后在发生Groovy / Grails / closure魔术之后,我需要代码表现得好像我写的那样:
import groovy.util.logging.Slf4j
import org.apache.commons.lang3.exception.ExceptionUtils
import com.example.myapp.MyAppExceptionHandler
@Slf4j
class WidgetService {
WidgetDataService widgetDataService = new WidgetDataService()
MyAppExceptionHandler myAppExceptionHandler = new MyAppExceptionHandler()
Widget getWidgetById(Long widgetId) {
try {
List<Widget> widgets = widgetDataService.getAllWidgets()
widgets.each {
if(it.id.equals(widgetId)) {
return it
}
}
return null
} catch(MyAppException maExc) {
log.error(ExceptionUtils.getStackTrace(maExc))
myAppExceptionHandler.handleOrRethrow(maExc)
}
}
}
关于如何实现这一目标的任何想法?我担心纯Groovy闭包可能会在运行时以某种方式干扰Grails对其服务的任何操作(因为它们都是不显式扩展父类的类)。
答案 0 :(得分:2)
以下是我试图在评论中指出的内容:
package com.example
import groovy.util.logging.Log4j
@Log4j
trait SomeTrait {
def withErrorHandler(Closure clos) {
try {
clos()
} catch(Exception e) {
log.error e.message
throw new ApplicationSpecificException(
"Application Specific Message: ${e.message}"
)
}
}
}
服务类:
package com.example
class SampleService implements SomeTrait {
def throwingException() {
withErrorHandler {
throw new Exception("I am an exception")
}
}
def notThrowingException() {
withErrorHandler {
println "foo bar"
}
}
}
测试:
package com.example
import grails.test.mixin.TestFor
import spock.lang.Specification
@TestFor(SampleService)
class SampleServiceSpec extends Specification {
void "test something"() {
when:
service.throwingException()
then:
ApplicationSpecificException e = thrown(ApplicationSpecificException)
e.message == "Application Specific Message: I am an exception"
}
void "test something again"() {
when:
service.notThrowingException()
then:
notThrown(Exception)
}
}
这是sample app。
Grails 3.0.9但是没关系。这适用于Grails 2.4。*
答案 1 :(得分:1)
您可以使用MetaInjection或Spring AOP拦截对Service类方法的调用。因此,您不必在每个Service类中编写闭包。您可以查看通过示例解释这两种方法的blog。