【发布时间】:2023-03-08 06:09:01
【问题描述】:
这里是 Grails 2.4.x。
我要求我的所有 Grails 服务的所有方法(由 grails create-service <xyz> 生成)都使用以下逻辑“包装”/拦截:
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类型;和 - 对于 Grails 服务中定义的每个方法,这种行为都存在(或者在需要以某种方式显式调用时可以选择存在)
所以很明显,这个包装代码也需要包含这些类的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 在运行时对其服务进行的任何操作(因为它们都是没有显式扩展父类的类)。
【问题讨论】:
-
你问过a similar question a year ago。只需稍加调整即可使用相同的方法。通过将通用逻辑作为默认实现移动到特征,然后在服务类中实现特征。另一种方法是使用
invokeMethod拦截服务类中的每个方法并用try/catch 包装它们。使用这种方法的缺点是它必须在每个服务类中重复。我相信以前的方法会更干净,可以静态编译。 -
谢谢@dmahapatro (+1) - 是的,我记得这一点,并且在问这个问题时确实想到了这一点,但就像我说的,我担心 Grails 可能会以某种方式干扰。如果您可以通过显示您建议的方法之一的代码示例将您的评论转移到答案中,我会很高兴为您提供绿色检查!
标签: grails groovy closures aop grails-services