2008-10-24 11 views
7

나는 Freemarker에서 Tiles2 + Freemarker로 이주하려고 애 쓰고있었습니다.Spring + Tiles2 + Freemarker - Freemarker 서블릿 또는 Spring의 FreeMarkerViewResolver를 통해 통합 할 수 있습니까?

내 freemarker 템플릿은 spring.ftl에서 오는 매크로를 사용합니다.

web.xml에서 fremarker 서블릿을 제공하는 경우 내 모델은 freemarker에 표시되지만 스프링 변수 FreemarkerView가 해당 모델을 담당하므로 특정 스프링 변수 (자연스럽게)가 모델에 채워지지 않습니다.

특정 URL (예 : "/ tpl/*")에 대해 별도의 DispatcherServlet을 구성하고 해당 서블릿에 대한 기본보기 확인자로 freemarker resolver를 구성하고 기본 컨트롤러로 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

더 나은 솔루션을 찾으셨습니까? –

+0

freemarker 서블릿과 spring taglibs를 사용하고 있습니다. 그들은 특수 스프링 freemarker 매크로를 통해 사용하고있는 모든 것을 처리합니다. – miceuz

+0

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

답변

1

두 프로젝트에서 같은 문제가 해결 된 것을 기억합니다. 두 번째 접근법이 거의 올바르지 만 (FreeMarkerViewResolver) 정확하게 기억한다면 두 모델을 명시 적으로 연결하기 위해 FreeMarkerViewTilesView까지 확장해야했습니다.

사용자 정의 타일보기 :

public class CustomTilesView extends TilesView { 

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

사용자 정의 프리 마커보기 :

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

작동합니다.