我有一个使用grails Multi-Tenancy 核心插件来托管站点的多个版本的应用程序。我希望能够为每个站点创建自定义的GSP,而不仅仅是简单的外观设置。本质上,我希望能够使grails-app/views文件夹如下所示:

views
|
|__template1
|  |
|  |__layouts
|  |  |
|  |  |__main.gsp
|  |
|  |__controller1
|     |
|     |__index.gsp
|
|__template 2
   |
   |__layouts
   |  |
   |  |__main.gsp
   |
   |__controller1
      |
      |__index.gsp

然后配置特定的租户以使用一组特定的GSP。我使用的是持久化在我的数据库中的DNS解析器,因此我大概可以向DomainTenantMap域类添加一个属性,该属性将templateDir属性分配给特定的租户,并在我的GSP和 Controller 中的各处散布条件逻辑。 (紧接着是“不能...得到...干净”的感觉)

找到现有的可提供此功能的插件并没有取得任何成功。我考虑过的其他选项似乎涉及自定义相当核心的grails(渲染标签,模板引擎等),这让我感到紧张。

我意识到这是一个相当广泛的问题;无论是具体的解决方案还是一般性建议,都应得到赞赏。

编辑:

通过在新方法上创建插件和元编程,我找到了另一种可能的方法:
def configureTemplateRenderer(application, applicationContext) {
    for (controllerClass in application.controllerClasses) {

        controllerClass.metaClass.newRender = { args ->
            println 'something'
            if(args.view) {
                args.view = "/somedir/${args.view}"
            }
            if(args.template) {
                args.template = "/somedir/${args.template}"
            }
            delegate.render(args)
        }
    }
}

这只是一个概念证明,看看我是否可以通过我的新方法调用标准render方法(可以)。理想情况下,我可以完全重写render方法,以基于某种类型的租户/模板映射(未显示)来修改args.viewargs.template属性。但是,我无法成功覆盖render方法,因此,此解决方案实际上仅比在某些路径变量上撒些对render的调用要好。

解决方案!

我最终创建了一个单独的插件,该插件实质上可以归结为使用可检查租户/模板映射的render方法。仍在测试中,但到目前为止看起来很有希望,这是要点:
def overrideRender = { application ->
    for (controllerClass in application.controllerClasses) {
        def original = controllerClass.metaClass.getMetaMethod("render", [Map] as Class[])
        def originalRender = original.getClosure()

        controllerClass.metaClass.originalRender = originalRender

        controllerClass.metaClass.render = { Map atts ->
            def templatePath = // some code to lookup against a TenantTenantMap
            if(templatePath) {
                if(atts.view) {
                    atts.view = "${templatePath}${atts?.view}"
                }
                if(atts.template) {
                    atts.template = "${templatePath}${atts?.template}"
                }
            }
            delegate.originalRender(atts)
        }
    }
}

唯一的缺点是我必须使用比我想要的稍微难看的目录结构:views/controller/$template/action,而不是在views/$template/controller/action下将所有模板gsps组合在一起。我想我现在可以忍受。

最佳答案

我使用的解决方案:

def overrideRender = { application ->
    for (controllerClass in application.controllerClasses) {
        def original = controllerClass.metaClass.getMetaMethod("render", [Map] as Class[])
        def originalRender = original.getClosure()

        controllerClass.metaClass.originalRender = originalRender

        controllerClass.metaClass.render = { Map atts ->
            def templatePath = // some code to lookup against a TenantTenantMap
            if(templatePath) {
                if(atts.view) {
                    atts.view = "${templatePath}${atts?.view}"
                }
                if(atts.template) {
                    atts.template = "${templatePath}${atts?.template}"
                }
            }
            delegate.originalRender(atts)
        }
    }
}

关于grails - 通过Grails Multi-Tenancy 核心插件使用多个GSP模板/皮肤?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/7417251/

10-14 15:47
查看更多