在 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 中使用绝对路径的主要内容,如果未能解决你的问题,请参考以下文章