Использовать несколько шаблонов / скинов GSP с плагином для нескольких арендаторов Grails?
У меня есть приложение, которое использует плагин для нескольких арендаторов Grails для размещения нескольких версий сайта. Я хочу иметь возможность создавать собственные 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 и контроллерах. (с последующим ощущением "не могу... получить... чистоту")
Мне не удалось найти существующий плагин, который обеспечивает эту функциональность. Кажется, что другие варианты, которые я рассмотрел, включают в себя настройку довольно основных частей grails (тег Render, движок шаблонов и т. Д.), Что заставляет меня нервничать.
Я понимаю, что это довольно широкий вопрос; и конкретные решения и общие предложения приветствуются.
РЕДАКТИРОВАТЬ:
Я нашел другой возможный подход, создав плагин и метапрограммирование на новый метод:
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.view
а также args.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
вместо того, чтобы объединить все шаблоны GPS вместе под views/$template/controller/action
, Я думаю, что могу жить с этим сейчас.
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)
}
}
}
Вы можете попробовать реализовать свой собственный Spring ViewResolver: http://static.springsource.org/spring/docs/current/javadoc-api/org/springframework/web/servlet/ViewResolver.html