Apache Tiles 2 + Spring MVC 3 с использованием нескольких наборов определений представлений

Это сложный вопрос, поэтому, пожалуйста, выдержите меня в длинном объяснении.

Текущий сценарий

Мы используем Spring MVC 3.0.5 с плитками Apache 2.2. В настоящее время наша конфигурация плиток на основе Spring выглядит следующим образом:

<bean id="tilesConfigurer"
    class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
    <property name="definitions">
        <list>
            <value>/WEB-INF/**/views.xml</value>
        </list>
    </property>

    <!-- resolving preparer names as Spring bean definition names -->
    <property name="preparerFactoryClass" 
        value="org.springframework.web.servlet.view.tiles2.SpringBeanPreparerFactory" />
</bean>

<bean id="tilesViewResolver"
    class="org.springframework.web.servlet.view.UrlBasedViewResolver"
    p:order="1" p:viewClass="org.springframework.web.servlet.view.tiles2.TilesView" />

Определения представлений (Tiles) считываются из всех файлов views.xml, и когда контроллер Spring выдает, скажем, «домашнюю страницу» в качестве логического имени представления для отображения, отображается соответствующее определение плиток с именем «домашняя страница».

Цель

Теперь мы намерены разрешить разные наборы определений представлений из разных каталогов в нашем веб-приложении. Причина в том, что разные группы пользователей будут иметь индивидуальные шаблоны в соответствии с их группой.

Скажем, все мои текущие определения представлений находятся в

 /WEB-INF/default-views/**/views.xml

И я хочу добавить вторую папку

 /WEB-INF/administrator-views/**/views.xml

Эта вторая папка должна содержать определения представлений с теми же именами, что и в папке default-views. Но в зависимости от шаблона URL будет отображаться либо тот, либо другой. Вот два образца:

http://example.com/default/foobar 
==> Controller yields logical view name "foobar"
==> definition "foobar" from "default-views" folder shall be displayed

http://example.com/admin/foobar 
==> Controller yields logical view name "foobar"
==> definition "foobar" from "administrator-views" folder shall be displayed

Кроме того, мы хотели бы разрешить резервный механизм. Если специализированное имя представления (для «admin» в приведенном выше примере) не существует в соответствующей папке представлений, мы хотим отобразить версию по умолчанию из другой папки.

Уже

В настоящее время я думаю о нескольких отправных точках. Может быть, я мог бы настроить TilesConfigurer. который хранит определения представлений плиток в одном свойстве без различия папок, из которых пришли определения представлений.

Другой вариант — попытаться выполнить это с помощью преобразователи представлений в цепочке, причем специализированные из них находятся выше в цепочке, а стандартные — в конце.

В третьем варианте используются разные имена представлений и перехватить ответ имени представления от контроллера, используя HandlerInterceptor, чтобы сопоставить его со специализированным представлением (может не работать, если оно не существует).

Вопросы

  • What are good options to implement this view-resolution mechanism?
    • Allowing view-defintions to be overridden by others / more specialized ones
    • Настройка отображения в зависимости от шаблона URL-адреса запроса

На данный момент мой вариант № 2 звучит наиболее убедительно, так как я хотел бы не возиться с классами Springs, когда это не очень нужно. Но мне не хватает связи между связанными преобразователями представлений и списком определений представлений в TilesConfigurer.

Спасибо за ваше терпение и чтение до сих пор.


person Axel Knauf    schedule 08.04.2011    source источник


Ответы (1)


Для тех, кто может столкнуться с подобной проблемой, вот как мы это реализовали:

  • использовать пользовательскую реализацию HandlerInterceptorAdapter#postHandle(..) для преобразования компонентов пути URL в префиксы имени логического представления.
  • использовать имена определений представлений плиток с этими префиксами URL во всех views.xml файлах
  • используйте пользовательскую реализацию UrlBasedViewResolver#loadView(..), чтобы сначала попробовать имя представления, заданное Controller и HandlerInterceptor, и если оно не существует (super.loadView(..) дает значение null), вместо этого попробуйте префикс по умолчанию.

Надеюсь, это достаточно ясно.

person Axel Knauf    schedule 15.04.2011