在Java EE服务器中使用Freemarker和Restlet 2.0

PhD*_*PhD 5 servlets freemarker restlet java-ee restlet-2.0

我对Freemarker和Restlet的freemarker扩展文档中的内容感到有点困惑.

情况就是这样:restlet引擎提供资源的HTML表示(例如www.mysite.com/{user}/updates).为此URI返回的资源是一个HTML页面,其中包含使用freemarker模板创建的所有更新.此应用程序托管在Glassfish v3服务器上

问题(S):

  • 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());
    
    Run Code Online (Sandbox Code Playgroud)

    在Java EE应用程序中执行此操作的最佳位置是什么?我想在web.xml中使用它作为context-param并使用ServletContextListener - 但我不知道如何去做.

  • 根据freemarker的文档,我们还可以添加freemarkerservlet并映射.ftl url-patterns.但是这已经由Restlet servlet映射(即,"/ " 的url模式).所以为*.ftl另外一个没有意义(或者是吗?)

所以问题基本上是关于如何最好地与Freemarker的"配置"集成,以便它只发生一次,这段代码的"入口点"是什么(谁称之为).有没有人在Java EE环境中成功使用Freemarker + restlet?有任何想法吗?

谢谢!

PhD*_*PhD 6

这是一个棘手的问题 - 的确如此.要求我在org.restlet.ext.Freemarker包中执行源文件的实现 - P!

这是你如何做到的

  1. 如果您需要创建自己的OWN配置对象,请设置要使用的'templateLoader',然后让TemplateRepresentation'work'进行渲染:

    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;
    
    Run Code Online (Sandbox Code Playgroud)
  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);
    
    Run Code Online (Sandbox Code Playgroud)
  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;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后调用静态getFMConfig()并将其传递给TemplateRepresentation,如1所示

注意事项:

  • 如果你确实得到了一个不支持的协议Exception就会出现这种情况2.意味着ServerResource不知道用什么协议来访问文件 - 它将是Restlet的CLAP协议.您可能必须在web.xml文件中为RestletServlet设置init-params并将CLAP作为param-values之一
  • TemplateRepresentation有很多构造函数 - 如果你不在实例化期间传递配置对象(使用另一个重载的构造函数),它将为你创建一个新的Configuration().所以你不必像2中那样进行任何配置设置(这可能会让你觉得很明显,但我认为你仍然需要设置一个配置,否则它会"从某个地方拿起它")
  • 如果您希望进行OWN配置设置,则必须将其传递给其中一个构造函数
  • 在1中的ContextTemplateLoader的构造函数中查看"war:///"字符串.这很重要没有在哪里提到这个baseUri引用应该是什么,甚至在文档中都没有.我尝试了很长一段时间才搞清楚它应该是"war:///",然后是存储模板的文件夹名称.
  • 对于案例2,您可能必须将模板存储在与访问此代码的类文件相同的包中.如果你仔细看,你会注意到LocalReference参数作为ClientResource的一个参数,说该资源应该是本地存在的,因此你需要使用自定义CLAP协议(classLoader访问协议)

个人挫折点 - 为什么不是所有这些都在文档或任何地方澄清 :)

希望它可以帮助那些偶然发现这篇文章的人!唷!