0

我正在尝试使用 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 缓存正确的路径?

4

1 回答 1

2

问题出在 FreeMarker 的FileTemplateLoader课程上。它对baseDir.getCanonicalFile(...)传递给构造函数的基目录进行调用。当我们的应用程序启动时,基目录/var/cms/live被解析为真实路径/var/cms/trunk/127/getCanonicalFile(...)因此将来对符号链接的任何更改都将被忽略。

它在构造函数中执行此操作,因此我们被迫创建自己的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代码。 关于 pastebin 的完整课程

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
    }
}
于 2013-06-10T22:03:48.703 回答