使用FreeMarker的绝对路径

时间:2009-07-30 17:52:32

标签: java linux freemarker

我一直在使用FreeMarker一段时间,但有一个明显的功能要么丢失要么我想不出来(我希望后者!)。如果你传递cfg.getTemplate()一个绝对路径,它就行不通。我知道你可以指定一个模板目录,但我负担不起,我的用例可以处理任何目录中的文件。有没有办法设置FreeMarker以任何用户期望的方式呈现绝对路径?

4 个答案:

答案 0 :(得分: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 :(得分:2)

实际上它会删除开头“/”,因此您需要将其添加回

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

答案 2 :(得分:1)

Freemarker默认使用FileTemplateLoader,它不允许你从“base”目录之外获取模板(默认情况下,它来自'user.dir'系统属性,因此它是你的主目录)。你能做的是:

  1. 显式创建FileTemplateLoader,并将baseDir设置为您将获得模板的最顶层目录(理论上您可以将其设置为root以便使用绝对路径,但从安全角度来看,这是非常糟糕的事情)
  2. 编写自己的模板加载器,它将采用绝对路径,但确保模板仍在模板文件夹中。如果这样做,请注意比较规范文件路径。
  3. 重新思考你的方法。你真的需要模板的绝对路径吗?

答案 3 :(得分: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());