Как использовать несколько ViewResolvers в Spring? - PullRequest
17 голосов
/ 23 июня 2009

Я работаю над веб-приложением, в котором большинство моих страниц используют плитки apache (2.1.2), но некоторые из них должны быть просто jsps.

У меня проблема в том, что и InternalResourceViewResolver, и UrlBasedViewResolver будут пытаться разрешить представление независимо от того, что, так что, независимо от того, какой порядок я использую, оно либо не будет работать на страницах простой JSP, на страницах плитки.

Вот конфиг:

<bean id="tilesViewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
    <property name="viewClass" value="org.springframework.web.servlet.view.tiles2.TilesView"/>
    <property name="order" value="0"/>
</bean>

<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/"/>
    <property name="suffix" value=".jsp"/>
    <property name="order" value="1"/>
</bean>

Чтобы было яснее, что я пытаюсь сделать, мне нужно иметь возможность просматривать состояния, подобные этому:

<view-state id="someState" view="/someDir/foo"><!--render foo.jsp -->
    <transition on="foo" to="bar"/>
</view-state>

<view-state id="someState" view="something.core"><!--render tile defintion named 'something.core' -->
    <transition on="foo" to="bar"/>
</view-state>

Кто-нибудь знает, как настроить вещи так, чтобы я мог заставить их отображать определения плиток и простой jsps?

Ответы [ 5 ]

20 голосов
/ 23 июня 2009

Как вы говорите, вы не можете связать их вместе. Javadoc для обоих штатов ясно, что они оба должны быть в конце цепочки резольвера.

Я полагаю, что если вам действительно нужно использовать их вместе, то вы пишете простую пользовательскую реализацию ViewResolver, которая берет имя представления и решает, какому из двух ваших «реальных» преобразователей представления делегировать. Это предполагает, что вы можете указать, какой распознаватель следует вызывать, основываясь на имени представления.


Итак, вы бы определили собственный ViewResolver следующим образом:

public class MyViewResolver implements ViewResolver {

    private ViewResolver tilesResolver;
    private ViewResolver jspResolver;

    public void setJspResolver(ViewResolver jspResolver) {
        this.jspResolver = jspResolver;
    }

    public void setTilesResolver(ViewResolver tilesResolver) {
        this.tilesResolver = tilesResolver;
    }

    public View resolveViewName(String viewName, Locale locale) throws Exception {
        if (isTilesView(viewName)) {
            return tilesResolver.resolveViewName(viewName, locale);
        } else {
            return jspResolver.resolveViewName(viewName, locale);
        }
    }

    private boolean isTilesView(String viewName) {
    .....
    }
}

Вам необходимо реализовать метод isTilesView, чтобы решить, какому преобразователю делегировать.

В конфигурации XML определите этот новый распознаватель представлений и убедитесь, что он отображается перед другими.

<bean class="MyViewResolver">
    <property name="tilesResolver" ref="tilesViewResolver"/>
    <property name="jspResolver" ref="viewResolver"/>
</bean>
3 голосов
/ 01 августа 2012

Я только что решил ту же проблему, разделив файл конфигурации *-servlet.xml на две части; в моем случае основное приложение использует Tiles, но я хочу, чтобы тесты QUnit были простыми JSP.

app-servlet.xml содержит только распознаватель представлений Tiles, tests-servlet.xml содержит только распознаватель представлений JSP, а сопоставления web.xml отправляют запросы правильному сервлету на основе URL.

<servlet-mapping>
  <servlet-name>app</servlet-name> <!-- will reach app-servlet.xml -->
  <url-pattern>/foo</url-pattern> <!-- will use "foo" Tile -->
  <url-pattern>/bar</url-pattern> <!-- will use "bar" Tile -->
</servlet-mapping>

<servlet-mapping>
  <servlet-name>tests</servlet-name> <!-- will reach tests-servlet.xml -->
  <url-pattern>/foo-test</url-pattern> <!-- will use foo-test.jsp -->
  <url-pattern>/bar-test</url-pattern> <!-- will use bar-test.jsp -->
</servlet-mapping>
1 голос
/ 23 июня 2009

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

Редактировать: упс ... да, другой постер верен, оба эти резольвера будут делать "всегда совпадают", поэтому вы не можете использовать их в цепочке Другой альтернативой может быть попытка расширить TilesView для выполнения простого рендеринга JSP, если он не может найти настроенное представление плиток.

0 голосов
/ 15 мая 2016

Я решил эту проблему, просто добавив определение листов для макета простого jsp, например:

  <definition name="plain-jsp.layout" template="/WEB-INF/layouts/plainJsp.jspx" >
    <put-attribute name="content" value=""/>
  </definition>

Тогда вы можете просто использовать этот макет в качестве шаблона для включения ваших простых файлов JSP.

  <definition name="catalog/details" extends="plain-jsp.layout">
    <put-attribute name="content" value="/WEB-INF/views/catalog/details.jspx"/>
  </definition>

И файл шаблона макета:

<html xmlns:tiles="http://tiles.apache.org/tags-tiles"
      xmlns:jsp="http://java.sun.com/JSP/Page" version="2.0">

  <jsp:output doctype-root-element="HTML"/>
  <jsp:directive.page contentType="text/html;charset=UTF-8" />  
  <jsp:directive.page pageEncoding="UTF-8" />

  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=8" />      
  </head>
  <body>
    <div id="content">
      <tiles:insertAttribute name="content"/>
    </div>
  </body>
</html>
0 голосов
/ 22 сентября 2014

Да, вы можете использовать любое количество средств распознавания в вашем проекте.

Таким образом, вы можете использовать и «тайл-просмотрщик», и «внутренний просмотрщик» в одном проекте. .

Вы должны настроить ContentNegotiatingViewResolver. ,

и укажите стоимость заказа в ваших резольверах.

<property name="order" value="int Value here" />

так же, как я дал разрешение на просмотр плиток 2 и internalviewresolver 3. Сначала он проверяет определения плиток, если представление не найдено в плитках, оно проверяется в InternaiViewResolver

вот некоторые конфигурации, которые работают для меня.

    <bean
        class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
        <property name="order" value="1" />
        <property name="mediaTypes">
            <map>
                <entry key="json" value="application/json" />
                <entry key="html" value="text/html" />
            </map>
        </property>
        <property name="parameterName" value="accept"></property>
        <property name="favorParameter" value="true"></property>
        <property name="defaultContentType" value="text/html"></property>
        <property name="viewResolvers">
            <list>
                <ref bean="tilesViewResolver" />
                <ref bean="internalViewResolver" />
            </list>
        </property>
        <property name="defaultViews">
            <list>
                <bean
                    class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
            </list>
        </property>
        <property name="ignoreAcceptHeader" value="true" />
    </bean>

<!--    Configures the Tiles layout system  -->
    <bean class="org.springframework.web.servlet.view.tiles2.TilesConfigurer"
        id="tilesConfigurer">
        <property name="definitions">
            <list>
                <value>/WEB-INF/layouts/layouts.xml</value>
            <!-- Scan views directory for Tiles configurations  -->
                <value>/WEB-INF/views/**/views.xml</value>
            </list>
        </property>
    </bean>
    <bean id="tilesViewResolver"
        class="org.springframework.web.servlet.view.UrlBasedViewResolver"
        p:viewClass="org.springframework.web.servlet.view.tiles2.TilesView">
        <property name="order" value="3" />
    </bean>


    <bean id="internalViewResolver"
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="order" value="2" />
        <property name="prefix">
            <value>/WEB-INF/views/</value>
        </property>
        <property name="suffix">
            <value>.jsp</value>
        </property>
    </bean>
...