2008-10-24 13 views
7

Я изо всех сил пытался мигрировать из Фримаркера в Tiles2 + Freemarker.Spring + Tiles2 + Freemarker - интегрируется через сервлет Freemarker или через SpringMarkerViewResolver Spring?

Мои шаблоны freemarker используют макросы, которые поступают из spring.ftl.

Если я предоставляю сервлет fremarker в web.xml, моя модель видна freemarker, но конкретные весенние переменные (естественно) не заполняются в модель в качестве пружин, за которые несет ответственность FreemarkerView.

Если настроить отдельный DispatcherServlet для конкретного URL (скажем «/ TPL/*») и настроить Freemarker распознаватель как вид по умолчанию распознаватель для этого сервлета и обеспечить 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), но если я правильно помню, мне также пришлось растягиваться от FreeMarkerView и TilesView, чтобы явно объединить обе модели вместе.

Пользовательские плитки вид:

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

Должно работать.