12.30 java實現代碼自動生成工具,基於spring boot

前言:

此項目主要解決在項目搭建初期,創建項目時很多代碼手動創建太過繁瑣,耗費不必要的開發時間。通過此代碼生成工具可以自動生成相關代碼,當然不侷限於controller層、service層、entity層、mapper層的代碼生成!因為本項目中自定義代碼生成規則的配置比較簡單,只需自定義模板並創建工廠實例即可。同時可自定義代碼的生成路徑,未設置則默認生成在本項目下(可更直觀查看生成的結構效果,文末有效果圖)。

項目結構

java實現代碼自動生成工具,基於spring boot

一: 導入pom文件相關依賴

<dependency>

<groupid>org.springframework.boot/<groupid>

<artifactid>spring-boot-starter/<artifactid>

<dependency>

<groupid>org.projectlombok/<groupid>

<artifactid>lombok/<artifactid>

<optional>true/<optional>

<dependency>

<groupid>org.springframework.boot/<groupid>

<artifactid>spring-boot-starter-test/<artifactid>

<scope>test/<scope>

<dependency>

<groupid>org.mybatis.spring.boot/<groupid>

<artifactid>mybatis-spring-boot-starter/<artifactid>

<version>1.3.2/<version>

<dependency>

<groupid>com.ibeetl/<groupid>

<artifactid>beetl-framework-starter/<artifactid>

<version>1.1.68.RELEASE/<version>

<dependency>

<groupid>org.antlr/<groupid>

<artifactid>antlr4-runtime/<artifactid>

<version>4.7.1/<version>

<dependency>

<groupid>mysql/<groupid>

<artifactid>mysql-connector-java/<artifactid>

<dependency>

<groupid>org.springframework.boot/<groupid>

<artifactid>spring-boot-starter-web/<artifactid>

二: 編寫beetl配置類

/**

* @author: brbai

* @create: 2019-10-16 17:12:45

* @description:

*/

@Configuration

@Slf4j

@Data

public class BeetlConfiguration {

@Value("${beetl.template-path}")

private String templatePath;

@Value("${beetl.delimiter-statement-start}")

private String delimiterStatementStart;

@Value("${beetl.delimiter-statement-end}")

private String delimiterStatementEnd;

@Bean(name = "beetlConfig")

public BeetlGroupUtilConfiguration beetlGroupUtilConfiguration() {

BeetlGroupUtilConfiguration beetlGroupUtilConfiguration = new BeetlGroupUtilConfiguration();

// Beetl的配置

Properties properties = new Properties();

properties.setProperty("statementStart",delimiterStatementStart);

properties.setProperty("statementEnd",delimiterStatementEnd);

properties.setProperty("DELIMITER_STATEMENT_START", delimiterStatementStart);

properties.setProperty("DELIMITER_STATEMENT_END", delimiterStatementEnd);

beetlGroupUtilConfiguration.setConfigProperties(properties);

ClasspathResourceLoader resourceLoader = new ClasspathResourceLoader(templatePath);

beetlGroupUtilConfiguration.setResourceLoader(resourceLoader);

// 調用Beetl的初始化方法

beetlGroupUtilConfiguration.init();

return beetlGroupUtilConfiguration;

}

}

三: 配置properties文件

application.properties文件:

server.port=8090

server.servlet.context-path=/

spring.datasource.url=jdbc:mysql://localhost:3306/building_materials?useUnicode=true&characterEncoding=UTF-8&nullCatalogMeansCurrent=true&tinyInt1isBit=false

spring.datasource.username=root

spring.datasource.password=bhy702

# beetl模板引擎的加載路徑。以resources為根路徑,此時表示加載resources/template文件夾中的模板文件

beetl.template-path = template

# beetl模板引擎語法開始標記

beetl.delimiter-statement-start = @

# beetl模板引擎語法結束標記。為空時在有開始標記@的行末結束

beetl.delimiter-statement-end =

# 代碼文件的保存路徑,註釋後默認保存在本項目中

#project.base-path = F:\\\\360MoveData\\\\Users\\\\n551\\\\Desktop

為了便於查看代碼生成效果,默認代碼生成在此項目內,同時提供自定義代碼生成位置。自定義代碼生成位置只需配置application.properties中的project.base-path

四: 設計代碼模板(代碼模板沒限制,想怎麼設計都行)

下面以Entity.tpl代碼模板文件為例:

package ${props.params.packageName};

import lombok.Data;

@for(column in props.columnList){

@if(column.type=='Date'){

import java.util.Date;

@break;

@}}

\\@Data

public class ${props.className}{

@for(column in props.columnList){

private ${column.type} ${column.lowerPropertyName};

@}

}

五: 根據代碼模板確定所需參數數據,添加代碼模板的工廠實例。

為了便於開發,我封裝了一個模板所需的參數類TplProperties

TplProperties參數類:

/**

* @author: brbai

* @create: 2019-12-26 11:13:42

* @description: 模板參數

*/

@Data

public class TplProperties {

private String basePath;

private String rootPackage;

private String tableName;

private List<column> columnList;/<column>

private Map<string> params = new HashMap();;/<string>

/**

* 表名格式轉換

* xxx_yyy->XxxYyy

*/

private String className;

/**

* 表名格式轉換

* xxx_yyy->xxxYyy

*/

private String propertyName;

public TplProperties(String basePath, String rootPackage, String tableName, List<column> columnList) {/<column>

this.basePath = basePath;

this.rootPackage = rootPackage;

this.tableName = tableName;

this.columnList = columnList;

}

public TplProperties(String rootPackage, String tableName, List<column> columnList) {/<column>

this.rootPackage = rootPackage;

this.tableName = tableName;

this.columnList = columnList;

}

public String getClassName() {

return StringUtil.mapTableNameToClassName(tableName);

}

public String getPropertyName() {

return StringUtil.mapTableNameToPropertyName(tableName);

}

public void setParam(String key,Object value) {

this.params.put(key,value);

}

public String getBasePath() {

if(basePath == null){

//未在properties文件中設置代碼生成路徑時,代碼默認生成在此項目下

return System.getProperty("user.dir") + "/src";

}

return basePath;

}

}

工廠實例:

/**

* @author: brbai

* @create: 2019-12-14 19:12:59

* @description:

*/

public class Entity implements Code {

@Override

public void create(GroupTemplate gt, TplProperties properties, String tplPath) throws IOException {

String packageName = properties.getRootPackage()+ ".entity";

properties.setParam("packageName",packageName);

Template t = gt.getTemplate(tplPath);

t.binding("props", properties);

GenerateUtil.createFile(t,properties.getBasePath()+"/main/java/"

+ packageName.replace(".", "/") + "/" + properties.getClassName() + ".java");

}

}

六: 識別數據庫類型,讀取數據庫表結構

/**

* @Description: 獲取數據庫表結構

* @Param: [sqlSessionFactory]

* @return: java.util.Map<java.lang.string>>/<java.lang.string>

*/

public static Map<string>> getDatabaseAttribute(SqlSession sqlSession) throws SQLException {/<string>

Map<string>> databaseAttribute = new HashMap<>();/<string>

Connection connection = sqlSession.getConnection();

//獲得數據庫信息

DatabaseMetaData metaData = connection.getMetaData();

String databaseName = metaData.getDatabaseProductName();

if ("MySQL".equals(databaseName)) {

//獲得數據庫表

ResultSet resultSet = metaData.getTables(null, null, null, new String[]{"TABLE"});

while (resultSet.next()) {

String tableName = resultSet.getString(3);

String sql = "SELECT * FROM " + tableName;

PreparedStatement preparedStatement = connection.prepareStatement(sql);

ResultSet set = preparedStatement.executeQuery();

//獲得表信息

ResultSetMetaData md = set.getMetaData();

//獲得表字段數

int columnCount = md.getColumnCount();

Map<string> attributes = new LinkedHashMap<>();/<string>

for (int i = 1; i <= columnCount; i++) {

//字段名

String columnName = md.getColumnName(i);

//字段屬性

String columnType = md.getColumnTypeName(i);

attributes.put(columnName, columnType);

}

databaseAttribute.put(tableName,attributes);

}

}else if("Oracle".equals(databaseName)){

//DEVTEST是oracle的用戶名。此Oracle代碼還沒怎麼測試。

ResultSet rs = metaData.getTables("null", "DEVTEST", "%", new String[]{"TABLE"});

while (rs.next()) {

String tableName = rs.getString("TABLE_NAME");

ResultSet columns = metaData

.getColumns(null, "DEVTEST", tableName, "%");

Map<string> attributes = new LinkedHashMap<>();/<string>

while (columns.next()) {

attributes.put(columns.getString("COLUMN_NAME"), columns.getString("TYPE_NAME"));

}

databaseAttribute.put(tableName, attributes);

}

}

return databaseAttribute;

}

七: 數據清洗,設置生成代碼的包名,獲取工廠實例生成代碼文件

/**

* @author: brbai

* @create: 2019-11-20 14:12:12

* @description: test

*/

@RunWith(SpringRunner.class)

@SpringBootTest

public class CodeTest {

@Autowired

private SqlSessionFactory sqlSessionFactory;

@Autowired

private BeetlGroupUtilConfiguration beetlConfig;

@Autowired

private CodeFactory codeFactory;

@Value("${project.base-path:#{null}}")

private String basePath;

@Test

public void codeGeneratorTest() throws SQLException{

//生成代碼的項目包名

String rootPackage = "aaa.bbb.ccc";

GroupTemplate gt = beetlConfig.getGroupTemplate();

//獲取數據庫表結構

SqlSession sqlSession = sqlSessionFactory.openSession();

Map<string>> databaseAttribute = DBUtil.getDatabaseAttribute(sqlSession);/<string>

String databaseName = sqlSession.getConnection().getMetaData().getDatabaseProductName();

databaseAttribute.forEach((tableName,columnMap)->{

List<column> columnList = new ArrayList<>();/<column>

columnMap.forEach((name,type)->{

String javaType = null;

//數據庫行字段類型以及字段名格式轉換,並存入模板參數集合

if("MySQL".equals(databaseName)){

javaType = DBUtil.sqlTypeToJavaType(type);

}else if("Oracle".equals(databaseName)){

javaType = DBUtil.oracleSqlTypeToJavaType(type);

}

columnList.add(new Column(name, javaType, StringUtil.mapUnderscoreToCamelCase(name), StringUtil.mapTableNameToClassName(name)));

});

//構建參數

TplProperties properties = null;

if(basePath != null){

properties = new TplProperties(basePath,rootPackage,tableName,columnList);

}else{

properties = new TplProperties(rootPackage,tableName,columnList);

}

try {

//代碼生成

codeFactory.getCodeInstance("CONTROLLER").create(gt,properties,"/Controller.tpl");

codeFactory.getCodeInstance("SERVICE").create(gt,properties,"/Service.tpl");

codeFactory.getCodeInstance("ENTITY").create(gt,properties,"/Entity.tpl");

codeFactory.getCodeInstance("MAPPER").create(gt,properties,"/Mapper.tpl");

codeFactory.getCodeInstance("MAPPER_XML").create(gt,properties,"/MapperXml.tpl");

} catch (IOException e) {

e.printStackTrace();

}

});

}

}

運行codeGeneratorTest()方法

效果圖如下:

java實現代碼自動生成工具,基於spring boot

未配置代碼生成路徑時:

java實現代碼自動生成工具,基於spring boot

配置了代碼生成路徑時:

java實現代碼自動生成工具,基於spring boot



分享到:


相關文章: