考虑到 Sérgio 的回答,我进一步调试了一下,并提出了一个可能适用于某些项目的解决方案,而对于某些项目则不会。不幸的是,我们工作中的 Grails 项目属于后一组项目……但首先要做的是。这就是我所做的。
我设置了一个完全空的 Grails 项目和 Grails 插件项目。该插件包含在内联中,以反映我们在 Grails 项目中的工作情况。
我在插件的 conf 目录中创建了一个文件 Constraints.groovy ,如问题中所述。
grails.gorm.default.constraints = {
myShared(nullable: false, blank: false)
}
为了让这些共享约束可用于插件内部的测试,我将此文件添加到 Config.groovy 中的配置位置。
grails.config.locations = [Constraints]
现在是使这些约束可用于主项目的部分。这是通过在插件描述符中添加一些行来实现的。
def loadBefore = ['domainClass']
正如 Sérgio 建议的那样,我更改了加载顺序。虽然我不确定这是否真的有必要。关于我为什么不确定的更多细节如下。
def doWithSpring = {
ConstraintEvalUtils.clearDefaultConstraints()
mergeConfig(application)
}
protected mergeConfig(application) {
application.config.merge(loadConfig(application))
}
protected loadConfig(application) {
new ConfigSlurper(Environment.current.name).parse(application.classLoader.loadClass("Constraints"))
}
这两个方法负责将 Constraints.groovy 的内容加载并合并到应用程序配置中。但实际上,诀窍是ConstraintEvalUtils.clearDefaultConstraints()
在合并之前调用。
/**
* Looks up the default configured constraints from the given configuration
*/
public static Map<String, Object> getDefaultConstraints(ConfigObject config) {
def cid = System.identityHashCode(config)
if (defaultConstraintsMap == null || configId != cid) {
configId = cid
def constraints = config?.grails?.gorm?.default?.constraints
if (constraints instanceof Closure) {
defaultConstraintsMap = new ClosureToMapPopulator().populate((Closure<?>) constraints);
}
else {
defaultConstraintsMap = Collections.emptyMap()
}
}
return defaultConstraintsMap
}
此方法(也在 中ConstraintEvalUtils
)被调用以加载共享约束。如您所见,结果被缓存在defaultConstraintsMap
. 因此,如果在第一次调用此方法时共享约束为空,它总是返回一个空映射。所以我调试了这个方法来找出这个方法实际被调用的时间。它总是返回一个空地图。即使我在插件描述符中设置loadBefore
为core
,该方法已经在插件描述符之前被调用(不止一次)。正如我已经提到ConstraintEvalUtils.clearDefaultConstraints()
的那样,它可以清除缓存的约束,并且可以从我将约束合并到的配置中重新加载默认约束。
差不多就是这样。实际上需要添加的行并不多。它适用于我的测试项目,可能也适用于其他项目,但不适用于我们正在工作的 Grails 项目。如果我也能在那里工作,我会更新我的答案。