मेरे पास एक ऐसा एप्लिकेशन है जो साइट के एकाधिक संस्करणों को होस्ट करने के लिए grails बहु-किरायेदार-कोर प्लग-इन का उपयोग करता है। मैं प्रत्येक साइट के लिए कस्टम जीएसपी बनाने में सक्षम होना चाहता हूं जो साधारण स्किनिंग मुझे करने की अनुमति देगा। अनिवार्य रूप से, मैं अपने grails-app/views फ़ोल्डर को कुछ इस तरह दिखाना चाहता हूं:

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

और फिर GSP के विशिष्ट सेट का उपयोग करने के लिए एक विशिष्ट टैनेंट को कॉन्फ़िगर करें। मैं एक डीएनएस रिज़ॉल्वर का उपयोग कर रहा हूं जो मेरे डेटाबेस में कायम है, इसलिए मैं संभावित रूप से DomainTenantMap डोमेन क्लास में एक संपत्ति जोड़ सकता हूं जो एक विशेष किरायेदार को templateDir संपत्ति प्रदान करता है और सभी जगह सशर्त तर्क छिड़कता है मेरे जीएसपी और नियंत्रक। (उसके बाद वह 'नहीं कर सकता ... प्राप्त करें ... साफ' महसूस कर रहा है)

मुझे मौजूदा प्लग-इन खोजने में कोई सफलता नहीं मिली है जो यह कार्यक्षमता प्रदान करता है। मैंने जिन अन्य विकल्पों पर विचार किया है, उनमें ग्रेल्स (रेंडर टैग, टेम्प्लेट इंजन, आदि) के काफी मूल टुकड़ों को अनुकूलित करना शामिल है, जो मुझे परेशान करता है।

मैं समझता हूं कि यह काफी व्यापक प्रश्न है; विशिष्ट समाधान और सामान्य सुझावों दोनों की सराहना की जाती है।

संपादित करें:

मुझे एक नई विधि पर प्लग-इन और मेटा-प्रोग्रामिंग बनाकर एक और संभावित दृष्टिकोण मिला:

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 विधि का आह्वान कर सकता हूं। आदर्श रूप से, मैं किसी प्रकार के टैनेंट/टेम्पलेट मैपिंग (दिखाया नहीं गया) के आधार पर args.view और args.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 के तहत सभी टेम्पलेट जीएसपीएस को एक साथ संयोजित करने के बजाय। मुझे लगता है कि मैं अभी इसके साथ रह सकता हूं।

2
proflux 14 सितंबर 2011, 17:37

2 जवाब

सबसे बढ़िया उत्तर

मैंने जो समाधान इस्तेमाल किया:

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)
        }
    }
}
1
proflux 29 फरवरी 2012, 07:17

आप अपना स्वयं का स्प्रिंग व्यू रिसोल्वर लागू करने का प्रयास कर सकते हैं: http://static.springsource.org/spring/docs/current/javadoc-api/org/springframework/web/servlet/ViewResolver.html

0
Kimble 21 नवम्बर 2011, 22:23