You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Freemarker如何获取自定义指令的未处理原始内容?

如何获取Freemarker自定义指令的原始未处理内容

要解决宏中嵌套内容被预先处理的问题,不能使用Freemarker宏,必须实现自定义TemplateDirectiveModel指令。通过自定义指令,你可以直接获取未解析的原始模板片段,而不是处理后的内容。

核心解决方案思路

Freemarker的宏(#macro)在执行<#nested/>时会立刻处理嵌套内容并输出结果,无法保留原始模板代码。而自定义指令通过DirectiveCallPlace对象可以直接获取指令嵌套的原始未解析字符串,完全符合你的需求。

实现步骤

1. 编写自定义指令类

实现TemplateDirectiveModel接口,在execute方法中获取原始嵌套内容,并完成业务逻辑:

import freemarker.core.DirectiveCallPlace;
import freemarker.core.Environment;
import freemarker.template.*;
import java.io.IOException;
import java.util.Map;

public class ProcessContentDirective implements TemplateDirectiveModel {

    @Override
    public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body) throws TemplateException, IOException {
        // 解析指令参数:获取name值
        SimpleScalar nameParam = (SimpleScalar) params.get("name");
        if (nameParam == null) {
            throw new TemplateModelException("Required parameter 'name' is missing.");
        }
        String contentName = nameParam.getAsString();

        // 获取原始未处理的嵌套模板内容
        DirectiveCallPlace callPlace = env.getCurrentDirectiveCallPlace();
        String rawTemplateContent = callPlace.getNestedContentAsString();

        // 业务逻辑:从数据库读取或存入原始内容
        String storedContent = getFromDatabase(contentName);
        if (storedContent == null) {
            saveToDatabase(contentName, rawTemplateContent);
            storedContent = rawTemplateContent;
        }

        // 处理并输出最终内容
        Template dynamicTemplate = new Template("dynamic-content", storedContent, env.getConfiguration());
        String processedOutput = FreeMarkerTemplateUtils.processTemplateIntoString(dynamicTemplate, env.getDataModel());
        env.getOut().write(processedOutput);
    }

    // 模拟数据库读取方法
    private String getFromDatabase(String name) {
        // 实际项目中替换为数据库查询逻辑
        return null; // 首次访问返回null,触发存入操作
    }

    // 模拟数据库存储方法
    private void saveToDatabase(String name, String content) {
        // 实际项目中替换为数据库插入/更新逻辑
        System.out.printf("Saved to DB: name=%s, content=%s%n", name, content);
    }
}

2. 配置Freemarker,注册自定义指令

将自定义指令加入Freemarker配置的共享变量:

Configuration freemarkerCfg = new Configuration(Configuration.VERSION_2_3_32);
// 配置模板加载路径、编码等其他设置...
freemarkerCfg.setSharedVariable("process", new ProcessContentDirective());

3. 修改模板,使用自定义指令

替换原来的宏调用,使用自定义指令:

<@process name='this-content-name'>
    <p>This is some content about ${companyName}</p>
</@process>

效果验证

运行后,日志(或数据库存储内容)会输出原始模板代码:

Saved to DB: name=this-content-name, content=<p>This is some content about ${companyName}</p>

而不是处理后的This is some content about My Company Name,完全符合你的预期。

内容的提问来源于stack exchange,提问作者cmorris

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 03:33:30