2013-08-04 3 views
3

В соответствии с документацией вы должны иметь возможность передать javabean в шаблон FreeMarker, и он сможет получить доступ к геттерам компонента. Я пытался это сделать, но не повезло. Вот мой код, где я передаю компонент в шаблон.FreeMarker не может получить доступ к свойствам javabean

public class Hello extends HttpServlet { 
    public static final Logger LOGGER = Logger.getLogger(Hello.class.getName()); 

    @Override 
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 
     try { 
      Configuration cfg = new Configuration(); 
      cfg.setDirectoryForTemplateLoading(new File(this.getServletContext().getRealPath("/templates"))); 
      cfg.setObjectWrapper(new DefaultObjectWrapper()); 
      cfg.setDefaultEncoding("UTF-8"); 
      cfg.setTemplateExceptionHandler(TemplateExceptionHandler.HTML_DEBUG_HANDLER); 
      cfg.setIncompatibleImprovements(new Version(2, 3, 20)); // FreeMarker 2.3.20 

      final String name = req.getParameter("name"); 
      // This works when model is a Map, but not when it is a bean 
      Model model = new Model(); 
      model.setUsername(name); 
      Template template = cfg.getTemplate("hello.ftl"); 
      template.process(model, resp.getWriter()); 
     } catch (TemplateException ex) { 
      LOGGER.log(Level.SEVERE, "Unexpected template exception", ex); 
      resp.sendError(500); 
     } 
    } 

    private static class Model { 
     private String username; 

     public void setUsername(String username) { 
      this.username = username; 
     } 

     public String getUsername() { 
      return username; 
     } 

    } 
} 

Когда я пытаюсь получить доступ к ${username} в шаблоне, я получаю следующее сообщение об ошибке.

The following has evaluated to null or missing: 
==> username [in template "hello.ftl" at line 8, column 10] 

Tip: If the failing expression is known to be legally null/missing... (snip) 

The failing instruction (FTL stack trace): 
---------- 
==> ${username} [in template "hello.ftl" at line 8, column 8] 
---------- 

Я могу заставить шаблон работать правильно, когда я пользуюсь Картой. Я попытался явно обернуть объект Model различными обертками TemplateModel, но ничего, что я пытаюсь, кажется, работает.

Любые подсказки?

ответ

4

Model должен быть открытым классом для этого.

Другие замечания, относящиеся к вопросу: используйте setServletContextForTemplateLoading вместо setDirectoryForTemplateLoading, иначе ваше приложение не будет работать, если оно запущено из распакованного .war. Кроме того, конечно, вы не должны повторно создавать Configuration для каждого запроса, но я предполагаю, что это так, только для этого примера.

+0

Это исправлено. Я проверил источник FreeMarker, и они явно проверяют, включен ли компонент. Только тогда они пытаются открыть общественные методы. Не знаете, почему они это сделали, поскольку вы можете получить общедоступные методы любого объекта с отражением. Спасибо за другие советы. Знал не восстанавливать объект конфигурации, но не знал о загрузке шаблона. – haydenmuhl

+0

Да, я не знаю, почему это ограничение существует ... Я добавил это в свой длинный длинный список TODO (я был сторонником FM). – ddekany

Смежные вопросы