2008-10-24 41 views
7

今天我在努力從Freemarker遷移到Tiles2 + Freemarker。Spring + Tiles2 + Freemarker - 通過Freemarker Servlet或通過Spring的FreeMarkerViewResolver集成?

我的freemarker模板使用來自spring.ftl的宏。

如果我在web.xml中提供了一個fremarker servlet,我的模型對freemarker是可見的,但特定的spring變量(自然)不會作爲彈簧填充到模型中,FreemarkerView負責這一點。

如果我爲特定url(比如「/ tpl/*」)配置一個單獨的DispatcherServlet,並將freemarker解析器配置爲該servlet的默認視圖解析器並提供UrlFilenameViewController作爲默認控制器,則特殊彈簧變量會填充到模型中,但我自己的模型不可見:它被綁定爲一個請求屬性。我可以通過$ {Request.mymodel.myvar}訪問我的模型,但這種方式我必須更改所有我的freemarker模板,並且我在這個想法中看到了一些臭味。

現在我的解決辦法是延長UrlFilenameViewController會和請求加我模型的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); 
    } 

但這種方法是有點臭太 - 如果我在我的生意控制器添加了一些模型,我要在這裏添加它。

有沒有一個優雅的解決方案,我的問題?

+0

你有沒有找到一個更好的解決方案呢? – 2009-02-03 18:34:58

回答

1

我記得我在兩個項目中解決了同樣的問題。 你的第二種方法幾乎是正確的(FreeMarkerViewResolver),但如果我沒有記錯的話,我還必須擴展FreeMarkerViewTilesView以明確地將兩個模型連接在一起。

定製瓷磚觀點:

public class CustomTilesView extends TilesView { 

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

自定義FreeMarker的觀點:

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

註冊無論是在春:

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

應該工作。