在 FreeMarker 中使用绝对路径

Posted

技术标签:

【中文标题】在 FreeMarker 中使用绝对路径【英文标题】:Using An Absolute Path With FreeMarker 【发布时间】:2010-11-15 13:05:30 【问题描述】:

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

【问题讨论】:

【参考方案1】:

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

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

【讨论】:

感谢您的回答。我最终只是每次都更改模板目录,但创建自定义 FileTemplateLoader 将是更正确的处理方法。我当然理解如果使用它来生成网页,为什么这会是一个安全漏洞,但是如果它在普通用户正在运行的程序中,在我看来,标准的 linux 权限应该是一个足够好的预防措施,不是吗? 只要您的权限设置得当,是的,您应该没问题。不过,我仍然无法想象您为什么要使用绝对路径……似乎您希望将模板保留在某个通用(非根)文件夹下,或者,如果它们是每个用户可自定义的,则相对于用户的家。但我相信你有你的理由 - 祝你实施顺利。【参考方案2】:

我必须使用绝对路径,因为模板是在 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());

    // ...

【讨论】:

非常感谢。我不再开发这个项目,所以我无法测试这个,但我相信其他有我同样问题的人会很感激这个。 我接受了你的回答,因为社区似乎同意,抱歉花了这么长时间!【参考方案3】:

实际上它删除了开头的“/”所以你需要重新添加它

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

【讨论】:

【参考方案4】:

接受的解决方案的问题是,路径名在使用 TemplateLoader 之前在 FreeMarker 中被破坏。请参阅模板缓存:

    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());

【讨论】:

以上是关于在 FreeMarker 中使用绝对路径的主要内容,如果未能解决你的问题,请参考以下文章

freemarker include必须在同一个目录下吗

node rename绝对路径

怎么把文件保存到绝对路径

绝对路径与相对路径

linux系统下,输入绝对路径程序运行不了

什么相对路径?什么是绝对路径?