低代码探索:Java模板引擎技术

2022-12-01 15:46:12 浏览数 (1)

系列文章:

Mavan:自定义骨架及工程初始化

一 前言

上一篇文章简单介绍了工程的初始化方法,本篇将探索代码生成技术。因为业务开发中使用Java语言较多,所以这里以Java作为背景语言。

大家熟知并且日常都在使用Spring/SpringMVC/SpringBoot、Mybatis框架,在开发中我们经常需要手写Entity、Mapper、dao、service、controller相关代码,这些重复性的工作会占用很多工作时间。如果有一个代码生成工具来做这些重复工作,显然可以提高我们的工作效率。这时,就需要了解模板引擎技术。

二 模板引擎工具:freemarker与velocity

最早接触的是velocity,记得14,15年左右,当时在某家公司开发的前端页面,就是使用velocity作为模板引擎。创建前端页面的vm/tpl模板后,利用velocity提供的能力,编写脚本生成静态页面,然后再走上线更新。

除了velocity之外,freemarker也是一款模板引擎,使用FreeMarker Template Language(FTL)编写,它是一种简单的、专用的语言。

关于二者(有时也会包括thymeleaf)的对比,已经有一些文章进行了分析,这里不再赘述,感兴趣的朋友可以搜索,或在评论中留言一起探讨。这里基于以前的一些调研工作,选择freemarker作为这里使用的模板引擎,用于示例。

三 freemarker介绍

freemarker的基础介绍,可以参考freemarker在线手册,中文版地址:http://freemarker.foofun.cn/。

简单来说,FreeMarker 是一款 模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页,电子邮件,配置文件,源代码等)的通用工具。 它不是面向最终用户的,而是一个Java类库,是一款程序员可以嵌入他们所开发产品的组件。

freemarker的几个关键概念:模板(template)、Java对象(Java Object)、输出(Output),三者含义和关系可通过下图体现:

(1)其中,template是我们要使用的模板,基于这个模板来生成文件。简单来说,就是一些固定模式(代码/标签/逻辑) 变量的组合,其中变量在后面根据需要,替换成所需的值;

(2)Java Object是模型/对象,可以简单理解为一些key-value对,key是变量名称,value就是变量的值;

(3)Output是输出结果,在把template中的变量替换成object中的value后,就得到了我们预期的文件。

而替换的动作,就是由freemarker来实现的。

四 示例

4.1 工程结构

这里采用maven工程,idea创建,工程目录结构如下:

4.2 依赖包引入-pom

代码语言:javascript复制
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>template-engine</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <dependencies>
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.23</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.0.2</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
        <finalName>${project.artifactId}</finalName>
    </build>
</project>

4.3 自定义freemark模板

这里预期是生成一个Java类,如下所示,是一个典型的bean,包括几个属性和对应的get/set方法,几个变量: packageName-包名,className-类名,属性:id, userName, password

代码语言:javascript复制
package ${packageName};

public class ${className} {

    private Integer ${id};

    private String ${userName};

    private String ${password};

    public Integer get${id?cap_first}(){
        return ${id};
    }

    public void set${id?cap_first}(Integer ${id}){
        this.${id}=${id};
    }

    public String get${userName?cap_first}(){
        return ${userName};
    }

    public void set${userName?cap_first}(String ${userName}){
        this.${userName}=${userName};
    }

    public String get${password?cap_first}(){
        return ${password};
    }

    public void set${password?cap_first}(String ${password}){
        this.${password}=${password};
    }
}

4.4 定义生成代码方法

代码语言:javascript复制
package com.freemark.demo.templates.util;

import freemarker.template.Configuration;
import freemarker.template.Template;

import java.io.*;
import java.util.HashMap;
import java.util.Map;

public class FreemarkTest {

  private static final String TEMPLATE_PATH = "src/main/java/com/freemark/demo/templates";

  private static final String CLASS_PATH = "src/main/java/com/freemark/demo";

  public static void main(String[] args) {
    // 创建freeMarker配置实例
    Configuration configuration = new Configuration();
    Writer out = null;
    try {

      // 设置模版路径
      configuration.setDirectoryForTemplateLoading(new File(TEMPLATE_PATH));
      // 创建数据模型
      Map<String, Object> dataMap = new HashMap<>();
      dataMap.put("packageName", "com.freemark.demo");
      dataMap.put("className", "Test");
      dataMap.put("id", "id");
      dataMap.put("userName", "userName");
      dataMap.put("password","password");

      // 加载模版文件
      Template template = configuration.getTemplate("test.ftl");

      // 生成文件流
      File docFile = new File(CLASS_PATH   "/"   "Test.java");
      out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(docFile)));

      // 输出到文件
      template.process(dataMap, out);
      System.out.println("Test.java 源码生成成功!");
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      try {
        if (null != out) {
          out.flush();
        }
      } catch (Exception e2) {
        e2.printStackTrace();
      }
    }
  }
}

运行main方法,可以看到控制台会打印出 Test.java 源码生成成功! 并在src/main 指定的包下,生成了Test.java类文件,内容如下:

代码语言:javascript复制
package com.freemark.demo;

public class Test {

    private Integer id;

    private String userName;

    private String password;

    public Integer getId(){
        return id;
    }

    public void setId(Integer id){
        this.id=id;
    }

    public String getUserName(){
        return userName;
    }

    public void setUserName(String userName){
        this.userName=userName;
    }

    public String getPassword(){
        return password;
    }

    public void setPassword(String password){
        this.password=password;
    }
}

0 人点赞