Jak korzystać z wielu Viewresolverów wiosną?

Pracuję nad aplikacją internetową, w której większość moich stron korzysta z płytek apache (2.1.2), ale kilka z nich musi być po prostu zwykłym JSP.

Mam problem w tym, że zarówno InternalResourceViewResolver, jak i UrlBasedViewResolver będą próbować rozwiązać Widok bez względu na wszystko, tak że bez względu na kolejność, której używam, albo zawiedzie na zwykłych stronach JSP, albo na stronach kafelków.

Oto konfiguracja:

<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>

Aby było bardziej jasne, co próbuję zrobić, muszę mieć stan widoku Tak:

<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>

Czy ktoś wie jak skonfigurować rzeczy tak, że mogę go zmusić do renderowania definicji kafelków i zwykłych JSP?

Author: skaffman, 2009-06-23

5 answers

Jak mówisz, nie możesz ich połączyć. Javadoc dla obu stanów wyraźnie wskazuje, że oba muszą znajdować się na końcu łańcucha rozdzielacza.

Sugeruję, że jeśli naprawdę potrzebujesz ich użyć, napisz prostą, niestandardową implementację ViewResolver, która przyjmuje nazwę widoku i decyduje, do którego z twoich dwóch" prawdziwych " rozdzielaczy widoku delegować. Zakłada to, że na podstawie nazwy widoku można określić, który resolver ma zostać wywołany.


Więc zdefiniujesz zwyczaj ViewResolver like this:

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) {
    .....
    }
}

Musisz zaimplementować metodę isTilesView, aby zdecydować, do którego resolvera delegować.

W konfiguracji XML zdefiniuj ten nowy mechanizm rozpoznawania widoku i upewnij się, że pojawia się przed innymi.

<bean class="MyViewResolver">
    <property name="tilesResolver" ref="tilesViewResolver"/>
    <property name="jspResolver" ref="viewResolver"/>
</bean>
 20
Author: skaffman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-22 20:45:55

Właśnie rozwiązałem ten sam problem dzieląc plik konfiguracyjny *-servlet.xml na dwa; w moim przypadku główna aplikacja używa kafelków, ale chcę, aby testy QUnit były prostymi Jspami.

app-servlet.xml zawiera tylko rozdzielacz widoku kafelków, tests-servlet.xml zawiera tylko rozdzielacz widoku JSP, a mapowania web.xml wysyłają żądania do właściwego servletu na podstawie adresu 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
Author: kryger,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-01 09:50:49

Wygląda na to, że jesteś na dobrej drodze, ale należy pamiętać, że niektóre resolvery widoku zachowują się tak, jakby zawsze rozwiązywały widok. Musisz upewnić się, że takie resolvery są ostatnie w zamówieniu. Uważam, że Widok płytek jest jednym z takich.

Edit: UPS... tak, drugi plakat jest poprawny, oba te resolvery będą "zawsze pasowały", więc nie można ich używać w łańcuchu. Inną alternatywą byłoby rozszerzenie TilesView, aby zrobić prosty render JSP, jeśli nie można znaleźć skonfigurowanego widoku kafelków.

 1
Author: Jherico,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-22 20:29:52

Tak możesz użyć dowolnej liczby rozdzielaczy widoku w swoim projekcie.

Więc możesz używać zarówno 'tiles View resolver', jak i 'Internal view resolver' w tym samym projekcie. .

Musisz skonfigurować ContentNegotiatingViewResolver . .

I podaj wartość zamówienia w widoku resolvers.

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

Tak jak dałem tiles view resolver 2 i internalviewresolver 3. . Najpierw sprawdzi w definicjach kafelków jeśli widok nie zostanie znaleziony w kafelkach, zostanie on sprawdzony w InternaiViewResolver

Oto kilka konfiguracji, które działają dla mnie.

    <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>
 0
Author: Nirbhay Mishra,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-22 10:28:39

Rozwiązałem ten problem, po prostu dodając definicję kafelków dla zwykłego układu jsp, tak:

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

Następnie możesz użyć tego układu jako szablonu do włączenia prostych plików jsp.

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

I plik szablonu układu:

<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
Author: Andrey Sarul,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-14 21:24:18