In freemarker is it possible to check to see if a file exists before including it?

泪湿孤枕 提交于 2019-12-05 04:25:48

easier solution would be:

<#attempt>
    <#import xyz.ftl>
    your_code_here
<#recover>
</#attempt>

We've written a custom macro which solves this for us. In early testing, it works well. To include it, add something like this (where mm is a 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());
            }
        }
    }
}

I had this exact need as well but I didn't want to use FreeMarker's ObjectConstructor (it felt too much like a scriptlet for my taste).

I wrote a custom 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;
    }

}

And my corresponding FreeMarker macro:

<#macro optional_include name>
    <#include "/optional:" + name>
</#macro>

An empty FTL file was required (/tools/empty.ftl) which just contains a comment explaining its existence.

The result is that an "optional" include will just include this empty FTL if the requested FTL cannot be found.

You can use also use Java method to check file exist or not.

Java Method-

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>
Paul Sweatte

Try this to get the base path:

<#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>

Then this to walk the directory structure:

<#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>
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!