繁体   English   中英

是否可以“预处理” Freemarker模板?

[英]Is it possible to “pre-process” Freemarker templates?

考虑以下模板:

<#include "../header.txt"/>
<#list items as item>
Item name is: ${item.name}<br/>
</#list>

header.txt包含:

<html>
<head>
</head>
<body>

我想对该模板进行“预处理”,以便得到的输出为:

<html>
<head>
</head>
<body>
<#list items as item>
Item name is: ${item.name}<br/>
</#list>

我希望能够扩展包含但不能解析变量。 如何使用Freemarker做到这一点?

FreeMarker不支持这样做(仅解决模板的某些部分)。 您可以做的是使用自己的解析器预处理模板。 通过使用您自己的TemplateLoader实现(将其委派给另一个TemplateLoader (原始的)并过滤内容)来支持该功能。 因此,当您第一次需要模板时,您可以即时应用转换,并且结果将被缓存(在FreeMarker的标准模板缓存中)。 我建议您使用自己的语法(例如<%include '...'> ),以便每个人都可以看到特殊的内容。

我最终不得不创建自己的扩展器。 我希望这对某人有用:

/**
 * Utility class to perform Freemarker template expansion.
 * 
 * @author Chris Mepham
 */
public class FreemarkerTemplateExpander implements ApplicationAware {

    static final String INCLUDE_REGEX = "<#include \\\"\\S+\\\"\\/>";

    static final String PATH_REGEX = "\\\"\\S+\\\"";

    private ModuleStateHolder moduleStateHolder;

    /**
     * Takes the Freemarker template String input and
     * 
     * recursively expands all of the includes.
     * 
     * @param input The String value of a Freemarker template.
     * 
     * @return The expanded version of the Freemarker template.
     */
    public final String expand(String module, String path, String input) {

        Assert.notNull(module, "module cannot be null");
        Assert.notNull(path, "path cannot be null");
        Assert.notNull(input, "input cannot be null");

        if (!hasText(input)) return input;

        // See if there is an include
        int indexOfNextInclude = getIndexOfNextInclude(Pattern.compile(INCLUDE_REGEX), input);

        // If there is no include just return the input text
        if (indexOfNextInclude == -1) return input;

        StringBuffer buffer = new StringBuffer();

        // Otherwise, get all the text up to the next include and add it to buffer
        String prefix = input.substring(0, indexOfNextInclude);
        if (hasText(prefix)) buffer.append(prefix);

        // Then get the contents of the include as a String
        String includeContents = getIncludeContents(module, path, input);
        if (hasText(includeContents)) buffer.append(includeContents);

        // Then get all the text after the next include
        int includeLastCharacterIndex = indexOfNextInclude + matchRegexPattern(input, INCLUDE_REGEX).length();

        String suffix = input.substring(includeLastCharacterIndex + 1);

        buffer.append(suffix);

        input = buffer.toString();

        return expand(module, path, input);
    }

    final String getIncludeContents(String module, String path1, String input) {

        // Get next include file relative path
        String nextIncludePath = getNextIncludePath(input);
        String resourcePath = getResourcePath(nextIncludePath);

        // Get file name
        String filename = getFilename(nextIncludePath);

        // Get file contents here
        String path = "templates." + resourcePath;
        InputStream resource = ClasspathResourceUtils.getClassPathResource(path, filename, getClassLoader(module));

        StringWriter writer = new StringWriter();
        try {
            IOUtils.copy(resource, writer, "UTF-8");
        } catch (IOException e) {
            e.printStackTrace();
        }

        return writer.toString();
    }

    static final int getIndexOfNextInclude(Pattern pattern, String input) {

        Matcher matcher = pattern.matcher(input);

        return matcher.find() ? matcher.start() : -1;
    }

    private static final String getNextIncludePath(String input) {

        String include = matchRegexPattern(input, INCLUDE_REGEX);

        if (include == null) return null;

        String path = matchRegexPattern(include, PATH_REGEX);
        path = path.replace("\"", "");

        return path;
    }

    private static final String matchRegexPattern(String input, String regex) {

        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(input);

        while(matcher.find()) {

            return matcher.group(0);
        }

        return null;
    }

    private String getResourcePath(String path) {

        if (!path.contains("/")) return path;

        String resourcePath = path.substring(path.indexOf("/") + 1, path.lastIndexOf("/"));

        return resourcePath;

    }

    private String getFilename(String path) {

        if (!path.contains("/")) return path;

        return path.substring(path.lastIndexOf("/") + 1);
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM