Apache Tiles 2 + Spring MVC 3 с использованием нескольких наборов определений видов - PullRequest
0 голосов
/ 08 апреля 2011

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

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

Мы используем Spring MVC 3.0.5 с Apache Tiles 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 выдает, скажем, "homepage" в качестве имени логического представления для отображения, отображается соответствующее определение Tiles с именем "homepage".

Aim

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

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

 /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. который хранит определения представлений Tiles в одном свойстве без различия папок, из которых получены определения представлений.

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

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

Вопросы

  • Какие есть хорошие варианты для реализации этого механизма разрешения вида?
    • Разрешение определения вида быть переопределенным другими / более специализированными
    • Настройка отображения зависит от шаблона URL запроса

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

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

1 Ответ

2 голосов
/ 15 апреля 2011

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

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

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

...