获取包含当前 FreeMarker 的目录的绝对路径

问题描述 投票:0回答:2

Apache FreeMarker 中,如何获取包含当前

.ftl
文件的目录的绝对路径?

例如,如果我正在处理文件

/path/to/template.ftl
,那么我正在寻找一种方法将
/path/to
放入
/path/to/template.ftl
中。

我已经尝试过

.current_template_name
和朋友,但这些实际上只包含文件的名称,而不是它的绝对路径(我可以从中获取父目录)。我也尝试过 absolute_template_name ,但这似乎只是在名称前面加上
/
以使路径看起来是绝对的,但它并没有解析为真正的绝对路径。

背景:我正在使用 Freemarker 模板化 Asciidoc 文件,并且 Asciidoc 文件必须包含驻留在

.flt
文件的原始目录下的其他 Asciidoc 文件,因此不得相对于临时“扩展”Asciidoc 文件搜索它们.

freemarker
2个回答
0
投票

模板使用的模板路径始终是虚拟的,并由

TemplateLoader
中设置的
Configuration
对象解析。
TemplateLoader
只是一个接口,有多种实现,对于FreeMarker来说也是一个黑盒子。模板的实际位置可以在 jar 文件内,甚至可以在数据库表中,因此通常模板在文件系统上没有路径。

通常,您设置

TemplateLoader
,以便它可以访问您需要的所有模板。那么你不需要任何技巧,只需使用模板路径即可。

另一种可能性是使用

FileTemplateLoader
将根目录用作基目录。对于大多数应用程序来说,这当然是一个坏主意(特别是出于安全原因,对于 Web 应用程序)。


0
投票

请务必阅读已接受答案中的解释,因为您很可能还需要其他内容。话虽如此,您可以使用反射深入了解 freemarker 的内部工作原理。以下代码获取给定 templateName 的绝对路径。

  private String getAbsolutePath(String inputFilePath, Configuration freeMarkerConfiguration) {
    String absolutePath = null;
    try {
      TemplateCache templateCache = getField(freeMarkerConfiguration, "cache", TemplateCache.class);
      Locale locale = freeMarkerConfiguration.getLocale();
      TemplateLookupResult lookup = callMethod(templateCache, "lookupTemplate", TemplateLookupResult.class, new Object[] {inputFilePath, locale, null});
      Object templateSource = callMethod(lookup, "getTemplateSource", Object.class, new Object[] {});
      File source = getField(templateSource, "source", File.class);
      absolutePath = source.getAbsolutePath();
    } catch (Exception e) {
      e.printStackTrace();
    }
    return absolutePath;
  }

  private <T> T callMethod(Object source, String methodName, Class<T> claz, Object[] methodInput)
      throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
    Class<?>[] inputTypes = Arrays.asList(methodInput).stream().map(t -> t == null ? Object.class : t.getClass()).toArray(Class[]::new);
    return callMethod(source, methodName, claz, methodInput, inputTypes);
  }

  private <T> T callMethod(Object source, String methodName, Class<T> claz, Object[] methodInput, Class<?>[] inputTypes)
      throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
    Method method = source.getClass().getDeclaredMethod(methodName, inputTypes);
    method.setAccessible(true);
    Object result = method.invoke(source, methodInput);
    return claz.cast(result);
  }

  private <T> T getField(Object source, String fieldName, Class<T> claz)
      throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
    Field field = source.getClass().getDeclaredField(fieldName);
    field.setAccessible(true);
    Object value = field.get(source);
    return claz.cast(value);
  }
© www.soinside.com 2019 - 2024. All rights reserved.