Использование Freemarker с Restlet 2.0 на сервере Java EE - PullRequest
5 голосов
/ 21 марта 2011

Я немного запутался с тем, что написано в документации (ах) для Freemarker и расширения freemarker Рестлета.

Вот ситуация: механизм перезапуска обслуживает HTML-представление ресурса (например, www.mysite.com/ enjuser automotive/updates). Ресурс, возвращаемый для этого URI, представляет собой HTML-страницу со всеми обновлениями, созданную с помощью шаблона freemarker. Это приложение размещено на сервере Glassfish v3

Вопрос (ы):

  • Конфигурация freemarker должна быть загружена только один раз в соответствии с документацией freemarker:

        /* You should do this ONLY ONCE in the whole application life-cycle:Create and adjust the configuration */
        Configuration cfg = new Configuration();
        cfg.setDirectoryForTemplateLoading(
                new File("/where/you/store/templates"));
        cfg.setObjectWrapper(new DefaultObjectWrapper());
    

    Как лучше всего это сделать в приложении Java EE? Я думаю о том, чтобы использовать его в качестве context-param в web.xml и использовать ServletContextListener - но я не уверен, как это сделать.

  • В соответствии с документацией freemarker мы также можем добавить freemarkerservlet и отобразить в него .ftl url-pattern. Но это уже отображено сервлетом Restlet (то есть шаблон URL "/ "). Так что иметь другой для * .ftl не имеет смысла (или нет?)

Таким образом, вопрос заключается в том, как лучше всего интегрироваться с «конфигурацией» Freemarker, чтобы это происходило только один раз, и какова «точка входа» для этого фрагмента кода (который его вызывает). Кто-нибудь успешно использовал Freemarker + restlet в среде Java EE? Есть идеи?

Спасибо!

1 Ответ

6 голосов
/ 23 марта 2011

Это был сложный вопрос - действительно. Требуется, чтобы я прошел через реализацию исходных файлов в пакете org.restlet.ext.Freemarker - Фу!

Вот как вы можете это сделать

  1. Если вам нужно создать свой объект конфигурации OWN, установите «templateLoader» для использования, а затем настройте TemplateRepresentation для работы с ним:

    Configuration cfg = new Configuration();
    
    ContextTemplateLoader loader = new ContextTemplateLoader(getContext(),"war:///WEB-INF");
    
    cfg.setTemplateLoader(loader);
    
    TemplateRepresentation rep = null;
    
    Mail mail = new Mail(); //The data object you wish to populate - example from Restlet itself
        mail.setStatus("received");
        mail.setSubject("Message to self");
        mail.setContent("Doh!");
        mail.setAccountRef(new Reference(getReference(), "..").getTargetRef()
                .toString());
    
      Map<String, Object> data = new HashMap<String, Object>();
      data.put("status", mail.getStatus());
      data.put("subject", mail.getSubject());
      data.put("content", mail.getContent());
      data.put("accountRef", mail.getAccountRef());
    
      rep = new TemplateRepresentation("Mail.ftl", cfg, data, MediaType.TEXT_HTML);
    
      return rep;
    
  2. Если вы удовлетворены настройками по умолчанию и хотите использовать загрузчик шаблонов на основе загрузчика классов

    //Load the FreeMarker template
        Representation mailFtl = new ClientResource(
                LocalReference.createClapReference(getClass().getPackage())
                        + "/Mail.ftl").get(); 
      //Wraps the bean with a FreeMarker representation
    return new TemplateRepresentation(mailFtl, mail, MediaType.TEXT_HTML);
    
  3. Если вы хотите инициализировать объект конфигурации один раз и установить шаблон, вызвав метод setServletContextForTemplateLoading (...) для объекта конфигурации. Вы всегда можете сделать это в ServletContextListener


public class Config implements ServletContextListener {
    private static Configuration cfg = new Configuration();

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        ServletContext sc = sce.getServletContext();
        cfg.setServletContextForTemplateLoading(sc, "/WEB-INF");        
    }
    public static Configuration getFMConfig()
    {
        return cfg;
    }
}

А затем вызовите статический метод getFMConfig () и передайте его в TemplateRepresentation, как в 1

На что обратить внимание:

  • Если вы получите протокол, который не поддерживается, исключение будет в случае 2. Подразумевает, что ServerResource не знает, какой протокол использовать для доступа к файлу - это будет протокол CLAP Рестлета. Возможно, вам придется настроить init-params для RestletServlet в файле web.xml и использовать CLAP в качестве одного из значений param
  • В TemplateRepresentation довольно много конструкторов - если вы НЕ передадите объект конфигурации во время создания экземпляра (используя другой перегруженный конструктор), он создаст для вас новую конфигурацию (). Таким образом, вам не нужно настраивать конфигурацию, как в 2 (Это может показаться вам очевидным, но я предположил, что вам все равно нужно будет настроить конфигурацию, иначе она "подберет ее откуда-то")
  • Если вы действительно хотите настроить свою СОБСТВЕННУЮ конфигурацию, вы ДОЛЖНЫ передать ее одному из конструкторов
  • Посмотрите на строку "war: ///" в конструкторе ContextTemplateLoader в 1. это важно Нет, где упоминается, что должна быть эта ссылка baseUri даже не в документах. Я довольно долго пытался понять, что это должен быть «war: ///», за которым следует имя папки, в которой хранятся шаблоны.
  • В случае 2 вам, вероятно, придется хранить шаблоны в том же пакете, что и файл класса, из которого осуществляется доступ к этому коду. Если вы внимательно посмотрите, вы заметите параметр LocalReference в качестве аргумента для ClientResource, говорящего о том, что ресурс должен присутствовать локально, и, следовательно, вам нужно использовать собственный протокол CLAP (протокол доступа к classLoader)

Точка личного разочарования - почему все это даже не разъяснено ни в документации, ни в другом месте :)

Надеюсь, это поможет тому, кто наткнется на этот пост! Уф!

...