Java 如何呈现路径中有符号链接的freemarker模板?
我试图使用FreeMarker来呈现一些来自CMS路径的模板,该路径恰好包含一个符号链接(在Linux下)。我们的CMS代码处理模板的路径,例如,此路径:Java 如何呈现路径中有符号链接的freemarker模板?,java,content-management-system,symlink,freemarker,Java,Content Management System,Symlink,Freemarker,我试图使用FreeMarker来呈现一些来自CMS路径的模板,该路径恰好包含一个符号链接(在Linux下)。我们的CMS代码处理模板的路径,例如,此路径: /var/cms/live/display/main.html 真正指向: /var/cms/trunk/127/display/main.html /var/cms/live是基本目录,而/display/main.html是路径 在我的例子中,live是一个符号链接——在本例中是指向trunk/127。仅供参考:主干是我们的SVN分支
/var/cms/live/display/main.html
真正指向:
/var/cms/trunk/127/display/main.html
/var/cms/live
是基本目录,而/display/main.html
是路径
在我的例子中,live
是一个符号链接——在本例中是指向trunk/127
。仅供参考:主干是我们的SVN分支。当我们的CMS系统下载新版本的CMS文件时(例如)trunk-128.zip
,它会将其解压到trunk/128
,然后将符号链接(原子地)更改为trunk/128
。太好了
问题是FreeMarker似乎缓存了trunk/127
路径。它无法识别文件/var/cms/live/display/main.html
已更新,如果删除trunk/127
树,则会生成500错误
500 Unable to load template: /display/main.html
如何让FreeMarker缓存正确的路径?问题原来是FreeMarker的
FileTemplateLoader
类。它对传递到构造函数中的基本目录执行baseDir.getCanonicalFile(…)
调用。当我们的应用程序启动时,基本目录/var/cms/live
通过getCanonicalFile(…)
解析为实际路径/var/cms/trunk/127/
,因此对符号链接的任何未来更改都将被忽略
它在构造函数中执行此操作,因此我们被迫创建自己的LocalFileTemplateLoader
,如下所示
它只是TemplateLoader
的基本弹簧加载实现。然后,在构建FreeMarker配置时,我们设置模板加载器:
Configuration config = new Configuration();
LocalTemplateLoader loader = new LocalTemplateLoader();
// this is designed for spring
loader.setBaseDir("/var/cms/live");
config.setTemplateLoader(loader);
...
这是我们的LocalFileTemplateLoader
code:
public class LocalFileTemplateLoader implements TemplateLoader {
public File baseDir;
@Override
public Object findTemplateSource(String name) {
File source = new File(baseDir, name);
if (source.isFile()) {
return source;
} else {
return null;
}
}
@Override
public long getLastModified(Object templateSource) {
if (templateSource instanceof File) {
return new Long(((File) templateSource).lastModified());
} else {
throw new IllegalArgumentException("templateSource is an unknown type: " + templateSource.getClass());
}
}
@Override
public Reader getReader(Object templateSource, String encoding) throws IOException {
if (templateSource instanceof File) {
return new InputStreamReader(new FileInputStream((File) templateSource), encoding);
} else {
throw new IllegalArgumentException("templateSource is an unknown type: " + templateSource.getClass());
}
}
@Override
public void closeTemplateSource(Object templateSource) {
// noop
}
@Required
public void setBaseDir(File baseDir) {
this.baseDir = baseDir;
// it may not exist yet because CMS is going to download and create it
}
}