【问题标题】:How to create multiple files based on one Freemarker Template如何基于一个 Freemarker 模板创建多个文件
【发布时间】:2025-12-09 01:10:01
【问题描述】:

我现在在使用 freemarker 时遇到了一点麻烦。我想在我的模板中基本上做的事情:遍历元素列表并为每个元素创建一个新文件。

<#assign x=3>
<#list 1..x as i>
  ${i}
...create a new file with the output of this loop iteration...
</#list>

我在 freemarker 手册或谷歌中没有找到任何关于此的内容。有没有办法做到这一点?

【问题讨论】:

    标签: java code-generation freemarker


    【解决方案1】:

    您可以使用自定义指令来实现这一点。请参阅freemarker.template.TemplateDirectiveModel,尤其是TemplateDirectiveBody。自定义指令可以指定在其嵌套内容中使用的Writer。因此,您可以执行类似&lt;@output file="..."&gt;...&lt;/@output&gt; 的操作,其中嵌套内容将写入您在TemplateDirectiveModel 实现中提供的Writer,在这种情况下应该写入指定的文件。 (FMPP 也这样做:http://fmpp.sourceforge.net/qtour.html#sect4

    【讨论】:

      【解决方案2】:

      您不能仅使用 FreeMarker 来执行此操作。它的想法是从您的模板中生成单个输出流。它甚至不关心您是否将结果保存到文件、直接传递到 TCP 套接字、作为字符串存储在内存中或执行其他任何操作。

      如果你真的想做到这一点,你必须自己处理文件分离。例如,您可以插入特殊行,如:

      <#assign x=3>
      <#list 1..x as i>
        ${i}
      %%%%File=output${i}.html
      ...
      </#list>
      

      之后,您应该自行对 FreeMarker 输出进行后处理,查找以 %%%%File= 开头的行并在此时创建一​​个新文件。

      【讨论】:

        【解决方案3】:

        正如 ddekany 所说,您可以通过执行指令来做到这一点。我编写了一个小例子:

        package spikes;
        
        import java.io.File;
        import java.io.FileWriter;
        import java.io.IOException;
        import java.io.OutputStreamWriter;
        import java.io.Writer;
        import java.util.HashMap;
        import java.util.Map;
        
        import freemarker.core.Environment;
        import freemarker.template.Configuration;
        import freemarker.template.SimpleScalar;
        import freemarker.template.Template;
        import freemarker.template.TemplateDirectiveBody;
        import freemarker.template.TemplateDirectiveModel;
        import freemarker.template.TemplateException;
        import freemarker.template.TemplateModel;
        import io.vertx.core.json.JsonArray;
        import io.vertx.core.json.JsonObject;
        
        class OutputDirective implements TemplateDirectiveModel {
            
            @Override
            public void execute(
                    Environment env, 
                    @SuppressWarnings("rawtypes") Map params, 
                    TemplateModel[] loopVars, 
                    TemplateDirectiveBody body)
                    throws TemplateException, IOException {
                
                SimpleScalar file = (SimpleScalar) params.get("file");
                
                FileWriter fw = new FileWriter(new File(file.getAsString()));
                body.render(fw);
                fw.flush();
            }
        }
        
        public class FreemarkerTest {   
            
            public static void main(String[] args) throws Exception {
                
                Configuration cfg = new Configuration(Configuration.VERSION_2_3_0);
                cfg.setDefaultEncoding("UTF-8");
                
                JsonObject model = new JsonObject()
                        .put("entities", new JsonArray()
                                .add(new JsonObject()
                                        .put("name", "Entity1"))
                                .add(new JsonObject()
                                        .put("name", "Entity2")));
                
                Template template = new Template("Test", "<#assign model = model?eval_json><#list model.entities as entity><@output file=entity.name + \".txt\">This is ${entity.name} entity\n</@output></#list>", cfg);
                
                Map<String, Object> root = new HashMap<String, Object>();
                root.put("output", new OutputDirective());
                root.put("model", model.encode());
                Writer out = new OutputStreamWriter(System.out);
                template.process(root, out);
            }
        }
        

        这将生成两个文件:

        “Entity1.txt”:这是 Entity1 实体

        “Entity2.txt”:这是Entity2实体

        :-)

        【讨论】:

          最近更新 更多