Java 如何呈现路径中有符号链接的freemarker模板?

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分支

我试图使用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分支。当我们的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
    }
}