案例--使用freemarker實現代碼自動生成

freemarker是一款模板引擎,一種基於模板和數據,並用來生成輸出文本(HTML、配置文件,源代碼等)的工具。

freemarker模板文件相關語法

1、輸出基本數據類型或對象屬性
${數據} 或者 ${對象.屬性}
如:
    ${name}
    ${user.username}


2.輸出集合
<#list userList as item>
    ${item.username}
</#list>

3.if判斷
#list userList as item>
    <#if item.username == 'U1'>
        ${item.username},
    <#elseif item.username == 'U2'>
        你好  ${item.username},
    <#else >
        hello  ${item.username} 。
    </#if>
</#list>
----------------------------------
<#list userList as item>
    <#if item_has_next>
        ${item.username},
    <#else >
        ${item.username}
    </#if>
</#list>

4.當存在 '#{' 要保留時如需要轉義

 ${r"#{"}

測試實例:

新建maven項目,pom添加freemarker的依賴

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

模板文件hello.ftl

<html>
<HEAD>
    <meta charset="UTF-8">
</HEAD>
<BODY>
hello ${name}
<br />
你好 ${user.username}
<br />
<#list userList as item>
    ${item.username}
</#list>
<br />
<#list userList as item>
    <#if item.username == 'U1'>
        ${item.username},
    <#elseif item.username == 'U2'>
        你好  ${item.username},
    <#else >
        hello  ${item.username} 。
    </#if>
</#list>
<br />
<#list userList as item>
    <#if item_has_next>
        ${item.username},
    <#else >
        ${item.username}
    </#if>
</#list>

</BODY>
</html>

User類:

package cn.code;

public class User {

    private String username;

    private String password;

    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;
    }
}

測試類:

package cn.code.test;

import cn.code.User;
import freemarker.template.Configuration;
import freemarker.template.Template;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Test {

    public static void main(String[] args) throws Exception {

        //創建configuration對象
        Configuration configuration = new Configuration(Configuration.getVersion());

        //設置模板所在路徑
        String path = "E:\\IdeaProjects\\generator-demo\\src\\main\\resources\\";
        configuration.setDirectoryForTemplateLoading(new File(path));

        //獲取模板對應實例,hello.ftl爲模板路徑下的模板文件
        Template template = configuration.getTemplate("hello.ftl");

        //指定生成文件的保存路徑
        String savePath = "E:\\IdeaProjects\\generator-demo\\src\\main\\java\\cn\\code\\test\\hello.html";
        FileOutputStream stream = new FileOutputStream(savePath);
        OutputStreamWriter outputStreamWriter = new OutputStreamWriter(stream);

        //組裝數據
        Map param = new HashMap();
        User user = new User();
        user.setUsername("Lily");
        param.put("name","Tom");
        //輸出對象
        param.put("user",user);
        //輸出集合
        List<User> userList = new ArrayList<>();
        User user1 = new User();
        user1.setUsername("U1");
        User user2 = new User();
        user2.setUsername("U2");
        User user3 = new User();
        user3.setUsername("U3");

        userList.add(user1);
        userList.add(user2);
        userList.add(user3);

        param.put("userList",userList);

        //傳參,生成數據文件
        template.process(param, outputStreamWriter);

    }
}

 

<html>
<HEAD>
    <meta charset="UTF-8">
</HEAD>
<BODY>
hello Tom
<br />
你好 Lily
<br />
    U1
    U2
    U3
<br />
        U1,
        你好  U2,
        hello  U3 。
<br />
        U1,
        U2,
        U3

</BODY>
</html>

生成pojo案例:

1、新建maven項目,pom添加freemarker與mysql連接的依賴,注意版本號要與自己安裝的mysql版本一致

    <dependency>
      <groupId>org.freemarker</groupId>
      <artifactId>freemarker</artifactId>
      <version>2.3.23</version>
    </dependency>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.15</version>
    </dependency>
 

新增pojo模板文件

package cn.code.beans;

import java.io.Serializable;


public class ${table.className} implements Serializable {

    <#list table.columns as column>
         //${column.remarks}
         private ${column.javaType} ${column.fieldName};
    </#list>

    <#list table.columns as column>
    public void set${column.upperFieldName} (${column.javaType}  ${column.fieldName} ){
        this.${column.fieldName}=${column.fieldName};
    }

    public  ${column.javaType} get${column.upperFieldName}(){
        return this.${column.fieldName};
    }
    </#list>
}

新增數據庫表名與列名的描述

package cn.code.module;

import java.util.ArrayList;
import java.util.List;

public class Table {

    //數據庫表名
    private String tableName;

    //表名對應的類名
    private String className;

    //表中的列,一對多
    List<Column> columns = new ArrayList<>();

    public String getTableName() {
        return tableName;
    }

    public void setTableName(String tableName) {
        this.tableName = tableName;
    }

    public String getClassName() {
        return className;
    }

    public void setClassName(String className) {
        this.className = className;
    }

    public List<Column> getColumns() {
        return columns;
    }

    public void setColumns(List<Column> columns) {
        this.columns = columns;
    }
}
wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==
package cn.code.module;

public class Column {

    //列名
    private String columnName;

    //列名對應的屬性名
    private String fieldName;

    //首字母大寫的屬性名
    private String upperFieldName;

    //列類型,數據庫類型
    private String columnType;

    //列類型對應的java類型
    private String javaType;

    //備註
    private String remarks;

    public String getRemarks() {
        return remarks;
    }

    public void setRemarks(String remarks) {
        this.remarks = remarks;
    }

    public String getColumnName() {
        return columnName;
    }

    public void setColumnName(String columnName) {
        this.columnName = columnName;
    }

    public String getFieldName() {
        return fieldName;
    }

    public void setFieldName(String fieldName) {
        this.fieldName = fieldName;
    }

    public String getUpperFieldName() {
        return upperFieldName;
    }

    public void setUpperFieldName(String upperFieldName) {
        this.upperFieldName = upperFieldName;
    }

    public String getColumnType() {
        return columnType;
    }

    public void setColumnType(String columnType) {
        this.columnType = columnType;
    }

    public String getJavaType() {
        return javaType;
    }

    public void setJavaType(String javaType) {
        this.javaType = javaType;
    }
}
wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

數據庫相關配置文件database.properties,

注意mysql 8x以上,driver的值,url後面添加 &serverTimezone=GMT ,不然會報異常

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/testdb?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT
user=root
password=root

 

相關工具類PropertiesUtils.java 

package cn.code.util;

import java.io.InputStreamReader;
import java.util.Properties;


public class PropertiesUtils {

    private static Properties props;

    /**
     * 加載配置文件
     *
     * @param fileName
     */
    private static void readProperties(String fileName) {
        try {
            props = new Properties();
            InputStreamReader inputStream = new InputStreamReader(PropertiesUtils.class.getClassLoader().getResourceAsStream(fileName), "UTF-8");
            props.load(inputStream);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 根據key讀取對應的value
     *
     * @param key
     * @return
     */
    public static String get(String fileName,String key) {
        readProperties(fileName);
        //System.out.println(props.getProperty(key));
        return props.getProperty(key);
    }

}
wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==
package cn.code.util;

public class StringUtils {

    //根據數據庫列類型返回相應的java類型
    public static String switchType(String columnName) {
        String javaType = null;

        switch (columnName) {

            case "VARCHAR":
                javaType = "String";
                break;
            case "INT":
                javaType = "Integer";
                break;
            case "DATETIME":
                javaType = "Date";
                break;
            default:
                javaType = "String";

        }

        return javaType;
    }

    /**
     * 字符串首字母大寫
     *
     * @param str
     * @return
     */
    public static String captureName(String str) {

        return String.valueOf(str.charAt(0)).toUpperCase() + str.substring(1);
    }

    /**
     * 去除下劃線,下劃線後的首字母大寫
     *
     * @param str
     * @return
     */
    public static String putOffUnderline(String str) {

        int idx = str.indexOf("_");
        if (idx == -1) return str;

        String s1 = str.replaceFirst("_", "");
        String s2 = s1.substring(0, idx) + String.valueOf(s1.charAt(idx)).toUpperCase() + s1.substring(idx + 1);

       /* String[] strings = str.split("_");

        for (int i = 0; i < strings.length; i++) {
            if (i == 0)
                ret += strings[i];
            else
                ret += String.valueOf(strings[i].charAt(0)).toUpperCase() + strings[i].substring(1);
        }*/

        return putOffUnderline(s2);
    }

    public static void main(String[] args) {
        System.out.println(putOffUnderline("tb_test_a"));
    }


}
wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

數據庫連接與獲取表名,與表名對應的列名TableUtils 

package cn.code.util;

import cn.code.module.Column;
import cn.code.module.Table;
import cn.code.util.PropertiesUtils;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class TableUtils {

    private static String DBDRIVER = PropertiesUtils.get("database.properties", "driver");

    private static String DBURL = PropertiesUtils.get("database.properties", "url");

    private static String DBUSER = PropertiesUtils.get("database.properties", "user");

    private static String DBPASS = PropertiesUtils.get("database.properties", "password");

    private static Connection connection;

    private static DatabaseMetaData dbmd;

    static {

        try {
            //連接數據庫
            Class.forName(DBDRIVER);
            connection = DriverManager.getConnection(DBURL, DBUSER, DBPASS);
            //獲取metaData
            dbmd = connection.getMetaData();

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public static List<Table> getTable() {

        List<Table> tableList = new ArrayList<>();
        //獲取數據庫連接
        try {
            //獲取所有表名的結果集
            ResultSet rs = dbmd.getTables(null, null, null, new String[]{"TABLE"});
            //遍歷結果集
            while (rs.next()) {
                Table table = new Table();//tb_test_a -> TbTestA
                String tableName = rs.getString("TABLE_NAME");
                table.setTableName(tableName);
                table.setClassName(StringUtils.captureName(StringUtils.putOffUnderline(tableName)));
                table.setColumns(getColumns(tableName));
                tableList.add(table);

            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return tableList;
    }

    public static List<Column> getColumns(String tableName) {

        List<Column> columnList = new ArrayList<>();

        try {
            ResultSet rs = dbmd.getColumns(null, "%", tableName, "%");
            while (rs.next()) {
                Column column = new Column();
                String columnName = rs.getString("COLUMN_NAME");
                String columnType = rs.getString("TYPE_NAME");
                String remarks = rs.getString("REMARKS");

                column.setColumnName(columnName);
                column.setColumnType(columnType);
                column.setRemarks(remarks);
                column.setFieldName(columnName);
                column.setUpperFieldName(StringUtils.captureName(columnName));
                column.setJavaType(StringUtils.switchType(columnType));

                columnList.add(column);

            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        return columnList;

    }

    public static void main(String[] args) {
        //getTable();
        //getColumns("tb_test_b");

        //測試
        List<Table> tableList = getTable();
        for (Table table: tableList) {
            System.out.println(table.getTableName());
        }


    }
}

freemarker環境初始化

package cn.code;

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

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Generator {

    private Configuration configuration;

    //完成環境初始化
    public void init(String path) throws Exception {

        configuration = new Configuration(freemarker.template.Configuration.getVersion());

        //設置模板所在路徑
        configuration.setDirectoryForTemplateLoading(new File(path));

    }

    public void process(String tempName, String savePath, Map<String, Object> param) throws Exception {

       

        //獲取模板對應實例
        Template template = configuration.getTemplate(tempName);
        //初始化保存路徑
        FileOutputStream stream = new FileOutputStream(savePath);
        OutputStreamWriter outputStreamWriter = new OutputStreamWriter(stream);
        //傳參,生成數據
        template.process(param, outputStreamWriter);

    }

   
}

傳送從數據庫讀取的數據並生成pojo

package cn.code.ssm;

import cn.code.Generator;
import cn.code.module.Table;
import cn.code.util.TableUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ModuleHandler {

    private Generator generator = new Generator();

    private String templatePath = this.getClass().getClassLoader().getResource("").getPath()+"\\module\\";

    private String savePath = "E:\\IdeaProjects\\generator-demo\\src\\main\\java\\cn\\code\\beans";

    public void exectue() throws Exception {

        //獲取table對應的實例
        List<Table> tableList = TableUtils.getTable();
        Map<String,Object> param = new HashMap<>();

        for (Table table:tableList){
            param.put("table",table);
            generator.init(templatePath);
            generator.process("module.ftl",savePath+"\\"+table.getClassName()+".java",param);
        }
    }

    public static void main(String[] args) throws Exception {
        ModuleHandler moduleHandler = new ModuleHandler();
        moduleHandler.exectue();
    }
}

生成的pojo

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章