2008-10-24 11 views
7

Estaba luchando hoy intentando migrar de Freemarker a Tiles2 + Freemarker.Spring + Tiles2 + Freemarker: ¿se integran a través de Freemarker Servlet o Spring FreeMarkerViewResolver?

Mis plantillas de freemarker usan macros que vienen de spring.ftl.

Si proporciono un servlet fremarker en web.xml, mi modelo es visible para freemarker, pero las variables de resorte específicas (naturalmente) no se incluyen en el modelo como manantiales FreemarkerView es responsable de eso.

Si configuro un DispatcherServlet separado para una URL específica (digamos "/ tpl/*") y configuro freemarker como predeterminado para ese servlet y proporciono UrlFilenameViewController como controlador predeterminado, las variables de resorte especiales se llenan al modelo, pero mi propio modelo no es visible: está vinculado como un atributo de solicitud. Puedo acceder a mi modelo a través de $ {Request.mymodel.myvar} pero de esta manera tengo que cambiar todas mis plantillas de freemarker y veo algo mal en la idea.

Ahora mi solución fue extender UrlFilenameViewController y añadir mi modelo de solicitud a ModelAndView:

protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) { 
     ModelAndView mav = super.handleRequestInternal(request, response); 

     HashMap<String, Object> map = new HashMap<String, Object>(); 

     Enumeration<String> attributes = request.getAttributeNames(); 

     while(attributes.hasMoreElements()) { 
      String attribute = attributes.nextElement(); 

      if("model".equals(attribute)) { 
       logger.debug("FreemarkerViewController.handleRequestInternal: putting attribute to model: " + attribute + "=" + request.getAttribute(attribute)); 
       map.put(attribute, request.getAttribute(attribute)); 
      } 
     } 
     logger.debug("FreemarkerViewController.handleRequestInternal: VIEW: " + mav.getViewName()); 
     return new ModelAndView(mav.getViewName(), map); 
    } 

Pero esta solución es algo maloliente también - si añado algo que el modelo en mis controladores de negocio, tengo que agrégalo aquí.

¿Existe una solución elegante para mi problema?

+0

¿Alguna vez encontró una mejor solución para esto? –

+0

estoy usando servlet freemarker y taglibs de primavera - se encargan de todo lo que estaba usando a través de macros especiales de Spring Freemarker. – miceuz

+0

Relacionados con http://stackoverflow.com/questions/221178/can-anyone-point-me-to-spring-mvc-tiles-freemarker-integration-example – Nick

Respuesta

1

Recuerdo que resolví el mismo problema en dos proyectos. Su segundo enfoque es casi correcto (FreeMarkerViewResolver), pero si mal no recuerdo también tuve que extenderme desde FreeMarkerView y TilesView para unir explícitamente ambos modelos.

Azulejos personalizados vista:

vista
public class CustomTilesView extends TilesView { 

    @Override 
    protected void exposeModelAsRequestAttributes(Map model, HttpServletRequest request) { 
     request.setAttribute(CustomFreeMarkerView.MODEL_KEY, model); 
    } 
} 

FreeMarker personalizado:

public class CustomFreeMarkerView extends FreeMarkerView { 

    public static final String MODEL_KEY = FreeMarkerView.class.getName() + ".MODEL"; 

    @Override 
    protected void exposeHelpers(Map model, HttpServletRequest request) throws Exception { 
     super.exposeHelpers(model, request); 
     final Map savedModel = (Map) request.getAttribute(MODEL_KEY); 
     if (savedModel != null) { 
      mergeModels(model, savedModel); 
     } 
    } 

    private void mergeModels(Map<String, Object> targetModel, Map<String, Object> recipientModel) throws ServletException { 
     for (Map.Entry<String, Object> entry : recipientModel.entrySet()) { 
      String key = entry.getKey(); 
      if (targetModel.containsKey(key)) { 
       throw new ServletException("Cannot merge models because of an existing model object of the same name: " + key); 
      } 
      targetModel.put(key, entry.getValue()); 
     } 
    } 
} 

Registro tanto en primavera:

<bean class="org.springframework.web.servlet.view.UrlBasedViewResolver" 
     p:viewClass="com.my.CustomTilesView" 
     p:contentType="text/html;charset=UTF-8"/> 

<bean class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver" 
     p:suffix=".ftl" 
     p:exposeSpringMacroHelpers="true" 
     p:viewClass="com.my.CustomFreeMarkerView" 
     p:contentType="text/html;charset=UTF-8"/> 

debería funcionar.

Cuestiones relacionadas