Подтвердить что ты не робот

Как использовать несколько ViewResolvers в Spring?

Я работаю над веб-приложением, где у меня есть большинство моих страниц, использующих плитки 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?

4b9b3361

Ответ 1

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

Я предлагаю, чтобы, если вам действительно нужно использовать эти togather, вы пишете простую пользовательскую реализацию 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>

Ответ 2

Я только что решил ту же проблему, разделив файл конфигурации *-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>

Ответ 3

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

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

Ответ 4

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

Таким образом, вы можете использовать как "Плитки", так и "Встроенный просмотрщик" в одном проекте..

вам нужно настроить ContentNegotiationViewResolver.,

и укажите значение порядка в ваших разрешениях.

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

как я дал плитку viewver 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>

Ответ 5

Я решил эту проблему, просто добавив определение плитки для простого 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>