【问题标题】:How to create Template based files in Java?如何在 Java 中创建基于模板的文件?
【发布时间】:2012-04-07 13:55:41
【问题描述】:

我想在 java 中创建一个模板文件,我使用 Eclipse IDE。我想创建一个模板文件,这样一个从用户那里获取参数的程序应该能够将这些参数粘贴到模板文件中,然后将其保存为单独的文件。我怎样才能做到这一点 ?

请指导我。

谢谢 注意

【问题讨论】:

    标签: java eclipse templates


    【解决方案1】:

    这是在我的开源模板引擎Chunk 中执行此操作的方法。

     import com.x5.template.Theme;
     import com.x5.template.Chunk;
     import java.io.File;
     import java.io.FileWriter;
     import java.io.IOException;
    
     ...
    
     public void writeTemplatedFile() throws IOException
     {
         Theme theme = new Theme();
         Chunk chunk = theme.makeChunk("my_template", "txt");
    
         // replace static values below with user input
         chunk.set("name", "Lancelot");         
         chunk.set("favorite_color", "blue");
    
         String outfilePath = getFilePath();
         File file = new File(outfilePath);
         FileWriter out = new FileWriter(file);
    
         chunk.render(out);
    
         out.flush();
         out.close();
     }
    

    my_template.txt(只需放在themes/my_template.txt的类路径中)

    My name is {$name}.
    
    My favorite color is {$favorite_color}.
    

    输出:

    My name is Lancelot.
    
    My favorite color is blue.
    

    通过向标签添加 |filters 和 :defaults 可以使您的模板更加智能。

    my_template.txt - 示例 2

    My name is {$name|defang:[not provided]}.
    
    My favorite color is {$favorite_color|defang|lc:[not provided]}.
    

    在此示例中,defang 过滤器会删除任何可能有助于形成 XSS 攻击的字符。 lc 过滤器将文本更改为小写。冒号后面的任何内容都将输出,以防值为空。

    有一个Eclipse plugin 可用于直接在 Eclipse IDE 中编辑块模板。该插件为模板文档提供语法高亮和大纲视图。

    Chunk 可以做更多事情,请查看docs 进行快速浏览。全面披露:我喜欢 Chunk 的部分原因是我创造了它。

    【讨论】:

    • 更新以帮助警告人们这个答案是一个无耻的自我插入:)
    • 易于设置!我在自己的道路上挣扎了一下。但最后,成功了! :) 非常感谢!
    【解决方案2】:

    有大量的 Java 模板解决方案。

    【讨论】:

    • 我发现它们最好的一个易于使用的是 Jtwig(来自 PHP symfony 的 Twig 端口)。它具有非常好的继承结构和脚本(也是可扩展的),而其他那些你必须将实际代码嵌入到 HTML 标记中并且由于缺乏继承而不得不复制代码。缺点是 jtwig 已被弃用:/
    • @TheRealChx101 风景和十年前差不多(三角洲 Thymeleaf,我猜是 Pebble)。您将“HTML 模板”与“模板”混为一谈;它们是不同的东西。但是,在 HTML 模板的 HTML 标记中包含“代码”有可量化的好处,因为它们是实际的 HTML,并且可以这样查看(数据前原型)。模板继承遇到与普通 OOP 继承相同的问题(有时更多),因为 HTML。您也可以通过多种方式实现“模板继承”,具体取决于您的意思。
    • 当我说代码时,我指的是模板的脚本/模板语言。例如,thymeleaf 要求您向 HTML 元素添加属性,这很愚蠢,因为很难覆盖这种行为或添加自定义函数。 Jtwig 在各方面都很出色
    • @TheRealChx101 这也是愚蠢的,因为您可以在原型设计期间按原样使用 HTML,因为它没有与其他语言混合,它可以通过普通 DOM 工具查询(更容易用于处理和内省的工具)等。您可能不喜欢它,但它远非“愚蠢”。
    【解决方案3】:
    【解决方案4】:

    让我们把它分解成几个步骤:

    1. 从用户那里获取输入参数:

      无论您如何执行此操作(向 servlet 发送请求、使用 CLI 或将参数传递给 main 方法),您都需要在某种对象或数据结构中捕获输入。为此,我将创建一个像这样的简单 pojo 类:

    public class UserInput
    {
    
      protected String firstName;
    
      protected String lastName;
    
        public String getFirstName()
        {
            return firstName;
        }
    
        public void setFirstName(String firstName)
        {
            this.firstName = firstName;
        }
    
        public String getLastName()
        {
            return lastName;
        }
    
        public void setLastName(String lastName)
        {
            this.lastName = lastName;
        }
    
    }
    
    1. 创建一个模板引擎接口:

      这很方便,因此您可以尝试多个模板库。使用界面也是最佳实践,这样您就可以轻松改变主意并切换到不同的库。我最喜欢的库是freemarkermustache。这是一个演示其常见流程的界面示例。

    public interface ITemplateEngine
    {
        /**
         * creates the template engines instance and sets the root path to the templates in the resources folder
         * @param templatesResouceFolder 
         */
        public void init(String templatesResouceFolder);
    
        /**
         * sets the current template to use in the process method
         * @param template 
         */
        public void setTemplate(String template);
    
        /**
         * compiles and writes the template output to a writer
         * @param writer
         * @param data 
         */
        public void process(Writer writer, Object data);
    
        /**
         * returns the template file extension
         * @return 
         */
        public String getTemplateExtension();
    
        /**
         * finishes the write process and closes the write buffer
         */
        public void flush();
    
    } 
    
    1. 实现接口

    第一个是 freemarker 模板的示例...

    /**
     * This class is a freemarker implementation of ITemplateEngine
     * Use ${obj.prop} in your template to replace a certain the token
     * Use ${obj.prop!} to replace with empty string if obj.prop is null or undefined
     * 
     * 
     */
    public class FreemarkerTemplateEngine implements ITemplateEngine
    {
    
        protected Configuration instance = null;
    
        protected String templatesFolder = "templates";
    
        protected Template templateCompiler = null;
    
        protected Writer writer = null;
    
        @Override
        public void init(String templatesResouceFolder)
        {
    
            if(instance == null){
                instance = new Configuration();
                instance.setClassForTemplateLoading(this.getClass(), "/");
                this.templatesFolder = templatesResouceFolder;
            }
        }
    
        @Override
        public void setTemplate(String template)
        {
            try
            {
                templateCompiler = instance.getTemplate(templatesFolder + File.separatorChar + template + getTemplateExtension());
            } catch (IOException ex)
            {
                Logger.getLogger(FreemarkerTemplateEngine.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    
        @Override
        public void process(Writer writer, Object data)
        {
            try
            {
                templateCompiler.process(data, writer);
                this.writer = writer;
            } catch (TemplateException | IOException ex)
            {
                Logger.getLogger(FreemarkerTemplateEngine.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    
        @Override
        public String getTemplateExtension()
        {
            return ".ftl";
        }
    
        @Override
        public void flush()
        {
            try
            {
                this.writer.flush();
            } catch (IOException ex)
            {
                Logger.getLogger(FreemarkerTemplateEngine.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    
    }
    

    这是一个mustache模板引擎的例子...

    /**
     * 
     * Use {{obj.prop}} in your template to replace a certain the token
     * If obj.prop is null or undefined, it will automatically replace it with an empty string
     * If you want to exclude an entire section based on if a value is null, undefined, or false you can do this:
     *     {{#obj.prop}}
     *     Never shown
     *     {{/obj.prop}}  
     */
    public class MustacheTemplateEngine implements ITemplateEngine
    {
    
        protected MustacheFactory factory = null;
    
        protected Mustache instance = null;
    
        protected Writer writer = null;
    
        protected String templatesFolder = "templates";
    
        @Override
        public void init(String templatesResouceFolder)
        {
            if(factory == null){
                factory = new DefaultMustacheFactory();
                this.templatesFolder = templatesResouceFolder;
            }
        }
    
        @Override
        public void setTemplate(String template)
        {
            instance = factory.compile(templatesFolder + File.separatorChar + template + getTemplateExtension());
        }
    
        @Override
        public void process(Writer writer, Object data)
        {
            this.writer = instance.execute(writer, data);
        }
    
        @Override
        public String getTemplateExtension()
        {
            return ".mustache";
        }
    
        @Override
        public void flush()
        {
            try
            {
                this.writer.flush();
            } catch (IOException ex)
            {
                Logger.getLogger(MustacheTemplateEngine.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    
    }
    
    1. 创建模板

    Freemarker 模板具有“.ftl”扩展名,而 mustache 模板具有“.mustache”扩展名。让我们创建一个名为“test.mustache”的小胡子模板,并将其放在“resources/templates”文件夹中。

    Hello {{firstName}} {{lastName}}!
    
    1. 现在,让我们使用我们的模板引擎。

    创建 JUnit 测试总是一个好主意

    public class JavaTemplateTest
    {
    
        ITemplateEngine templateEngine = new MustacheTemplateEngine();
    
        public File outputFolder = new File(System.getProperty("user.home") + "/JavaTemplateTest");
    
        @Before
        public void setUp()
        {
            outputFolder.mkdirs();
        }
    
        @After
        public void tearDown()
        {
            for (File file : outputFolder.listFiles())
            {
                file.delete();
            }
            outputFolder.delete();
        }
    
        public JavaTemplateTest()
        {
        }
    
        @Test
        public void testTemplateEngine() throws Exception
        {
    
            //mock the user input
            UserInput userInput = new UserInput();
            userInput.setFirstName("Chris");
            userInput.setLastName("Osborn");
    
            //create the out put file
            File file = new File(outputFolder.getCanonicalPath() + File.separatorChar + "test.txt");
    
            //create a FileWriter 
            try (Writer fileWriter = new FileWriter(file.getPath()))
            {
    
                //put the templateEngine to work
                templateEngine.init("templates");
                templateEngine.setTemplate("test"); //resources/templates/test.mustache
                templateEngine.process(fileWriter, userInput); //compile template
                templateEngine.flush(); //write to file
            }
    
            //Read from the file and assert
            BufferedReader buffer = new BufferedReader(new FileReader(file));
            Assert.assertEquals("Hello Chris Osborn!", buffer.readLine());
    
        }
    
    }
    

    基本上就是这样。如果您使用 maven 进行设置,则在运行 mvn install 目标时测试应该运行并通过。

    这是我为此示例创建的项目代码:https://github.com/cosbor11/java-template-example

    希望对你有帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-10
      • 1970-01-01
      • 2015-08-05
      • 1970-01-01
      • 1970-01-01
      • 2020-11-17
      • 2011-09-24
      • 2017-01-03
      相关资源
      最近更新 更多