2009-07-30 146 views
1

我一直在使用FreeMarker有一段时间,但有一个明显的功能缺失或者我无法弄清楚(我希望后者!)。如果你传递了一个绝对路径cfg.getTemplate(),它就不起作用。我知道你可以指定一个模板目录,但是我不能这么做,我的用例可能会处理任何目录中的文件。有没有办法设置FreeMarker以任何用户期望的方式渲染绝对路径?在FreeMarker中使用绝对路径

回答

6

我不得不使用绝对路径,因为模板是在Ant脚本中发生的,而模板在文件系统上,并且使用Ant文件集发现。我想这是相当一些独特的要求...

无论如何,对于后人(只要SO达),这里是一个可行的解决方案:

public class TemplateAbsolutePathLoader implements TemplateLoader { 

    public Object findTemplateSource(String name) throws IOException { 
     File source = new File(name); 
     return source.isFile() ? source : null; 
    } 

    public long getLastModified(Object templateSource) { 
     return ((File) templateSource).lastModified(); 
    } 

    public Reader getReader(Object templateSource, String encoding) 
      throws IOException { 
     if (!(templateSource instanceof File)) { 
      throw new IllegalArgumentException("templateSource is a: " + templateSource.getClass().getName()); 
     } 
     return new InputStreamReader(new FileInputStream((File) templateSource), encoding); 
    } 

    public void closeTemplateSource(Object templateSource) throws IOException { 
     // Do nothing. 
    } 

} 

和初始化:

public String generate(File template) { 

    Configuration cfg = new Configuration(); 
    cfg.setTemplateLoader(new TemplateAbsolutePathLoader()); 
    Template tpl = cfg.getTemplate(template.getAbsolutePath()); 

    // ... 
} 
1

Freemarker默认使用FileTemplateLoader,它不允许你从“base”目录(默认取自'user.dir'系统属性,所以它是你的主目录)以外的地方获取模板。你可以做的是:

  1. 明确创建FileTemplateLoader与BASEDIR从下,你会得到模板(理论上你可以将其设置为使用绝对路径根但这是设置为您最上面的目录从安全的角度来看,这是非常糟糕的©)。
  2. 编写自己的模板加载器,它将采用绝对路径,但确保模板仍在模板文件夹内。如果你这样做,注意比较规范文件路径。
  3. 重新思考你的方法。你真的需要模板的绝对路径吗?
+0

感谢您的回答。我最终只是每次更改模板目录,但创建自定义FileTemplateLoader将是更正确的方式来处理它。 我当然明白为什么这将是一个安全漏洞,如果使用它来生成网页,但如果它在程序中正常用户正在运行,在我看来,标准的linux权限应该是一个足够好的预防措施,不是吗? – dimo414 2009-08-04 23:20:50

+0

只要你的权限设置得当,是的,你应该没问题。我仍然无法想象为什么你会使用绝对路径,尽管......似乎你想要将模板保存在一个普通的(非root)文件夹下,或者如果它们是每个用户可定制的,则相对于用户的家。但我相信你有你的理由 - 祝你好运。 – ChssPly76 2009-08-04 23:29:59

2

其实它删除开始“/”,所以你需要添加它

public Object findTemplateSource(String name) throws IOException { 
    File source = new File("/" + name); 
    return source.isFile() ? source : null; 
} 
0

的问题接受的解决方案是,在使用TemplateLoader之前,路径名在FreeMarker中被销毁。见TemplateCache:

name = normalizeName(name); 
    if(name == null) { 
     return null; 
    } 
    Template result = null; 
    if (templateLoader != null) { 
     result = getTemplate(templateLoader, name, locale, encoding, parseAsFTL); 
    } 

所以我觉得这是更好地使用一个解决方案,提出in this answer

例如

 Configuration config = new Configuration(); 
     File templateFile = new File(templateFilename); 
     File templateDir = templateFile.getParentFile(); 
     if (null == templateDir){ 
      templateDir = new File("./"); 
     } 
     config.setDirectoryForTemplateLoading(templateDir); 
     Template template = config.getTemplate(templateFile.getName());