我们正在尝试在freemarker中构建一个系统,可以选择添加扩展文件来替换标准模板的块。
我们已经到了这一点
<#attempt>
<#include "extension.ftl">
<#recover>
Standard output
</#attempt>
所以 - 如果extension.ftl文件存在,它将被使用,否则将输出recover块内的部分。
问题在于,freemarker始终记录导致恢复块触发的错误。
所以我们需要两件事之一:
-OR -
答案 0 :(得分:2)
更简单的解决方案是:
<#attempt>
<#import xyz.ftl>
your_code_here
<#recover>
</#attempt>
答案 1 :(得分:0)
我也有这个确切的需求,但我不想使用FreeMarker的ObjectConstructor
(根据我的口味,它感觉太像一个小脚本)。
我写了一个自定义FileTemplateLoader:
public class CustomFileTemplateLoader
extends FileTemplateLoader {
private static final String STUB_FTL = "/tools/empty.ftl";
public CustomFileTemplateLoader(File baseDir) throws IOException {
super(baseDir);
}
@Override
public Object findTemplateSource(String name) throws IOException {
Object result = null;
if (name.startsWith("optional:")) {
result = super.findTemplateSource(name.replace("optional:", ""));
if (result == null) {
result = super.findTemplateSource(STUB_FTL);
}
}
if (result == null) {
result = super.findTemplateSource(name);
}
return result;
}
}
我相应的FreeMarker宏:
<#macro optional_include name>
<#include "/optional:" + name>
</#macro>
需要一个空的FTL文件(/tools/empty.ftl
),该文件只包含解释其存在的注释。
结果是,如果找不到请求的FTL,“可选”包含将包含此空FTL。
答案 2 :(得分:0)
我们已经编写了一个自定义宏来解决这个问题。在早期测试中,它运作良好。要包含它,添加这样的东西(其中mm是Spring ModelMap):
mm.addAttribute(IncludeIfExistsMacro.MACRO_NAME, new IncludeIfExistsMacro());
import java.io.IOException;
import java.util.Map;
import org.apache.commons.io.FilenameUtils;
import freemarker.cache.TemplateCache;
import freemarker.cache.TemplateLoader;
import freemarker.core.Environment;
import freemarker.template.TemplateDirectiveBody;
import freemarker.template.TemplateDirectiveModel;
import freemarker.template.TemplateException;
import freemarker.template.TemplateModel;
/**
* This macro optionally includes the template given by path. If the template isn't found, it doesn't
* throw an exception; instead it renders the nested content (if any).
*
* For example:
* <@include_if_exists path="module/${behavior}.ftl">
* <#include "default.ftl">
* </@include_if_exists>
*
* @param path the path of the template to be included if it exists
* @param nested (optional) body could be include directive or any other block of code
*/
public class IncludeIfExistsMacro implements TemplateDirectiveModel {
private static final String PATH_PARAM = "path";
public static final String MACRO_NAME = "include_if_exists";
@Override
public void execute(Environment environment, Map map, TemplateModel[] templateModel,
TemplateDirectiveBody directiveBody) throws TemplateException, IOException {
if (! map.containsKey(PATH_PARAM)) {
throw new RuntimeException("missing required parameter '" + PATH_PARAM + "' for macro " + MACRO_NAME);
}
// get the current template's parent directory to use when searching for relative paths
final String currentTemplateName = environment.getTemplate().getName();
final String currentTemplateDir = FilenameUtils.getPath(currentTemplateName);
// look up the path relative to the current working directory (this also works for absolute paths)
final String path = map.get(PATH_PARAM).toString();
final String fullTemplatePath = TemplateCache.getFullTemplatePath(environment, currentTemplateDir, path);
TemplateLoader templateLoader = environment.getConfiguration().getTemplateLoader();
if (templateLoader.findTemplateSource(fullTemplatePath) != null) {
// include the template for the path, if it's found
environment.include(environment.getTemplateForInclusion(fullTemplatePath, null, true));
} else {
// otherwise render the nested content, if there is any
if (directiveBody != null) {
directiveBody.render(environment.getOut());
}
}
}
}
答案 3 :(得分:0)
您也可以使用Java方法检查文件是否存在。
Java方法 -
public static boolean checkFileExistance(String filePath){
File tmpDir = new File(filePath);
boolean exists = tmpDir.exists();
return exists;
}
Freemarker Code -
<#assign fileExists = (Static["ClassName"].checkFileExistance("Filename"))?c/>
<#if fileExists = "true">
<#include "/home/demo.ftl"/>
<#else>
<#include "/home/index.ftl">
</#if>
答案 4 :(得分:-1)
尝试此操作以获取基本路径:
<#assign objectConstructor = "freemarker.template.utility.ObjectConstructor"?new()>
<#assign file = objectConstructor("java.io.File","")>
<#assign path = file.getAbsolutePath()>
<script type="text/javascript">
alert("${path?string}");
</script>
然后这就走了目录结构:
<#assign objectConstructor = "freemarker.template.utility.ObjectConstructor"?new()>
<#assign file = objectConstructor("java.io.File","target/test.ftl")>
<#assign exist = file.exists()>
<script type="text/javascript">
alert("${exist?string}");
</script>