2009-06-22 5 views
17

Estoy trabajando en una aplicación web donde tengo la mayoría de mis páginas haciendo uso de los mosaicos de Apache (2.1.2), pero algunos de ellos solo necesitan ser simples jsps.¿Cómo usar múltiples ViewResolvers en Spring?

Tengo un problema porque tanto InternalResourceViewResolver como UrlBasedViewResolver intentarán resolver la vista pase lo que pase, de modo que no importa qué orden use, o bien fallará en las páginas JSP simples, o en las teselas páginas.

Aquí está el 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> 

Para hacer más claro lo que estoy tratando de hacer, tengo que ser capaz de tener visión estados como esto:

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

¿Alguien sabe ¿Cómo configurar las cosas para que pueda obtener que renderice definiciones de teselas y jsps simples?

Respuesta

20

Como dices, no puedes encadenarlos. El javadoc para ambos establece claramente que ambos deben estar al final de la cadena de resolución.

Sugiero que si realmente necesita usar estos togather, escriba una implementación personalizada simple de ViewResolver que tome el nombre de la vista y decida a cuál de sus dos resolvedores de vistas "reales" debe delegar. Esto supone que puede decir a qué resolver llamar en función del nombre de la vista.


Quizás definen un ViewResolver encargo de esta manera:

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

Se necesitaría para poner en práctica el método isTilesView decidir qué Resolver delegar a.

En la configuración XML, defina esta nueva resolución de vista, y asegúrese de que aparezca antes de las demás.

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

¿Podría explicar un poco sobre esto? No estoy seguro de cómo transferiría el control a otro sistema de resolución de vistas. –

+0

Consulte la edición del código de muestra – skaffman

+0

Se ve genial, lo intentaré, gracias! Intenté algo similar antes, pero estaba basado en devolver nulo para continuar en la cadena, y no estaba funcionando correctamente. –

1

Parece que va por buen camino, pero hay que tener en cuenta que algunos resolvedores de vistas se comportan como si siempre hubieran resuelto la vista. Debes asegurarte de poner esos resolvedores al final de tu orden. Creo que la vista de Tiles es una de ellas.

Edit: whoops ... sí, el otro póster es correcto, ambos resolvedores 'siempre coincidirán' por lo que no puede utilizarlos en una cadena. Otra alternativa sería intentar extender TilesView para hacer un simple render JSP si no puede encontrar una vista de mosaico configurada.

+0

Ambos siempre se comportan de esa manera, que es lo que crea el problema. –

3

he acabamos de resolver el mismo problema al dividir el archivo de configuración *-servlet.xml en dos; en mi caso, la aplicación principal usa Tiles, pero quiero que las pruebas QUnit sean JSP simples.

app-servlet.xml incluye solamente la vista de resolución Azulejos, tests-servlet.xml sólo contiene la vista de resolución de JSP y web.xml asignaciones están despachando peticiones al servlet correcto basándose en la 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

Sí, puede utilizar cualquier número de resolución de vista en su proyecto.

Para que pueda usar tanto 'tiles View resolver' como 'Internal view resolver' en el mismo proyecto. .

tiene que configurar un ContentNegotiatingViewResolver. .

y proporcione valor de orden en sus resolutores de vista.

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

azulejos como yo he dado ver resolutor 2 y 3. internalviewresolver .it compruebe en primer lugar en las definiciones de los azulejos si un punto de vista no se encuentra en los azulejos se comprobará en InternaiViewResolver

aquí es que algunas configuraciones funciona para mi.

<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

I resuelto este problema mediante la simple adición definición azulejos para el diseño de JSP llano, como esto:

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

continuación, sólo puede utilizar este diseño como plantilla para la inclusión de sus simples archivos JSP.

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

y la plantilla de diseño de archivo:

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