2008-10-24 5 views
7

Ich habe heute versucht, von Freemarker zu Tiles2 + Freemarker zu migrieren.Spring + Tiles2 + Freemarker - Integration über Freemarker Servlet oder über Spring's FreeMarkerViewResolver?

Meine Freimarker-Vorlagen verwenden Makros, die von spring.ftl kommen.

Wenn ich in der Datei web.xml ein Fremarker-Servlet zur Verfügung stelle, ist mein Modell für Freemarker sichtbar, aber bestimmte Federvariablen (natürlich) werden nicht in das Modell eingefügt, da FreemarkerView dafür verantwortlich ist.

Wenn ich ein separates DispatcherServlet für spezifische URL (sagen "/ tpl/*") konfigurieren und Freelancer-Resolver als Standard-View-Resolver für dieses Servlet konfigurieren und UrlFilenameViewController als Standard-Controller bereitstellen, werden spezielle Federvariablen zum Modellieren, aber Mein eigenes Modell ist nicht sichtbar: Es ist als Anforderungsattribut gebunden. Ich kann über $ {Request.mymodel.myvar} auf mein Modell zugreifen, aber auf diese Weise muss ich alle meine Freemarker-Vorlagen ändern und sehe etwas stinkendes in der Idee.

Nun war meine Lösung UrlFilenameViewController zu erweitern und fügen Sie mein Modell von Anfrage zu Modeland:

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); 
    } 

Aber diese Lösung ist etwas zu stinken - wenn ich etwas zum Modell in meinem Geschäft Controller hinzufügen, muß ich füge es hier hinzu.

Gibt es eine elegante Lösung für mein Problem?

+0

Haben Sie jemals eine bessere Lösung dafür gefunden? –

+0

Ich benutze Freemarker Servlet und Spring Taglibs - sie kümmern sich um alles, was ich über spezielle Freemarker Makros benutzt habe. – miceuz

+0

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

Antwort

1

Ich erinnere mich, dass ich das gleiche Problem in zwei Projekten gelöst habe. Ihr zweiter Ansatz ist fast richtig (FreeMarkerViewResolver), aber wenn ich mich richtig erinnere, musste ich auch von FreeMarkerView und TilesView verlängern, um beide Modelle zusammen zu überbrücken.

Benutzerdefinierte Fliesen Ansicht:

public class CustomTilesView extends TilesView { 

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

Individuelle Freemarker Ansicht:

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()); 
     } 
    } 
} 

Register sowohl im Frühling:

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

funktionieren sollte.