Java Web 模板程式碼生成器的設計與實現

tedhacker.top發表於2017-03-15

起因

專案中需要根據資料庫表寫很多Meta、Dao、Service程式碼,其中很多程式碼都是重複而繁瑣的。因此如果有一個模板程式碼的生成器,就可以一定程度提高開發效率。

目標

可配置生成Java Web專案中Dao、Meta、Service層模板程式碼的生成器。

程式碼框架

mvn archetype:generate -DgroupId=com.zju -DartifactId=JavaWebCodeGenerator -DarchetypeArtifactId=maven-archetype-webapp -DinteractiveMode=false -DarchetypeCatalog=internal

設計思路

專案參考Mybatis generator生成程式碼的過程,具體步驟分為以下5步。

邏輯步驟

  1. 解析命令列
  2. 解析配置檔案
  3. 獲取資料表資訊
  4. 生成配置資訊
  5. 生成檔案

程式碼設計

命令解析類 ShellRunner

該類負責解析命令列的命令,解析配置檔案並封裝所需的資料給程式碼生成類。

可解析命令有-configfile:指定配置檔案所在路徑和-overwrite:是否重寫目標檔案。

配置檔案的配置項有:

//Java SQL 驅動所在路徑(暫未使用)
private static final String CLASS_PATH_ENTRY = "class.path.entry";
//Java 驅動型別(暫未使用)
private static final String DRIVER_CLASS = "driver.class";
//資料庫地址
private static final String CONNECTION_URL = "connection.url";
//資料庫使用者名稱
private static final String USER_ID = "user.id";
//資料庫密碼
private static final String USER_PASSWORD = "user.password";
//模型生成地址
private static final String JAVA_MODEL_PACKAGE = "java.model.package";
//SQL生成地址
private static final String SQL_MAPPING_PACKAGE = "sql.mapping.package";
//專案地址
private static final String PROJECT = "project";
//資料表名
private static final String TABLE_NAME = "table.name";
//模型名稱
private static final String DOMAIN_OBJECT_NAME = "domain.object.name";

程式碼生成類 CodeGenerator

該類負責連線資料庫,查詢資料表的表資訊,將SQL型別對映成Java型別並封裝所需的資料給檔案生成類。

Class.forName(configuration.getDriverClass());
//獲取資料庫連線
Connection connection = DriverManager.getConnection(configuration.getConnectionURL(), configuration.getUserId(), configuration.getPassword());
DatabaseMetaData databaseMetaData = connection.getMetaData();
//獲取表結構資訊
ResultSet rs = databaseMetaData.getColumns("", "", configuration.getTableName(), "%");

通過以上幾行程式碼,rs變數中已經獲得目標資料表的表資訊。

databaseMetaData.getColumns方法的實質是執行了SELECT * FROM information_schema.COLUMNS WHERE TABLE_NAME="tableName"語句。

在結果集中,後續處理大致需要以下表資訊列。

欄位 描述
DATA_TYPE 資料型別
COLUMN_SIZE 資料長度
COLUMN_NANE 列名
NULLABLE 是否允許非空
DECIMAL_DIGITS 小數位數
REMARKS 備註
COLUMN_DEF 預設值

最後通過JavaTypeResolver中的型別對映(Map<Integer, JdbcTypeInformation> typeMap)和StringUtils中的駝峰命名轉換(getCamelCaseString)將SQL資訊轉換成Java資訊。

檔案生成類 FileGenerator

該類通過FreeMarker模板引擎組合資料成目的碼檔案。

主邏輯如下:

/**
* @param configuration 封裝的配置資訊
* @param columns       封裝的資料表列資訊
* @throws IOException
* @throws TemplateException
*/
public static void writeFile(Configuration configuration, List<TableColumn> columns) throws IOException, TemplateException {
    File r=new File("");
    //測試環境獲取專案根目錄路徑
    //String path=Class.class.getClass().getResource("/").getPath();
    //Jar包獲取根目錄路徑
    String path=r.getAbsolutePath();
    //System.out.println("path:"+path);
    Configuration cfg = new Configuration();
    cfg.setDirectoryForTemplateLoading(new File(path + "/ftl")); //需要資料夾絕對路徑
    cfg.setDefaultEncoding("UTF-8");
    cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
    Map root = new HashMap();
    root.put("configuration", configuration);
    root.put("columnList", columns);
    writeSingleFile(cfg, root, "DaoImpl.ftl", configuration.getProjectPath(), configuration.getSqlMappingPackage().replace(".", "/"), configuration.getDomainObjectName(), "DaoImpl.java",configuration.getOverwrite());
    writeSingleFile(cfg, root, "Dao.ftl", configuration.getProjectPath(), configuration.getSqlMappingPackage().replace(".", "/"), configuration.getDomainObjectName(), "Dao.java",configuration.getOverwrite());
    writeSingleFile(cfg, root, "Meta.ftl", configuration.getProjectPath(), configuration.getJavaModelPackage().replace(".", "/"), configuration.getDomainObjectName(), ".java",configuration.getOverwrite());
}

注意

在測試中,Class.class.getClass().getResource("/").getPath();該方法可以獲取專案根目錄,但是在測試生成的Jar包時,該方法時效。因此在生成Jar包前需要把該行修改成new File("").getAbsolutePath();獲取生成路徑。

專案結構

專案結構

配置檔案範例

generatorConfig.properties

class.path.entry=src/test/resources/mysql-connector-java-5.1.38.jar
driver.class=com.mysql.jdbc.Driver
connection.url=jdbc:mysql://localhost:3307/work
user.id=
user.password=
java.model.package=com.model
sql.mapping.package=com.dao
project=src
table.name=holiday
domain.object.name=Holiday

執行命令範例

java -jar JavaWebCodeGenerator.jar -configfile generatorConfig.properties -overwrite

例項演示

例項演示

原始碼

https://github.com/TedHacker/PracticeArea/tree/master/JavaWebCodeGenerator

相關文章