2009-06-22 6 views
17

Je travaille sur une application web où j'ai la plupart de mes pages en utilisant des tuiles Apache (2.1.2), mais quelques-unes d'entre elles doivent simplement être des jsps simples.Comment utiliser plusieurs ViewResolvers au printemps?

J'ai un problème en ce qu'un InternalResourceViewResolver et un UrlBasedViewResolver vont essayer de résoudre la vue quoi qu'il arrive, de sorte que quel que soit l'ordre que j'utilise, il échouera sur les pages JSP ou sur les carreaux. pages

Voici la config:

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

Pour le rendre plus clair ce que je suis en train de faire, je dois être en mesure d'avoir des états d'affichage comme ceci:

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

Est-ce que quelqu'un sait comment configurer les choses afin que je puisse l'obtenir pour rendre les définitions de carreaux et les jsps simples?

Répondre

20

Comme vous le dites, vous ne pouvez pas les enchaîner ensemble. Le javadoc pour les deux états clairement qu'ils doivent tous les deux être à la fin de la chaîne résolveur.

Je suggère que si vous avez vraiment besoin d'utiliser ces togather, alors vous écrivez une implémentation personnalisée simple de ViewResolver qui prend le nom de vue, et décide lequel de vos deux résolveurs de vue "réels" à déléguer. Cela suppose que vous pouvez indiquer quel résolveur appeler en fonction du nom de la vue.


donc vous devriez définir un ViewResolver personnalisé comme celui-ci:

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

Vous auriez besoin de mettre en œuvre la méthode isTilesView pour décider résolveur de déléguer.

Dans la configuration XML, définissez ce nouveau résolveur d'affichage et assurez-vous qu'il apparaît avant les autres.

<bean class="MyViewResolver"> 
    <property name="tilesResolver" ref="tilesViewResolver"/> 
    <property name="jspResolver" ref="viewResolver"/> 
</bean> 
+0

Pourriez-vous élaborer un peu là-dessus? Je ne suis pas vraiment sûr de la façon dont je transférerais le contrôle à un autre résolveur de vue. –

+0

Voir modifier pour l'exemple de code – skaffman

+0

Cela semble très bien, va l'essayer, merci! J'ai essayé quelque chose de similaire auparavant, mais je me suis basé sur le retour de null pour continuer dans la chaîne, et ça ne fonctionnait pas correctement. –

1

Il semble que vous soyez sur la bonne voie, mais la chose à garder à l'esprit est que certains résolveurs de vue se comportent comme s'ils avaient toujours résolu la vue. Vous devez vous assurer de mettre de tels résolveurs dans votre commande. Je crois que la vue de carreaux est un tel. Edit: whoops ... oui, l'autre affiche est correcte, ces deux résolveurs feront toujours 'match' donc vous ne pouvez pas les utiliser tous les deux dans une chaîne. Une autre alternative serait d'essayer d'étendre TilesView pour faire un rendu JSP simple s'il ne peut pas trouver une vue de vignette configurée.

+0

Ils ont tous deux se comportent toujours de cette façon, ce qui est ce qui crée le problème. –

3

Je viens de résoudre le même problème en divisant le fichier de configuration *-servlet.xml en deux; dans mon cas, l'application principale utilise des tuiles, mais je veux que les tests QUnit soient de simples JSP.

app-servlet.xml ne contient que le résolveur de vue Tiles, tests-servlet.xml ne contient que le résolveur de vue JSP et web.xml correspondances sont dispatching demandes au servlet correcte basant sur l'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> 
0

Oui, vous pouvez utiliser n'importe quel nombre de résolveurs de vue dans votre projet.

Vous pouvez donc utiliser à la fois 'mosaïque View resolver' et 'Internal view resolver' dans le même projet. .

vous devez configurer ContentNegotiatingViewResolver. .

et de donner la valeur de l'ordre dans vos résolveurs de vue.

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

comme je l'ai donné tuiles vue résolveur 2 et 3. internalviewresolver .it d'abord vérifier dans les définitions de carreaux si une vue ne se trouve pas dans les carreaux, il sera vérifié dans InternaiViewResolver

Voici quelques configurations travaille pour moi.

<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

Je résolu ce problème en ajoutant simplement la définition de carreaux pour la mise en page jsp plaine, comme ceci:

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

Alors vous ne pouvez utiliser cette mise en page en tant que modèle pour inclure vos fichiers jsp simples.

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

et le fichier modèle de mise en page:

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