Использование абсолютного пути с FreeMarker - PullRequest
1 голос
/ 30 июля 2009

Я уже некоторое время использую FreeMarker , но есть одна яркая часть функциональности, которая либо отсутствует, либо я просто не могу понять (надеюсь, последняя!). Если вы передадите cfg.getTemplate () абсолютный путь, он просто не будет работать. Я знаю, что вы можете указать каталог шаблонов, но я не могу себе этого позволить, мой сценарий использования может касаться файлов в любом каталоге. Есть ли способ настроить FreeMarker для отображения абсолютных путей так, как этого ожидает любой пользователь?

Ответы [ 4 ]

6 голосов
/ 15 октября 2009

Мне пришлось использовать абсолютный путь, потому что шаблонирование происходит в скрипте 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());

    // ...
}
2 голосов
/ 18 октября 2011

На самом деле он удаляет начало "/", поэтому вам нужно добавить его обратно в

public Object findTemplateSource(String name) throws IOException {
    File source = new File("/" + name);
    return source.isFile() ? source : null;
}
1 голос
/ 30 июля 2009

Freemarker по умолчанию использует FileTemplateLoader, который не позволит вам получать шаблоны извне «базового» каталога (который по умолчанию берется из системного свойства user.dir, поэтому это ваш домашний каталог). Что вы можете сделать, это:

  1. Явно создайте FileTemplateLoader с baseDir, установленным в ваш самый верхний каталог, из которого вы будете получать шаблоны (теоретически вы могли бы установить его как root, чтобы использовать абсолютные пути, но это ОЧЕНЬ ПЛОХАЯ копия) с точки зрения безопасности ).
  2. Напишите свой собственный загрузчик шаблонов, который будет использовать абсолютный путь, но затем убедитесь, что шаблон все еще находится в папке вашего шаблона. Если вы это сделаете, постарайтесь сравнить канонические пути к файлам.
  3. Переосмыслите свой подход. Вам действительно нужны абсолютные пути для шаблонов?
0 голосов
/ 15 марта 2015

Проблема с принятым решением заключается в том, что имя пути уничтожается в FreeMarker перед использованием TemplateLoader. См. TemplateCache:

    name = normalizeName(name);
    if(name == null) {
        return null;
    }
    Template result = null;
    if (templateLoader != null) {
        result = getTemplate(templateLoader, name, locale, encoding, parseAsFTL);
    }

Так что я думаю, что лучше использовать предложенное решение в этом ответе

Например

        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());
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...