2011-09-14 27 views
2

我有一个应用程序使用grails多租户内核插件来托管多个版本的网站。我希望能够为每个站点创建自定义的GSP,而不仅限于简单的蒙皮允许我执行的操作。从本质上讲,我希望能有我grails-app/views文件夹的样子是这样的:在Grails多租户核心插件中使用多个GSP模板/皮肤?

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

,然后配置特定租户使用一组特定的GSP的。我使用的是一个DNS解析器,它保存在我的数据库中,所以我可能会将一个属性添加到DomainTenantMap域类中,该类将一个templateDir属性分配给特定租户,并在我的GSP和控制器中遍布所有地方。 (其次是'不能...得到...干净'的感觉)

我还没有找到一个现有的插件提供此功能的任何成功。我所考虑的其他选项似乎涉及定制相当核心的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更好。

解决方案!

我最终创建了一个单独的插件,基本上归结为用于检查租户/模板映射的渲染方法。不过测试,但到目前为止,它看起来很有希望,这里是它的要点是:

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,而不是将所有的模板GSPS一起下views/$template/controller/action。我想我现在可以接受这一点。

回答

0

我使用的解决方案:

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) 
     } 
    } 
} 
相关问题