java - mvc - Accediendo Spring Beans desde una vista de Tiles(JSP)
spring mvc menu navigation example (3)
En Spring MVC puedo acceder a mis beans en JSP utilizando los atributos de contexto de contexto expuestos de JstlView (o exposeContextBeansAsAttributes). Por ejemplo, entonces, en mi JSP puedo escribir ($ {properties.myProperty). Pero cuando el mismo JSP es parte de una vista de mosaicos, estas propiedades no son accesibles. ¿Es posible configurar Tiles correctamente o acceder a estas propiedades de otra manera?
Estoy usando Spring MVC 3.0.2 y Tiles 2.2.1. Aquí hay un poco de mi configuración:
<bean id="tilesViewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="order" value="1"/>
<property name="viewClass" value="org.springframework.web.servlet.view.tiles2.TilesView" />
</bean>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="order" value="2"/>
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
<property name="exposedContextBeanNames">
<list><value>properties</value></list>
</property>
</bean>
EDITAR: He implementado la solución de Skaffman.
TilesExposingBeansViewResolver.java:
package es.kcsolutions.util.spring.servlet.view;
import org.springframework.web.servlet.view.*;
public class TilesExposingBeansViewResolver extends UrlBasedViewResolver {
private Boolean exposeContextBeansAsAttributes;
private String[] exposedContextBeanNames;
public void setExposeContextBeansAsAttributes(boolean exposeContextBeansAsAttributes) {
this.exposeContextBeansAsAttributes = exposeContextBeansAsAttributes;
}
public void setExposedContextBeanNames(String[] exposedContextBeanNames) {
this.exposedContextBeanNames = exposedContextBeanNames;
}
@Override
protected AbstractUrlBasedView buildView(String viewName) throws Exception {
AbstractUrlBasedView superView = super.buildView(viewName);
if (superView instanceof TilesExposingBeansView) {
TilesExposingBeansView view = (TilesExposingBeansView) superView;
if (this.exposeContextBeansAsAttributes != null) view.setExposeContextBeansAsAttributes(this.exposeContextBeansAsAttributes);
if (this.exposedContextBeanNames != null) view.setExposedContextBeanNames(this.exposedContextBeanNames);
}
return superView;
}
}
TilesExposingBeansView.java:
package es.kcsolutions.util.spring.servlet.view;
import java.util.*;
import javax.servlet.http.*;
import org.springframework.web.context.support.ContextExposingHttpServletRequest;
import org.springframework.web.servlet.view.tiles2.TilesView;
public class TilesExposingBeansView extends TilesView {
private boolean exposeContextBeansAsAttributes = false;
private Set<String> exposedContextBeanNames;
public void setExposeContextBeansAsAttributes(boolean exposeContextBeansAsAttributes) {
this.exposeContextBeansAsAttributes = exposeContextBeansAsAttributes;
}
public void setExposedContextBeanNames(String[] exposedContextBeanNames) {
this.exposedContextBeanNames = new HashSet<String>(Arrays.asList(exposedContextBeanNames));
}
protected HttpServletRequest getRequestToExpose(HttpServletRequest originalRequest) {
if (this.exposeContextBeansAsAttributes || this.exposedContextBeanNames != null)
return new ContextExposingHttpServletRequest(originalRequest, getWebApplicationContext(), this.exposedContextBeanNames);
return originalRequest;
}
@Override
protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest requestToExpose = getRequestToExpose(request);
exposeModelAsRequestAttributes(model, requestToExpose);
super.renderMergedOutputModel(model, requestToExpose, response);
}
}
Configuración de la primavera:
<bean id="tilesViewResolver" class="es.kcsolutions.util.spring.servlet.view.TilesExposingBeansViewResolver">
<property name="order" value="1"/>
<property name="viewClass" value="es.kcsolutions.util.spring.servlet.view.TilesExposingBeansView"/>
<property name="exposedContextBeanNames">
<list><value>properties</value></list>
</property>
</bean>
Si tiene algún problema, eche un vistazo a TilesExposingBeansView.renderMergedOutputModel. He hecho algunas pruebas, pero tal vez es necesario hacer mucho más.
¿Ha intentado usar ServletContextAttributeExporter en el archivo de configuración xml?
<bean
class="org.springframework.web.context.support.ServletContextAttributeExporter">
<property name="attributes">
<map>
<entry key="<bean key here>">
<ref bean="<bean name here" />
</entry>
</map>
</property>
</bean>
A partir de la primavera 3.0 ahora hay un TilesViewResolver .
Subclase de conveniencia de UrlBasedViewResolver que admite TilesView (es decir, definiciones de Tiles) y sus subclases personalizadas.
La clase de vista para todas las vistas generadas por este resolutor puede especificarse a través de la propiedad "viewClass". Ver javadoc de UrlBasedViewResolver para más detalles.
Nota: Al encadenar ViewResolvers, un TilesViewResolver verificará la existencia de los recursos de plantilla especificados y solo devolverá un objeto de Vista que no sea nulo si se encontró la plantilla.
Desde: 3.0 Autor: Juergen Hoeller
Como se ha dado cuenta, esta funcionalidad es parte de InternalResourceViewResolver
y InternalResourceView
, mientras que las cosas de Tiles se heredan directamente de UrlBasedViewResolver
y AbstractUrlBasedView
, por lo que no puede hacer uso de ella.
Mirando el código, no hay razón para que esto no se haya podido colocar en AbstractUrlBasedView
. La magia sucede en InternalResourceView.getRequestToExpose
, y se ve perfectamente aplicable también a AbstractUrlBasedView
.
En el corto plazo, sugiero subclasificar UrlBasedViewResolver
y TilesView
, copiando el material getRequestToExpose
de InternalResourceView
. A más largo plazo, lo invito a presentar un problema con SpringSource pidiéndoles que muevan esta funcionalidad hacia la jerarquía de clases a AbstractUrlBasedView
, para que esté más disponible.