Java 代码生成工具:如何快速构建项目骨架?
在 Java 项目开发过程中,构建项目骨架是一项繁琐但又基础重要的工作。幸运的是,Java 领域有许多代码生成工具可以帮助我们快速完成这一任务,大大提高开发效率。
一、代码生成工具概述
(一)常用 Java 代码生成工具简介
-
MyBatis Generator
- MyBatis Generator 是专为 MyBatis 框架设计的代码生成工具。它可以根据数据库表结构自动生成对应的 Mapper 接口、XML 映射文件、实体类等代码。例如,当我们有一个 “users” 表,包含 “id”“name”“age” 等字段,使用 MyBatis Generator 可以快速生成 User 实体类,其中包含这些字段以及对应的 getter 和 setter 方法;同时生成 UserMapper 接口,里面会有诸如 insert、delete、update、select 等基本的数据库操作方法声明,以及对应的 UserMapper.xml 文件,用于书写 MyBatis 的映射 SQL 语句。
-
Spring Initializr
- Spring Initializr 是 Spring 官方提供的一个在线项目初始化工具。它可以帮助开发者快速生成基于 Spring Boot 的项目骨架。我们只需要在网页上选择项目的基本信息,如项目名称、版本、依赖(如 Spring Web、Spring Data JPA 等),然后点击生成按钮,就会下载一个完整的项目目录结构,里面包含了构建文件(如 Maven 的 pom.xml 或 Gradle 的 build.gradle)、基础的配置文件(application.properties)、主程序入口类等。
-
FreeMarker(作为代码生成模板引擎)
- FreeMarker 是一个基于模板的生成代码工具。它本身不是专门为 Java 代码生成设计的,但可以结合 Java 程序灵活地用于代码生成场景。例如,我们可以定义一套代码模板,如 Java 服务类的模板,规定好类的结构、方法的格式等。然后通过 Java 程序读取数据库表信息或其他元数据,将这些数据填充到 FreeMarker 模板中,就可以生成对应的 Java 代码文件,如根据表字段生成实体类的字段以及相关的操作方法。
(二)代码生成工具的优势
-
提高开发效率
- 减少了手动编写重复、模式化代码的工作量。例如,对于数据库持久层代码,像实体类、Mapper 接口等,通过代码生成工具可以瞬间生成,而手动编写这些代码可能需要花费较多时间和精力,并且容易出错。
-
保证代码一致性
- 按照统一的模板生成代码,可以确保代码风格、结构和命名规范的一致性。这对于团队开发来说尤为重要,有助于提高代码的可读性和可维护性。
二、使用 MyBatis Generator 构建项目骨架
(一)搭建 MyBatis Generator 环境
- 添加依赖
- 如果我们使用 Maven 构建项目,在项目的 pom.xml 文件中添加 MyBatis Generator 的依赖:
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.4.1</version>
</dependency>
- 配置 MyBatis Generator 配置文件
- 创建一个 generatorConfig.xml 文件,用于配置数据库连接信息、代码生成的目标位置、模板等。示例配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<!-- 数据库连接信息 -->
<context id="DB2Tables" targetRuntime="MyBatis3Simple">
<jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/your_database"
userId="root"
password="password">
</jdbcConnection>
<!-- 生成的实体类等代码的目标位置 -->
<javaModelGenerator targetPackage="com.example.entity" targetProject="src/main/java">
</javaModelGenerator>
<sqlMapGenerator targetPackage="mapper" targetProject="src/main/resources">
</sqlMapGenerator>
<javaClientGenerator type="XMLMAPPER" targetPackage="com.example.mapper" targetProject="src/main/java">
</javaClientGenerator>
<!-- 指定要生成代码的数据库表 -->
<table tableName="users" domainObjectName="User" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false">
</table>
</context>
</generatorConfiguration>
(二)运行 MyBatis Generator 生成代码
- 编写运行代码的 Java 程序
- 创建一个 Java 类,使用 MyBatis Generator 的 API 加载配置文件并生成代码:
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class Generator {
public static void main(String[] args) {
List<String> warnings = new ArrayList<>();
boolean overwrite = true;
File configFile = new File("generatorConfig.xml");
ConfigurationParser cp = new ConfigurationParser(warnings);
Configuration config = null;
try {
config = cp.parseConfiguration(configFile);
DefaultShellCallback callback = new DefaultShellCallback(overwrite);
MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
myBatisGenerator.generate(null);
} catch (Exception e) {
e.printStackTrace();
}
for (String warning : warnings) {
System.out.println(warning);
}
}
}
- 查看生成的代码
- 运行上述 Java 程序后,在指定的目标位置会自动生成 User 实体类、UserMapper 接口和 UserMapper.xml 文件。例如,User 实体类代码如下:
public class User {
private Integer id;
private String name;
private Integer age;
// getter 和 setter 方法
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
三、使用 Spring Initializr 构建项目骨架
(一)在 Spring Initializr 网页端操作
-
访问 Spring Initializr 网址
- 打开浏览器,访问https://start.spring.io/。
-
填写项目基本信息
- 在页面上填写项目的基本信息,如 Group(项目的 Maven GroupId)、Artifact(项目的 Maven ArtifactId,通常为项目名称)、Version(项目版本)、Project Metadata(项目元数据,如名称、描述等)。
- 选择项目使用的构建工具,如 Maven 或 Gradle,以及 Java 版本。
-
添加依赖
- 点击 “Dependencies” 下拉菜单,选择所需的依赖。例如,如果我们是要构建一个 Web 应用,就选择 “Spring Web”;如果是需要操作关系型数据库,就添加 “Spring Data JPA” 以及对应的数据库驱动依赖(如 “MySQL Driver”)。
-
生成项目
- 点击 “Generate” 按钮后,网站会生成一个压缩包。下载并解压后,我们就可以得到一个完整的 Spring Boot 项目骨架。
(二)查看生成的项目结构
- 构建文件
- 对于 Maven 项目,生成的 pom.xml 文件包含了所有选定的依赖。例如,添加了 Spring Web 和 Spring Data JPA 以及 MySQL Driver 依赖后的 pom.xml 部分内容如下:
<?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 https://maven.apache.org/xsd/maven -4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
</project>
- 主程序入口类
- 生成的主程序入口类非常简单,包含一个 main 方法,通过 Spring Boot 的 SpringApplication.run() 方法启动应用。示例代码如下:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
四、使用 FreeMarker 构建项目骨架
(一)引入 FreeMarker 依赖
- Maven 依赖配置
- 在项目的 pom.xml 文件中添加 FreeMarker 的依赖:
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.32</version>
</dependency>
(二)创建代码生成模板
- 定义实体类模板(entity.ftl)
- 例如,以下是一个简单的实体类模板,用于根据表字段生成 Java 实体类代码:
package ${package}.entity;
public class ${className} {
<#list table.columns as column>
// ${column.comments}
private ${column.javaType} ${column.javaField};
public ${column.javaType} get${column.javaCap}() {
return this.${column.javaField};
}
public void set${column.javaCap}(${column.javaType} ${column.javaField}) {
this.${column.javaField} = ${column.javaField};
}
</#list>
}
(三)结合 Java 程序生成代码
-
读取数据库表信息
- 编写 Java 程序,通过 JDBC 或其他数据库访问方式读取数据库表的元数据,包括表名、字段名、字段类型、字段注释等信息。然后将这些信息封装成一个数据模型,用于填充到 FreeMarker 模板中。
-
使用 FreeMarker 生成代码
- 示例代码如下:
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;
public class CodeGenerator {
public static void main(String[] args) {
// 配置 FreeMarker
Configuration cfg = new Configuration(Configuration.VERSION_2_3_32);
try {
// 设置模板文件所在的目录
cfg.setDirectoryForTemplateLoading(new File("templates"));
// 加载模板
Template template = cfg.getTemplate("entity.ftl");
// 创建数据模型
Map<String, Object> dataModel = new HashMap<>();
dataModel.put("package", "com.example");
dataModel.put("className", "User");
dataModel.put("table", getTableInfo());
// 输出代码
Writer out = new FileWriter(new File("src/main/java/com/example/entity/User.java"));
template.process(dataModel, out);
out.close();
} catch (IOException | TemplateException e) {
e.printStackTrace();
}
}
// 模拟获取表信息的方法
public static Table getTableInfo() {
Table table = new Table();
table.setName("users");
// 添加字段信息
Column column1 = new Column();
column1.setName("id");
column1.setJavaType("Integer");
column1.setJavaField("id");
column1.setJavaCap("Id");
column1.setComments("用户 ID");
Column column2 = new Column();
column2.setName("name");
column2.setJavaType("String");
column2.setJavaField("name");
column2.setJavaCap("Name");
column2.setComments("用户名字");
Column column3 = new Column();
column3.setName("age");
column3.setJavaType("Integer");
column3.setJavaField("age");
column3.setJavaCap("Age");
column3.setComments("用户年龄");
table.setColumns(new Column[]{column1, column2, column3});
return table;
}
// Table 类用于封装表信息
public static class Table {
private String name;
private Column[] columns;
// getter 和 setter 方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Column[] getColumns() {
return columns;
}
public void setColumns(Column[] columns) {
this.columns = columns;
}
}
// Column 类用于封装字段信息
public static class Column {
private String name;
private String javaType;
private String javaField;
private String javaCap;
private String comments;
// getter 和 setter 方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getJavaType() {
return javaType;
}
public void setJavaType(String javaType) {
this.javaType = javaType;
}
public String getJavaField() {
return javaField;
}
public void setJavaField(String javaField) {
this.javaField = javaField;
}
public String getJavaCap() {
return javaCap;
}
public void setJavaCap(String javaCap) {
this.javaCap = javaCap;
}
public String getComments() {
return comments;
}
public void setComments(String comments) {
this.comments = comments;
}
}
}
通过这种方式,就可以根据数据库表结构生成相应的 Java 实体类代码,如根据上述代码生成的 User 实体类代码如下:
package com.example.entity;
public class User {
// 用户 ID
private Integer id;
// 用户名字
private String name;
// 用户年龄
private Integer age;
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return this.age;
}
public void setAge(Integer age) {
this.age = age;
}
}
五、对比不同代码生成工具
(一)功能对比
-
MyBatis Generator
- 主要针对 MyBatis 持久层框架,功能聚焦在根据数据库表生成 MyBatis 相关的代码,如实体类、Mapper 接口、XML 映射文件等,对于非 MyBatis 项目或不涉及数据库操作的代码生成支持有限。
-
Spring Initializr
- 主要用于快速生成 Spring Boot 项目的初始骨架,侧重于项目的整体搭建,包括构建文件、主程序入口类等,但对于项目内部具体的业务代码(如实体类、服务类等)生成能力较弱,需要开发者进一步手动编码。
-
FreeMarker(结合 Java 程序)
- 具有高度灵活性,可以根据需求自定义模板,生成各种类型的代码。不仅可以生成 Java 代码,还可以生成配置文件、HTML 页面等。但需要开发者自己编写读取元数据(如数据库表信息)的代码以及处理模板的逻辑,相对来说开发成本较高。
(二)易用性对比
-
MyBatis Generator
- 对于熟悉 MyBatis 和数据库操作的开发者来说,配置和使用相对简单。只需要编写一个配置文件,通过简单的运行就可以生成代码。但需要一定的 XML 配置知识来设置代码生成的各种细节。
-
Spring Initializr
- 提供了非常友好的网页界面,即使是初学者也可以轻松上手。只需要填写项目基本信息和选择依赖,点击生成按钮即可得到项目骨架。在本地使用时,也有对应的 Maven 和 Gradle 插件,方便集成到开发环境中。
-
FreeMarker(结合 Java 程序)
- 使用起来相对较复杂。需要先学习 FreeMarker 的模板语法,同时还要开发配套的 Java 程序来读取数据和处理模板。不过,一旦掌握了基本原理和开发模式,就可以灵活地用于各种代码生成场景。
六、总结与展望
Java 代码生成工具为我们快速构建项目骨架提供了极大的便利。MyBatis Generator 在持久层代码生成方面表现出色;Spring Initializr 是搭建 Spring Boot 项目的利器;FreeMarker 则提供了灵活自定义的代码生成方式。在实际项目开发中,我们可以根据项目的技术选型和具体需求,选择合适的代码生成工具,或者结合多种工具来高效地完成项目骨架的构建。随着技术的不断发展,未来的代码生成工具可能会更加智能化、自动化,能够更好地理解业务逻辑,生成更加高质量和贴合实际需求的代码,进一步提升软件开发的效率和质量。