mvc - ¿Cómo usar múltiples ViewResolvers en Spring?
tags spring mvc (5)
Estoy trabajando en una aplicación web en la que tengo la mayoría de mis páginas que usan apache tiles (2.1.2), pero algunas de ellas solo necesitan ser jsps.
Estoy teniendo un problema en que tanto InternalResourceViewResolver
como UrlBasedViewResolver
intentarán resolver la vista sin importar qué, así que no importa qué orden use, fallará en las páginas JSP simples o en las páginas de mosaicos.
Aquí está la configuración:
<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 que quede más claro lo que estoy tratando de hacer, necesito poder tener estados de vista como este:
<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 hacer que muestre definiciones de mosaicos y jsps simples?
Acabo de resolver el mismo problema dividiendo el archivo de configuración *-servlet.xml
en dos; en mi caso, la aplicación principal utiliza Tiles, pero quiero que las pruebas QUnit sean simples JSP.
app-servlet.xml
solo contiene el programa de resolución de vistas de Tiles, tests-servlet.xml
solo contiene el sistema de resolución de vistas de JSP y las asignaciones de web.xml
envían solicitudes 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>
Como dices, no puedes encadenarlos. El javadoc para ambos estados indica claramente que ambos deben estar al final de la cadena de resolución.
Le sugiero que si realmente necesita usar estos elementos para reunirse, escriba una implementación personalizada simple de ViewResolver que tome el nombre de la vista y decida a cuál de sus dos resolutores de vista "reales" delegará. Esto supone que puede indicar a qué resolutor llamar según el nombre de la vista.
Así que definirías un ViewResolver personalizado como este:
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) {
.....
}
}
Necesitará implementar el método isTilesView para decidir a qué resolución delegar.
En la configuración XML, defina este nuevo resolvedor de vista y asegúrese de que aparezca antes que los otros.
<bean class="MyViewResolver">
<property name="tilesResolver" ref="tilesViewResolver"/>
<property name="jspResolver" ref="viewResolver"/>
</bean>
Parece que estás en el camino correcto, pero lo que debes tener en cuenta es que algunos resolvedores de vista se comportan como si siempre hubieran resuelto la vista. Debes asegurarte de poner estos resolutores al final de tu pedido. Creo que la vista Tiles es una de ellas.
Edit: whoops ... sí, el otro póster es correcto, ambos de estos solucionadores harán ''siempre coincidir'', así que no puedes usarlos en una cadena. Otra alternativa sería tratar de extender el TilesView para realizar un procesamiento JSP simple si no puede encontrar una vista de mosaico configurada.
Resolví este problema simplemente agregando la definición de mosaicos para el diseño de jsp simple, como esto:
<definition name="plain-jsp.layout" template="/WEB-INF/layouts/plainJsp.jspx" >
<put-attribute name="content" value=""/>
</definition>
Luego, solo puede usar este diseño como plantilla para incluir sus archivos jsp simples.
<definition name="catalog/details" extends="plain-jsp.layout">
<put-attribute name="content" value="/WEB-INF/views/catalog/details.jspx"/>
</definition>
Y el archivo de plantilla de diseño:
<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>
Sí, puede utilizar cualquier número de resolución de vistas en su proyecto.
Por lo tanto, puede usar tanto ''resolución de vistas en mosaico'' como ''resolución de vista interna'' en el mismo proyecto. .
Tienes que configurar un ContentNegotiatingViewResolver. .
y dar el valor del pedido en su vista a los resolutores.
<property name="order" value="int Value here" />
al igual que le he dado a las vistas la resolución 2 y la visualización interna de las vistas 3.. Primero verificará las definiciones de las fichas si no se encuentra una vista en las fichas, se verificará en InternaiViewResolver
Aquí hay algunas configuraciones que funcionan para mí.
<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>