代码生成器原理分析

代码生成器原理分析

理解代码生成器的需求和实现思路掌握freemaker的使用

理解数据库中的元数据完成环境搭建工作

浅谈代码生成器

概述

在项目开发过程中,关注点更多是在业务功能的开发及保证业务流程的正确性上,对于重复性的代码编写占据了程 序员大量的时间和精力,而这些代码往往都是具有规律的。就如controller、service、serviceImpl、dao、daoImpl、model、jsp的结构,用户、角色、权限等等模块都有类似的结构。针对这部分代码,就可以使用代码生 成器,让计算机自动帮我们生成代码,将我们的双手解脱出来,减小了手工的重复劳动。

传统的方式程序员进行模块开发步骤如下:

  • 创建数据库表
  • 根据表字段设计实体类
  • 编写增删改查dao
  • 根据业务写service层
  • web层代码和前台页面

通常只需要知道了一个表的结构,增删改查的前后台页面的代码格式就是固定的,剩下的就是复杂的业务。而代码 生成工具的目标就是自动生成那部分固定格式的增删改查的代码

需求分析

再我们的代码生成器中就是根据公共的模板和数据库表中的信息自动的生成代码。

对于不借助代码生成工具的开发,程序员通常都是以一份已经写好的代码为基础进行代码Copy和修改,根据 不同业务数据库表完善需求,可以将这份代码称之为公共的代码模板。

生成的代码和数据库表中信息息息相关,所以除了模板之外还需要数据库表信息作为数据填充模板内容

实现思路

代码生成器的实现有很多种,我们以从mysql数据库表结构生成对应代码为例来说明如何实现一个代码生成器。有 以下几个重点:

  • 数据库和表解析,用于生成model及其他代码

通过数据库解析获取数据库中表的名称、表字段等属性:可以根据表名称确定实体类名称,根据字段确定实 体类中属性(如:tb_user表对应的实体类就是User)

  • 模板开发生成代码文件

模板中定义公共的基础代码和需要替换的占位符内容(如:${tableName}最终会根据数据库表替换为User), 根据解析好的数据库信息进行数据替换并生成代码文件

  • 基础框架的模板代码抽取

通过思路分析不难发现,对于代码生成工具而言只需要搞定数据库解析和模板开发。那么代码自动生成也并没有那么神秘和复杂。那接下来完成属于自己的代码生成器。

骚戴理解:代码生成器主要就是两部分,元数据+模板,元数据通常指的是数据库的表名,字段等,模板就是一些公共的代码需要一个模板,然后把元数据替换到模板里面即可生成代码

深入FreeMarker

什么是FreeMarker

FreeMarker 是一款模板引擎:一种基于模板的、用来生成输出文本(任何来自于 HTML格式的文本用来自动生成源代码)的通用工具。它是为 Java 程序员提供的一个开发包或者说是类库。它不是面向最终用户,而是为程序员提供的可以嵌入他们开发产品的一款应用程序。

FreeMarker 的设计实际上是被用来生成 HTML 网页,尤其是通过基于实现了 MVC(ModelView Controller,模型- 视图-控制器)模式的 Servlet 应用程序。使用 MVC 模式的动态网页的构思使得你可以将前端设计者(编写 HTML)从程序员中分离出来。所有人各司其职,发挥其擅长的一面。网页设计师可以改写页面的显示效果而不受程序员编译 代码的影响,因为应用程序的逻辑( Java 程序)和页面设计(FreeMarker 模板)已经分开了。页面模板代码不会受到复杂的程序代码影响。这种分离的思想即便对一个程序员和页面设计师是同一个人的项目来说都是非常有用的,因为 分离使得代码保持简洁而且便于维护。

尽管 FreeMarker 也有编程能力,但它也不是像 PHP 那样的一种全面的编程语言。反而,Java 程序准备的数据来显示(比如 SQL 查询),FreeMarker 仅仅使用模板生成文本页面来呈现已经准备好的数据

FreeMarker 不是 Web 应用框架。它是 Web 应用框架中的一个适用的组件,但是FreeMarker 引擎本身并不知道HTTP 协议或 Servlet。它仅仅来生成文本。即便这样,它也非常适用于非 Web 应用环境的开发

Freemarker的应用场景

动态页面

基于模板配置和表达式生成页面文件,可以像jsp一样被客户端访问

页面静态化

对于系统中频繁使用数据库进行查询但是内容更新很小的应用,都可以用FreeMarker将网页静态化,这样就避免 了大量的数据库访问请求,从而提高网站的性能

代码生成器

可以自动根据后台配置生成页面或者代码

freemarker的特征与亮点

  • 强大的模板语言:有条件的块,迭代,赋值,字符串和算术运算和格式化,宏和函数,编码等更多的功能;
  • 多用途且轻量:零依赖,输出任何格式,可以从任何地方加载模板(可插拔),配置选项丰富;
  • 智能的国际化和本地化:对区域设置和日期/时间格式敏感。
  • XML处理功能:将dom-s放入到XML数据模型并遍历它们,甚至处理他们的声明
  • 通用的数据模型:通过可插拔适配器将java对象暴露于模板作为变量树。

Freemarker的基本使用

构造环境

创建maven工程codeutil,并引入响应坐标

    <dependencies>
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.20</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>
    </dependencies>

入门案例

  • 创建模板template.ftl

欢迎您:${username}

  • 使用freemarker完成操作
package cn.itcast.freemarker.test;

import freemarker.cache.FileTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.junit.Test;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 第一个FreeMarker程序(数据+模板=文件输出)
 *      1.操作步骤
 */
public class FreeMarkerTest01 {

    @Test
    public void test01() throws Exception {
        //1.创建FreeMarker的配置类
        Configuration cfg = new Configuration();
        //2.指定模板加载器:将模板存入缓存中
        //文件路径加载器
        FileTemplateLoader ftl = new FileTemplateLoader(new File("templates"));
        cfg.setTemplateLoader(ftl);
        //3.获取模板
        Template template = cfg.getTemplate("template01.ftl");
        //4.构造数据模型
        Map<String,Object> dataModel = new HashMap<>();

        //

        //user对象
        dataModel.put("username","ZHangsan");
        dataModel.put("flag",3);

        List<String> list = new ArrayList<>();
        list.add("星期一");
        list.add("星期二");
        list.add("星期三");
        list.add("星期四");

        dataModel.put("weeks",list);

        //5.文件输出
        /**
         * 处理模型
         *      参数一:数据模型
         *      参数二:writer(FileWriter(文件输出),printWriter(控制台输出))
         */
        //template.process(dataModel,new FileWriter(new File("C:\\Users\\ThinkPad\\Desktop\\ihrm\\day12\\test\\a.txt")));
        template.process(dataModel,new PrintWriter(System.out));
    }
}

骚戴理解: FileTemplateLoader ftl = new FileTemplateLoader(new File("templates"));这是指的从项目代码里的templates文件下获取所有文件进行加载,例如这里的template.ftl就是在templates文件下, cfg.setTemplateLoader(ftl);是设置模板加载器,模板加载器有很多种,以下是FreeMarker中可用的模板加载器及其含义:

1. FileTemplateLoader:从文件系统中加载模板。需要指定模板文件所在的目录。

2. ClassTemplateLoader:从类路径中加载模板。需要指定模板文件所在的包名。

3. ServletContextTemplateLoader:从Web应用程序的上下文中加载模板。需要指定模板文件所在的相对路径。

4. StringTemplateLoader:从字符串中加载模板。可以将模板内容直接传递给模板加载器。

5. MultiTemplateLoader:可以将多个模板加载器组合在一起,以便从多个来源加载模板。

6. TemplateLoader:这是一个抽象类,可以通过继承它来实现自定义的模板加载器。

字符串模板

package cn.itcast.freemarker.test;

import freemarker.cache.StringTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.junit.Test;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringReader;
import java.util.HashMap;
import java.util.Map;

/**
 * 测试字符串模板
 *
 *
 */
public class FreeMarkerTest02 {

    /**
     *  com.${p1}.${p1}.${p1}.User
     *
     */
    @Test
    public void test() throws Exception {
        //1.创建配置对象
        Configuration cfg = new Configuration();
        //2.指定加载器
        cfg.setTemplateLoader(new StringTemplateLoader());
        //3.创建字符串模板
        // i.字符串
        String templateString = "欢迎您:${username}";
        // ii.通过字符串创建模板
        Template template = new Template("name1",new StringReader(templateString),cfg);
        //4.构造数据
        Map<String,Object> dataModel = new HashMap<>();
        dataModel.put("username","张三");
        //5.处理模板
        template.process(dataModel,new PrintWriter(System.out));
    }
}

骚戴理解: Template template = new Template("name1",new StringReader(templateString),cfg);的三个参数的含义分别是:

  • "name1" - 模板的名称,通常用于调试和错误报告。名称是可选的,因此它也可以是null。
  • new StringReader(templateString) - 这是一个StringReader对象,用于将模板字符串传递给FreeMarker引擎。 StringReader提供用于逐字符读取字符串的read()方法。
  • cfg - 配置对象,通常是Configuration类的实例。它提供了FreeMarker引擎的各种设置和选项,包括模板缓存、编码、指令语法等。

Freemarker模板

概述

FreeMarker模板文件主要有5个部分组成:

  • 数据模型:模板能用的所有数据
  • 文本,直接输出的部分
  • 注释,即<#--...-->格式不会输出
  • 插值(Interpolation):即${..}或者#{..}格式的部分,将使用数据模型中的部分替代输出
  • FTL指令:FreeMarker指令,和HTML标记类似,名字前加#予以区分,不会输出。

数据模型

FreeMarker(还有模板开发者)并不关心数据是如何计算的,FreeMarker 只是知道真实的数据是什么。模板能用的所有数据被包装成 data-model 数据模型

骚戴理解:例如${user}可以取得root中key为user的value。${lastestProduct.url}可以取得成员变量为lastestProduct的url属性

模板的常用标签

在FreeMarker模板中可以包括下面几个特定部分:

1. ${…}:称为interpolations,FreeMarker会在输出时用实际值进行替代。

    • ${name}可以取得root中key为name的value。
    • ${person.name}可以取得成员变量为person的name属性

2. <#…>:FTL标记(FreeMarker模板语言标记):类似于HTML标记,为了与HTML标记区分

3. <@>:宏,自定义标签

4. 注释:包含在<#--和-->(而不是)之间

模板的常用指令

if指令

分支控制语句

<#if 条件>
    ....
    <#elseif 条件>
        ...
    <#elseif 条件>      
        ...
    <#else>
        ...
</#if>

举个栗子

<#if flag=1>
    传入数据=1
    <#elseif flag=2>
    传入数据=2
    <#else>
    传入数据=其他
</#if>
package cn.itcast.freemarker.test;

import freemarker.cache.FileTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.junit.Test;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 第一个FreeMarker程序(数据+模板=文件输出)
 *      1.操作步骤
 */
public class FreeMarkerTest01 {

    @Test
    public void test01() throws Exception {
        //1.创建FreeMarker的配置类
        Configuration cfg = new Configuration();
        //2.指定模板加载器:将模板存入缓存中
        //文件路径加载器
        FileTemplateLoader ftl = new FileTemplateLoader(new File("templates"));
        cfg.setTemplateLoader(ftl);
        //3.获取模板
        Template template = cfg.getTemplate("template01.ftl");
        //4.构造数据模型
        Map<String,Object> dataModel = new HashMap<>();

        //

        //user对象
        dataModel.put("flag",3);

        //5.文件输出
        /**
         * 处理模型
         *      参数一:数据模型
         *      参数二:writer(FileWriter(文件输出),printWriter(控制台输出))
         */
        //template.process(dataModel,new FileWriter(new File("C:\\Users\\ThinkPad\\Desktop\\ihrm\\day12\\test\\a.txt")));
        template.process(dataModel,new PrintWriter(System.out));
    }
}

list、break指令

list指令时一个典型的迭代输出指令,用于迭代输出数据模型中的集合

<#list weeks as abc>
    ${abc_index} =  ${abc}
</#list>
package cn.itcast.freemarker.test;

import freemarker.cache.FileTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.junit.Test;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 第一个FreeMarker程序(数据+模板=文件输出)
 *      1.操作步骤
 */
public class FreeMarkerTest01 {

    @Test
    public void test01() throws Exception {
        //1.创建FreeMarker的配置类
        Configuration cfg = new Configuration();
        //2.指定模板加载器:将模板存入缓存中
        //文件路径加载器
        FileTemplateLoader ftl = new FileTemplateLoader(new File("templates"));
        cfg.setTemplateLoader(ftl);
        //3.获取模板
        Template template = cfg.getTemplate("template01.ftl");
        //4.构造数据模型
        Map<String,Object> dataModel = new HashMap<>();

        //

        //user对象
        dataModel.put("username","ZHangsan");
        dataModel.put("flag",3);

        List<String> list = new ArrayList<>();
        list.add("星期一");
        list.add("星期二");
        list.add("星期三");
        list.add("星期四");

        dataModel.put("weeks",list);

        //5.文件输出
        /**
         * 处理模型
         *      参数一:数据模型
         *      参数二:writer(FileWriter(文件输出),printWriter(控制台输出))
         */
        //template.process(dataModel,new FileWriter(new File("C:\\Users\\ThinkPad\\Desktop\\ihrm\\day12\\test\\a.txt")));
        template.process(dataModel,new PrintWriter(System.out));
    }
}

除此之外,迭代集合对象时,还包括两个特殊的循环变量:item是指的别名

a、item_index:当前变量的索引值。

b、item_has_next:是否存在下一个对象

也可以使用<#break>指令跳出迭代

<#list ["星期一","星期二","星期三","星期四","星期五"] as x>
    ${x_index +1}.${x} <#if x_has_next>,</#if>
    <#if x = "星期四"><#break></#if>
</#list>

骚戴理解:注意x_index下标是从0开始的!所以执行结果是

1.星期一, 2.星期二, 3.星期三, 4.星期四

include 指令

include指令的作用类似于JSP的包含指令,用于包含指定页,include指令的语法格式如下

<#include filename [options]></#include>

举个栗子
<#--模板包含 include-->
<#include "template02.ftl" >

在上面的语法格式中,两个参数的解释如下

a、filename:该参数指定被包含的模板文件

b、options:该参数可以省略,指定包含时的选项,包含encoding和parse两个选项,encoding指定包含页面时所使用的解码集,而parse指定被包含是否作为FTL文件来解析。如果省略了parse选项值,则该选项值默认是true

assign指令

它用于为该模板页面创建或替换一个顶层变量

<#-- assign指令 : 再ftl模板中定义数据存入到root节点下-->
<#assign name="zhangsan">

${name}

骚戴理解:assign指令其实就是定义一个变量,然后可以直接在ftl文件里直接用这个变量,例如上面定义的变量name=zhangsan,下面就可以直接用${name}

内置函数

FreeMarker还提供了一些内建函数来转换输出,可以在任何变量后紧跟?,?后紧跟内建函数,就可通过内建函数来转换输出变量。下面是常用的内建的字符串函数:

 ?html:html字符转义
 ?cap_first: 字符串的第一个字母变为大写形式
 ?lower_case :字符串的小写形式
 ?upper_case :字符串的大写形式
 ?trim:去掉字符串首尾的空格
 ?substring:截字符串
 ?lenth: 取长度
 ?size: 序列中元素的个数
 ?int : 数字的整数部分(比如- 1.9?int 就是- 1)
 ?replace:字符串替换

举个栗子

${username?lower_case}

骚戴理解:使用方法就是在直接添加?lower_case,他就会把java代码传入的username都变成小写,例如Zhan就会变成zhan

数据库之元数据

数据库中的元数据

什么是数据元数据?

元数据(MetaData),是指定义数据结构的数据。那么数据库元数据就是指定义数据库各类对象结构的数据。 例如数据库中的数据库名,表明, 列名、用户名、版本名以及从SQL语句得到的结果中的大部分字符串是元数据

数据库元数据的作用

在应用设计时能够充分地利用数据库元数据

深入理解了数据库组织结构,再去理解数据访问相关框架的实现原理会更加容易。

如何获取元数据

在我们前面使用JDBC来处理数据库的接口主要有三个,即Connection,PreparedStatement和ResultSet这三个,而对于这三个接口,还可以获取不同类型的元数据,通过这些元数据类获得一些数据库的信息。下面将对这三种类型的元数据对象进行各自的介绍并通过使用MYSQL数据库进行案例说明

数据库元数据

概述

数据库元数据(DatabaseMetaData):是由Connection对象通过getMetaData方法获取而来,主要封装了是对数据库本身的一些整体综合信息,例如数据库的产品名称,数据库的版本号,数据库的URL,是否支持事务等等。

以下有一些关于DatabaseMetaData的常用方法:

  • getDatabaseProductName:获取数据库的产品名称
  • getDatabaseProductName:获取数据库的版本号
  • getUserName:获取数据库的用户名
  • getURL:获取数据库连接的URL
  • getDriverName:获取数据库的驱动名称
  • driverVersion:获取数据库的驱动版本号
  • isReadOnly:查看数据库是否只允许读操作
  • supportsTransactions:查看数据库是否支持事务

骚戴理解:总体来说,数据库的元数据分为四大块

  • 数据库基本信息:例如用户名,版本号,驱动版本号,是否支持事务这些数据库基本信息【这个数据库指的是电脑安装的Mysql软件,就是一个数据库软件,这个软件里面有很多数据库database】
  • 所有database数据库名称:获取到所有数据库名称【这个数据库指的是所有的database名称】
  • 某个数据库的所有表信息:获取到指定的某个database数据库的所有表信息,也就是那个database里面的所有表的各种信息都可以获取
  • 某个表的所有列信息:获取到指定的某个database数据库的某个指定表的所有列信息

入门案例

构建环境

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.6</version>
</dependency>

获取数据库基本信息

/**
 * 测试数据库元数据
 */
public class DataBaseMetaDataTest {

    private Connection connection;

    @Before
    public void init() throws Exception {

        String driver ="com.mysql.jdbc.Driver";
        String url="jdbc:mysql://127.0.0.1:3306?useUnicode=true&characterEncoding=utf8";
        //String url="jdbc:mysql://127.0.0.1:3306/ihrm?useUnicode=true&characterEncoding=utf8";
        String username="root";
        String password="111111";

        Properties props = new Properties();
        props.put("remarksReporting","true");//获取数据库的备注信息
        props.put("user",username);
        props.put("password",password);

        //1.获取连接
        Class.forName(driver);//注册驱动
        connection = DriverManager.getConnection(url,props);
    }

    //获取数据库基本信息
    @Test
    public void test01() throws Exception {
        //2.获取元数据
        DatabaseMetaData metaData = connection.getMetaData();

        //3.获取数据库基本信息
        System.out.println(metaData.getUserName());

        System.out.println(metaData.supportsTransactions());//是否支持事务

        System.out.println(metaData.getDatabaseProductName());
    }
}

骚戴理解:DatabaseMetaData直接通过connection.getMetaData();获取即可,然后就是根据需求调用API接口,以下有一些关于DatabaseMetaData的常用方法:

  • getDatabaseProductName:获取数据库的产品名称
  • getDatabaseProductName:获取数据库的版本号
  • getUserName:获取数据库的用户名
  • getURL:获取数据库连接的URL
  • getDriverName:获取数据库的驱动名称
  • driverVersion:获取数据库的驱动版本号
  • isReadOnly:查看数据库是否只允许读操作
  • supportsTransactions:查看数据库是否支持事务

获取数据库列表

/**
 * 测试数据库元数据
 */
public class DataBaseMetaDataTest {

    private Connection connection;

    @Before
    public void init() throws Exception {

        String driver ="com.mysql.jdbc.Driver";
        String url="jdbc:mysql://127.0.0.1:3306?useUnicode=true&characterEncoding=utf8";
        //String url="jdbc:mysql://127.0.0.1:3306/ihrm?useUnicode=true&characterEncoding=utf8";
        String username="root";
        String password="111111";

        Properties props = new Properties();
        props.put("remarksReporting","true");//获取数据库的备注信息
        props.put("user",username);
        props.put("password",password);

        //1.获取连接
        Class.forName(driver);//注册驱动
        connection = DriverManager.getConnection(url,props);
    }

    //获取数据库列表
    @Test
    public void test02() throws SQLException {
        //1.获取元数据
        DatabaseMetaData metaData = connection.getMetaData();
        //2.获取所有数据库列表
        ResultSet rs = metaData.getCatalogs();
        while (rs.next()) {
            System.out.println(rs.getString(1));
        }
        rs.close();
        connection.close();
    }
}

骚戴理解:rs.getString(1)表示获取ResultSet中当前行的第一列的值,并将其以字符串的形式返回。如果第一列的值为null,则返回null。在ResultSet中,列的编号从1开始,依次递增。这里通过 ResultSet rs = metaData.getCatalogs();获取到的ResultSet只有一个field,所以通过rs.getString(1)就是拿到数据库database的名称

获取指定数据库中的表信息

/**
 * 测试数据库元数据
 */
public class DataBaseMetaDataTest {

    private Connection connection;

    @Before
    public void init() throws Exception {

        String driver ="com.mysql.jdbc.Driver";
        String url="jdbc:mysql://127.0.0.1:3306?useUnicode=true&characterEncoding=utf8";
        //String url="jdbc:mysql://127.0.0.1:3306/ihrm?useUnicode=true&characterEncoding=utf8";
        String username="root";
        String password="111111";

        Properties props = new Properties();
        props.put("remarksReporting","true");//获取数据库的备注信息
        props.put("user",username);
        props.put("password",password);

        //1.获取连接
        Class.forName(driver);//注册驱动
        connection = DriverManager.getConnection(url,props);
    }

    //获取指定数据库中的表信息
    @Test
    public void test03() throws Exception {
        //1.获取元数据
        DatabaseMetaData metaData = connection.getMetaData();

        //2.获取数据库中表信息
        /**
         * String catalog, String schemaPattern,String tableNamePattern, String types[]
         *
         *  catalog:当前操作的数据库
         *      mysql:
         *          :ihrm
         *          catalog
         *      oralce:
         *          xxx:1521:orcl
         *          catalog
         *   schema:
         *      mysql:
         *          :null
         *      oracle:
         *          :用户名(大写)
         *
         *    tableNamePattern:
         *      null:查询所有表
         *      为空:查询目标表
         *
         *    types:类型
         *      TABLE:表
         *      VIEW:视图
         *
         */
        ResultSet rs = metaData.getTables(null, null, null, new String[]{"TABLE"});


        while (rs.next()) {
            System.out.println(rs.getString("TABLE_NAME"));
        }
    }
}

骚戴理解:在JDBC中,DatabaseMetaData接口提供了一组方法,用于获取数据库的元数据信息,例如数据库中的表、列、索引等信息。其中,getTables()方法用于获取数据库中的所有表信息,其方法签名如下:

ResultSet getTables(String catalog, String schemaPattern, String tableNamePattern, String[] types) throws SQLException;

该方法接受四个参数,含义如下:

  • catalog:指定catalog名称,用于过滤返回的结果集。如果为null,则返回所有catalog的表信息。
  • schemaPattern:指定schema名称模式,用于过滤返回的结果集。如果为null,则返回所有schema的表信息。
  • tableNamePattern:指定表名称模式,用于过滤返回的结果集。如果为null,则返回所有表信息。
  • types:指定要返回的表类型,例如TABLE、VIEW等。如果为null,则返回所有表类型的信息。

在这个示例中,我们调用getTables()方法,并传入四个参数,其中第一个参数为null,表示返回所有catalog的表信息;第二个参数为null,表示返回所有schema的表信息;第三个参数为null,表示返回所有表信息;第四个参数为new String[]{"TABLE"},表示只返回表类型为TABLE的信息,即排除其他类型的对象,例如VIEW、SYSTEM TABLE等。因此,调用该方法返回的ResultSet中,只包含表类型为TABLE的表信息。

知识扩展

(1)mysql的schema是什么意思

在MySQL中,schema是指数据库对象的命名空间,用于将数据库对象(例如表、视图、存储过程等)分组,以便于管理和授权。在MySQL中,一个schema可以包含多个表、视图、存储过程等对象,而一个对象只能属于一个schema。

在MySQL中,schema通常与数据库是等价的,即一个schema对应一个数据库。因此,在MySQL中,我们可以使用CREATE SCHEMA语句来创建一个新的schema,例如:

CREATE SCHEMA mydatabase;

在这个示例中,我们创建了一个名为mydatabase的新schema,该schema将作为一个新的数据库来使用。可以通过USE语句来切换到该schema,例如:

USE mydatabase;

在这个示例中,我们切换到mydatabase这个schema,以便于在该schema中创建新的表、视图、存储过程等对象。

(2)mysql的catalog是什么意思

在MySQL中,catalog是指数据库的元数据信息,包括数据库名称、表名称、列名称等信息。在MySQL中,一个catalog可以包含多个schema,而一个schema可以包含多个表、视图、存储过程等对象。

在MySQL中,catalog通常与数据库是等价的,即一个catalog对应一个数据库。因此,在使用JDBC连接MySQL数据库时,可以使用数据库的名称作为catalog名称,例如:

String url = "jdbc:mysql://localhost:3306/mydatabase?useSSL=false&serverTimezone=UTC";
Connection conn = DriverManager.getConnection(url, "username", "password");

骚戴理解:简单来说,schema指的database数据库,catalog指的元数据

获取指定表中的字段信息

/**
 * 测试数据库元数据
 */
public class DataBaseMetaDataTest {

    private Connection connection;

    @Before
    public void init() throws Exception {

        String driver ="com.mysql.jdbc.Driver";
        String url="jdbc:mysql://127.0.0.1:3306?useUnicode=true&characterEncoding=utf8";
        //String url="jdbc:mysql://127.0.0.1:3306/ihrm?useUnicode=true&characterEncoding=utf8";
        String username="root";
        String password="111111";

        Properties props = new Properties();
        props.put("remarksReporting","true");//获取数据库的备注信息
        props.put("user",username);
        props.put("password",password);

        //1.获取连接
        Class.forName(driver);//注册驱动
        connection = DriverManager.getConnection(url,props);
    }
    //获取指定表中的字段信息
    @Test
    public void test04() throws Exception {
        DatabaseMetaData metaData = connection.getMetaData();

        //获取表中的字段信息
        /**
         *  catalog
         *  schema
         *  tableName
         *  columnName
         */
        ResultSet rs = metaData.getColumns(null, null, "bs_user", null);

        while (rs.next()) {
            System.out.println(rs.getString("COLUMN_NAME"));
        }
    }
}

骚戴理解:在JDBC中,DatabaseMetaData接口提供了一组方法,用于获取数据库的元数据信息,例如数据库中的表、列、索引等信息。其中,getColumns()方法用于获取指定表的所有列信息,其方法签名如下:

ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) throws SQLException;

该方法接受四个参数,含义如下:

  • catalog:指定catalog名称,用于过滤返回的结果集。如果为null,则返回所有catalog的列信息。
  • schemaPattern:指定schema名称模式,用于过滤返回的结果集。如果为null,则返回所有schema的列信息。
  • tableNamePattern:指定表名称模式,用于过滤返回的结果集。如果为null,则返回所有表的列信息。
  • columnNamePattern:指定列名称模式,用于过滤返回的结果集。如果为null,则返回所有列信息。

在这个示例中,我们调用getColumns()方法,并传入四个参数,其中第一个参数为null,表示返回所有catalog的列信息;第二个参数为null,表示返回所有schema的列信息;第三个参数为"bs_user",表示返回表名为"bs_user"的列信息;第四个参数为null,表示返回表中所有列的信息。因此,调用该方法返回的ResultSet中,只包含"bs_user"表的所有列信息。我们可以通过以下代码遍历ResultSet中的所有列信息:

ResultSet rs = metaData.getColumns(null, null, "bs_user", null);
while (rs.next()) {
    String columnName = rs.getString("COLUMN_NAME");
    String columnType = rs.getString("TYPE_NAME");
    int columnSize = rs.getInt("COLUMN_SIZE");
    System.out.println(columnName + " " + columnType + "(" + columnSize + ")");
}

在这个示例中,我们使用while循环遍历ResultSet中的所有行,每次获取当前行的列名称、列类型和列大小,并打印输出。需要注意的是,ResultSet中的列名称对应的字段名称为"COLUMN_NAME",列类型对应的字段名称为"TYPE_NAME",列大小对应的字段名称为"COLUMN_SIZE"。

参数元数据

参数元数据(ParameterMetaData):是由PreparedStatement对象通过getParameterMetaData方法获取而 来,主要是针对PreparedStatement对象和其预编译的SQL命令语句提供一些信息,ParameterMetaData能提供占位符参数的个数,获取指定位置占位符的SQL类型等等

以下有一些关于ParameterMetaData的常用方法:

getParameterCount:获取预编译SQL语句中占位符参数的个数

  /**
 * 测试数据库元数据
 */
public class DataBaseMetaDataTest {

    private Connection connection;

    @Before
    public void init() throws Exception {

        String driver ="com.mysql.jdbc.Driver";
        String url="jdbc:mysql://127.0.0.1:3306?useUnicode=true&characterEncoding=utf8";
        //String url="jdbc:mysql://127.0.0.1:3306/ihrm?useUnicode=true&characterEncoding=utf8";
        String username="root";
        String password="111111";

        Properties props = new Properties();
        props.put("remarksReporting","true");//获取数据库的备注信息
        props.put("user",username);
        props.put("password",password);

        //1.获取连接
        Class.forName(driver);//注册驱动
        connection = DriverManager.getConnection(url,props);
    }

  @Test
    public void test() throws Exception {
        String sql = "select * from bs_user where id=?";
        PreparedStatement pstmt = conn.prepareStatement(sql);
        pstmt.setString(1, "1063705482939731968");
        //获取ParameterMetaData对象
        ParameterMetaData paramMetaData = pstmt.getParameterMetaData();
        //获取参数个数
        int paramCount = paramMetaData.getParameterCount();
        System.out.println(paramCount);
   }
}


骚戴理解:这个ParameterMetaData其实有很多的方法,但是只有getParameterCount方法是准确的

结果集元数据

结果集元数据(ResultSetMetaData):是由ResultSet对象通过getMetaData方法获取而来,主要是针对由数据库执行的SQL脚本命令获取的结果集对象ResultSet中提供的一些信息,比如结果集中的列数、指定列的名称、指定 列的SQL类型等等,可以说这个是对于框架来说非常重要的一个对象。

以下有一些关于ResultSetMetaData的常用方法:

  • getColumnCount:获取结果集中列的个数
  • getColumnType:获取指定列的SQL类型对应于Java中Types类的字段
  • getColumnTypeName:获取指定列的SQL类型
  • getClassName:获取指定列SQL类型对应于Java中的类型(包名加类名)
  /**
 * 测试数据库元数据
 */
public class DataBaseMetaDataTest {

    private Connection connection;

    @Before
    public void init() throws Exception {

        String driver ="com.mysql.jdbc.Driver";
        String url="jdbc:mysql://127.0.0.1:3306?useUnicode=true&characterEncoding=utf8";
        //String url="jdbc:mysql://127.0.0.1:3306/ihrm?useUnicode=true&characterEncoding=utf8";
        String username="root";
        String password="111111";

        Properties props = new Properties();
        props.put("remarksReporting","true");//获取数据库的备注信息
        props.put("user",username);
        props.put("password",password);

        //1.获取连接
        Class.forName(driver);//注册驱动
        connection = DriverManager.getConnection(url,props);
    }

     @Test
    public void test() throws Exception {
        String sql = "select * from bs_user where id=?";
        PreparedStatement pstmt = conn.prepareStatement(sql);
        pstmt.setString(1, "1063705482939731968");
        //执行sql语句
        ResultSet rs = pstmt.executeQuery() ;
        //获取ResultSetMetaData对象
        ResultSetMetaData metaData = rs.getMetaData();
        //获取查询字段数量
        int columnCount = metaData.getColumnCount() ;
        for (int i=1;i<=columnCount;i++) {
            //获取表名称
            String columnName = metaData.getColumnName(i);
            //获取java类型
            String columnClassName = metaData.getColumnClassName(i);
            //获取sql类型
            String columnTypeName = metaData.getColumnTypeName(i);
            System.out.println(columnName);
            System.out.println(columnClassName);
            System.out.println(columnTypeName);
       }
        System.out.println(columnCount);
   }
}

    

   

代码生成器搭建环境

思路分析

工具的执行逻辑如下图所示:

如上分析,得知完成代码生成器需要以下几个操作:

  • 用户填写的数据库信息,工程搭建信息需要构造到实体类对象中方便操作
  • 数据库表信息,数据库字段信息需要构造到实体类中
  • 构造Freemarker数据模型,将数据库表对象和基本配置存入到Map集合中
  • 借助Freemarker完成代码生成
  • 自定义公共代码模板

搭建环境

配置坐标

    <dependencies>
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.20</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>
    </dependencies>

配置实体类

  • UI页面获取的数据库配置,封装到数据库实体类中
package cn.itcast.generate.entity.db;



//数据库实体类
public class DataBase {

    private static String mysqlUrl = "jdbc:mysql://[ip]:[port]/[db]?useUnicode=true&amp;characterEncoding=UTF8";
    private static String oracleUrl = "jdbc:oracle:thin:@[ip]:[port]:[db]";

    private String dbType;//数据库类型
    private String driver;
    private String userName;
    private String passWord;
    private String url;

    public DataBase() {}

    public DataBase(String dbType) {
        this(dbType,"127.0.0.1","3306","");
    }

    public DataBase(String dbType,String db) {
        this(dbType,"127.0.0.1","3306",db);
    }

    public DataBase(String dbType,String ip,String port,String db) {
        this.dbType = dbType;
        if("MYSQL".endsWith(dbType.toUpperCase())) {
            this.driver="com.mysql.jdbc.Driver";
            this.url=mysqlUrl.replace("[ip]",ip).replace("[port]",port).replace("[db]",db);
        }else{
            this.driver="oracle.jdbc.driver.OracleDriver";
            this.url=oracleUrl.replace("[ip]",ip).replace("[port]",port).replace("[db]",db);
        }
    }

    public String getDbType() {
        return dbType;
    }

    public void setDbType(String dbType) {
        this.dbType = dbType;
    }

    public String getDriver() {
        return driver;
    }

    public void setDriver(String driver) {
        this.driver = driver;
    }

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

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }
}
  • UI页面获取的自动生成工程配置,封装到设置实体类中
package cn.itcast.generate.entity;

import cn.itcast.generate.utils.StringUtils;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

public class Settings {

    private String project="example";
    private String pPackage="com.example.demo";
    private String projectComment;
    private String author;
    private String path1="com";
    private String path2="example";
    private String path3="demo";
    private String pathAll;

    public Settings(String project, String pPackage, String projectComment, String author) {
        if(StringUtils.isNotBlank(project)) {
            this.project = project;
        }
        if(StringUtils.isNotBlank(pPackage)) {
            this.pPackage = pPackage;
        }
        this.projectComment = projectComment;
        this.author = author;
        String[] paths = pPackage.split("\\.");
        path1 = paths[0];
        path2 = paths.length>1?paths[1]:path2;
        path3 = paths.length>2?paths[2]:path3;
        pathAll = pPackage.replaceAll(".","/");
    }

    public Map<String, Object> getSettingMap(){
        Map<String, Object> map = new HashMap<>();
        Field[] declaredFields = Settings.class.getDeclaredFields();
        for (Field field : declaredFields) {
            field.setAccessible(true);
            try{
                map.put(field.getName(), field.get(this));
            }catch (Exception e){}
        }
        return map;
    }

    public String getProject() {
        return project;
    }

    public void setProject(String project) {
        this.project = project;
    }

    public String getpPackage() {
        return pPackage;
    }

    public void setpPackage(String pPackage) {
        this.pPackage = pPackage;
    }

    public String getProjectComment() {
        return projectComment;
    }

    public void setProjectComment(String projectComment) {
        this.projectComment = projectComment;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public String getPath1() {
        return path1;
    }

    public void setPath1(String path1) {
        this.path1 = path1;
    }

    public String getPath2() {
        return path2;
    }

    public void setPath2(String path2) {
        this.path2 = path2;
    }

    public String getPath3() {
        return path3;
    }

    public void setPath3(String path3) {
        this.path3 = path3;
    }

    public String getPathAll() {
        return pathAll;
    }

    public void setPathAll(String pathAll) {
        this.pathAll = pathAll;
    }
}
  • 将查询数据表的元数据封装到Table实体类
package cn.itcast.generate.entity.db;

import java.util.List;

/**
 * 表实体
 * @author Administrator
 *
 */
public class Table {
    
    private String name;//表名称
    private String name2;//处理后的表名称
    private String comment;//介绍
    private String key;// 主键列
    private List<Column> columns;//列集合

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName2() {
        return name2;
    }

    public void setName2(String name2) {
        this.name2 = name2;
    }

    public String getComment() {
        return comment;
    }

    public void setComment(String comment) {
        this.comment = comment;
    }

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }

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

    public void setColumns(List<Column> columns) {
        this.columns = columns;
    }
}

骚戴理解:上面的 private String name2;属性指的是数据库表名对应转化为实体类名称,例如t_user表通过代码生成器转成User实体类,那么这个name2就是User,下面 Column实体类的private String columnName2;也一样,指的是转化为实体类后的属性名称

  • 将查询数据字段的元数据封装到Column实体类
package cn.itcast.generate.entity.db;
/**
 * 列对象
 */
public class Column {
    
    private String columnName;//列名称
    private String columnName2;//列名称(处理后的列名称)
    private String columnType;//列类型
    private String columnDbType;//列数据库类型
    private String columnComment;//列备注D
    private String columnKey;//是否是主键

    public String getColumnName() {
        return columnName;
    }

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

    public String getColumnName2() {
        return columnName2;
    }

    public void setColumnName2(String columnName2) {
        this.columnName2 = columnName2;
    }

    public String getColumnType() {
        return columnType;
    }

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

    public String getColumnDbType() {
        return columnDbType;
    }

    public void setColumnDbType(String columnDbType) {
        this.columnDbType = columnDbType;
    }

    public String getColumnComment() {
        return columnComment;
    }

    public void setColumnComment(String columnComment) {
        this.columnComment = columnComment;
    }

    public String getColumnKey() {
        return columnKey;
    }

    public void setColumnKey(String columnKey) {
        this.columnKey = columnKey;
    }
}

导入工具类

FileUtil工具类

  • getRelativePath:获取文件的相对路径
  • searchAllFile :查询文件夹下所有文件
  • mkdir :创建文件目录
package cn.itcast.generate.utils;

import java.io.*;
import java.net.URL;
import java.util.*;

//文件处理工具类
public class FileUtils {

    // 得到相对路径
    public static String getRelativePath(File baseDir,File file) {
        if(baseDir.equals(file))
            return "";
        if(baseDir.getParentFile() == null)
            return file.getAbsolutePath().substring(baseDir.getAbsolutePath().length());
        return file.getAbsolutePath().substring(baseDir.getAbsolutePath().length()+1);
    }

    //查询某个目录下的所有文件
    public static List<File> searchAllFile(File dir) throws IOException {
        ArrayList arrayList = new ArrayList();
        searchFiles(dir,arrayList);
        return arrayList;
    }

    //递归获取某个目录下的所有文件
    public static void searchFiles(File dir,List<File> collector) throws IOException {
        if(dir.isDirectory()) {
            File[] subFiles = dir.listFiles();
            for(int i = 0; i < subFiles.length; i++) {
                searchFiles(subFiles[i],collector);
            }
        }else{
            collector.add(dir);
        }
    }

    //创建文件
    public static File mkdir(String dir,String file) {
        if(dir == null) throw new IllegalArgumentException("dir must be not null");
        File result = new File(dir,file);
        if(result.getParentFile() != null) {
            result.getParentFile().mkdirs();
        }
        return result;
    }
}

PropertiesMaps工具类

  • 加载所有properties并存入Map集合中:
  • 加载代码生成器的基本配置文件加载用户的自定义配置文件
  • 所有配置文件需要放置到"/properties"文件夹下
package cn.itcast.generate.utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.*;

public class PropertiesUtils {

    public static Map<String,String> customMap = new HashMap<>();

    static {
        File dir = new File("properties");
        try {
            List<File> files = FileUtils.searchAllFile(new File(dir.getAbsolutePath()));
            for (File file : files) {
                if(file.getName().endsWith(".properties")) {
                    Properties prop = new Properties();
                    prop.load(new FileInputStream(file));
                    customMap.putAll((Map) prop);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        PropertiesUtils.customMap.forEach((k, v)->{
            System.out.println(k+"--"+v);
        });
    }
}

骚戴理解:File dir = new File("properties");表示这个工具类要用的话,那么配置文件就必须放在properties目录下,也就是跟src同一级目录

StringHelper字符串处理工具类

package cn.itcast.generate.utils;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class StringUtils {

    public static String removeCrlf(String str) {
        if(str == null) return null;
        return StringUtils.join(StringUtils.tokenizeToStringArray(str,"\t\n\r\f")," ");
    }

    private static final Map<String,String> XML = new HashMap<String,String>();

    static{
        XML.put("apos", "'");
        XML.put("quot", "\"");
        XML.put("amp", "&");
        XML.put("lt", "<");
        XML.put("gt", ">");
    }

    public static String unescapeXml(String str) {
        if(str == null) return null;
        for(String key : XML.keySet()) {
            String value = XML.get(key);
            str = StringUtils.replace(str, "&"+key+";", value);
        }
        return str;
    }


    public static String removePrefix(String str,String prefix) {
        return removePrefix(str,prefix,false);
    }

    public static String removePrefix(String str,String prefix,boolean ignoreCase) {
        if(str == null) return null;
        if(prefix == null) return str;
        if(ignoreCase) {
            if(str.toLowerCase().startsWith(prefix.toLowerCase())) {
                return str.substring(prefix.length());
            }
        }else {
            if(str.startsWith(prefix)) {
                return str.substring(prefix.length());
            }
        }
        return str;
    }

    public static boolean isBlank(String str) {
        return str == null || str.trim().length() == 0;
    }

    public static boolean isNotBlank(String str) {
        return !isBlank(str);
    }

    public static String getExtension(String str) {
        if(str == null) return null;
        int i = str.lastIndexOf('.');
        if(i >= 0) {
            return str.substring(i+1);
        }
        return null;
    }

    /**
     * Count the occurrences of the substring in string s.
     * @param str string to search in. Return 0 if this is null.
     * @param sub string to search for. Return 0 if this is null.
     */
    public static int countOccurrencesOf(String str, String sub) {
        if (str == null || sub == null || str.length() == 0 || sub.length() == 0) {
            return 0;
        }
        int count = 0;
        int pos = 0;
        int idx;
        while ((idx = str.indexOf(sub, pos)) != -1) {
            ++count;
            pos = idx + sub.length();
        }
        return count;
    }

    public static boolean contains(String str,String... keywords) {
        if(str == null) return false;
        if(keywords == null) throw new IllegalArgumentException("'keywords' must be not null");

        for(String keyword : keywords) {
            if(str.contains(keyword.toLowerCase())) {
                return true;
            }
        }
        return false;
    }

    public static String defaultString(Object value) {
        if(value == null) {
            return "";
        }
        return value.toString();
    }

    public static String defaultIfEmpty(Object value,String defaultValue) {
        if(value == null || "".equals(value)) {
            return defaultValue;
        }
        return value.toString();
    }

    public static String makeAllWordFirstLetterUpperCase(String sqlName) {
        String[] strs = sqlName.toLowerCase().split("_");
        String result = "";
        String preStr = "";
        for(int i = 0; i < strs.length; i++) {
            if(preStr.length() == 1) {
                result += strs[i];
            }else {
                result += capitalize(strs[i]);
            }
            preStr = strs[i];
        }
        return result;
    }

    public static int indexOfByRegex(String input,String regex) {
        Pattern p = Pattern.compile(regex);
        Matcher m = p.matcher(input);
        if(m.find()) {
            return m.start();
        }
        return -1;
    }

    public static String toJavaVariableName(String str) {
        return uncapitalize(toJavaClassName(str));
    }

    public static String toJavaClassName(String str) {
        return makeAllWordFirstLetterUpperCase(StringUtils.toUnderscoreName(str));
    }

    public static String removeMany(String inString, String... keywords) {
        if (inString == null) {
            return null;
        }
        for(String k : keywords) {
            inString = replace(inString, k, "");
        }
        return inString;
    }

    public static String replace(String inString, String oldPattern, String newPattern) {
        if (inString == null) {
            return null;
        }
        if (oldPattern == null || newPattern == null) {
            return inString;
        }

        StringBuffer sbuf = new StringBuffer();
        // output StringBuffer we'll build up
        int pos = 0; // our position in the old string
        int index = inString.indexOf(oldPattern);
        // the index of an occurrence we've found, or -1
        int patLen = oldPattern.length();
        while (index >= 0) {
            sbuf.append(inString.substring(pos, index));
            sbuf.append(newPattern);
            pos = index + patLen;
            index = inString.indexOf(oldPattern, pos);
        }
        sbuf.append(inString.substring(pos));

        // remember to append any characters to the right of a match
        return sbuf.toString();
    }
    /**    ĸ  copy from spring*/
    public static String capitalize(String str) {
        return changeFirstCharacterCase(str, true);
    }

    /**    ĸСдcopy from spring*/
    public static String uncapitalize(String str) {
        return changeFirstCharacterCase(str, false);
    }
    /**copy from spring*/
    private static String changeFirstCharacterCase(String str, boolean capitalize) {
        if (str == null || str.length() == 0) {
            return str;
        }
        StringBuffer buf = new StringBuffer(str.length());
        if (capitalize) {
            buf.append(Character.toUpperCase(str.charAt(0)));
        }
        else {
            buf.append(Character.toLowerCase(str.charAt(0)));
        }
        buf.append(str.substring(1));
        return buf.toString();
    }

    private static final Random RANDOM = new Random();
    public static String randomNumeric(int count) {
        return random(count, false, true);
    }

    public static String random(int count, boolean letters, boolean numbers) {
        return random(count, 0, 0, letters, numbers);
    }

    public static String random(int count, int start, int end, boolean letters, boolean numbers) {
        return random(count, start, end, letters, numbers, null, RANDOM);
    }

    public static String random(int count, int start, int end, boolean letters,
                                boolean numbers, char[] chars, Random random) {
        if (count == 0) {
            return "";
        } else if (count < 0) {
            throw new IllegalArgumentException(
                    "Requested random string length " + count
                            + " is less than 0.");
        }
        if ((start == 0) && (end == 0)) {
            end = 'z' + 1;
            start = ' ';
            if (!letters && !numbers) {
                start = 0;
                end = Integer.MAX_VALUE;
            }
        }

        char[] buffer = new char[count];
        int gap = end - start;

        while (count-- != 0) {
            char ch;
            if (chars == null) {
                ch = (char) (random.nextInt(gap) + start);
            } else {
                ch = chars[random.nextInt(gap) + start];
            }
            if ((letters && Character.isLetter(ch))
                    || (numbers && Character.isDigit(ch))
                    || (!letters && !numbers)) {
                if (ch >= 56320 && ch <= 57343) {
                    if (count == 0) {
                        count++;
                    } else {
                        // low surrogate, insert high surrogate after putting it
                        // in
                        buffer[count] = ch;
                        count--;
                        buffer[count] = (char) (55296 + random.nextInt(128));
                    }
                } else if (ch >= 55296 && ch <= 56191) {
                    if (count == 0) {
                        count++;
                    } else {
                        // high surrogate, insert low surrogate before putting
                        // it in
                        buffer[count] = (char) (56320 + random.nextInt(128));
                        count--;
                        buffer[count] = ch;
                    }
                } else if (ch >= 56192 && ch <= 56319) {
                    // private high surrogate, no effing clue, so skip it
                    count++;
                } else {
                    buffer[count] = ch;
                }
            } else {
                count++;
            }
        }
        return new String(buffer);
    }

    /**
     */
    public static String toUnderscoreName(String name) {
        if(name == null) return null;

        String filteredName = name;
        if(filteredName.indexOf("_") >= 0 && filteredName.equals(filteredName.toUpperCase())) {
            filteredName = filteredName.toLowerCase();
        }
        if(filteredName.indexOf("_") == -1 && filteredName.equals(filteredName.toUpperCase())) {
            filteredName = filteredName.toLowerCase();
        }

        StringBuffer result = new StringBuffer();
        if (filteredName != null && filteredName.length() > 0) {
            result.append(filteredName.substring(0, 1).toLowerCase());
            for (int i = 1; i < filteredName.length(); i++) {
                String preChart = filteredName.substring(i - 1, i);
                String c = filteredName.substring(i, i + 1);
                if(c.equals("_")) {
                    result.append("_");
                    continue;
                }
                if(preChart.equals("_")){
                    result.append(c.toLowerCase());
                    continue;
                }
                if(c.matches("\\d")) {
                    result.append(c);
                }else if (c.equals(c.toUpperCase())) {
                    result.append("_");
                    result.append(c.toLowerCase());
                }
                else {
                    result.append(c);
                }
            }
        }
        return result.toString();
    }

    public static String removeEndWiths(String inputString,String... endWiths) {
        for(String endWith : endWiths) {
            if(inputString.endsWith(endWith)) {
                return inputString.substring(0,inputString.length() - endWith.length());
            }
        }
        return inputString;
    }

    /**
     * 将string转换为List<ColumnEnum> 格式为: "enumAlias(enumKey,enumDesc)"
     */
    static Pattern three = Pattern.compile("(.*)\\((.*),(.*)\\)");
    static Pattern two = Pattern.compile("(.*)\\((.*)\\)");

    /**
     * Test whether the given string matches the given substring
     * at the given index.
     * @param str the original string (or StringBuilder)
     * @param index the index in the original string to start matching against
     * @param substring the substring to match at the given index
     */
    public static boolean substringMatch(CharSequence str, int index, CharSequence substring) {
        for (int j = 0; j < substring.length(); j++) {
            int i = index + j;
            if (i >= str.length() || str.charAt(i) != substring.charAt(j)) {
                return false;
            }
        }
        return true;
    }

    public static String[] tokenizeToStringArray(String str,String seperators) {
        if(str == null) return new String[0];
        StringTokenizer tokenlizer = new StringTokenizer(str,seperators);
        List result = new ArrayList();

        while(tokenlizer.hasMoreElements()) {
            Object s = tokenlizer.nextElement();
            result.add(s);
        }
        return (String[])result.toArray(new String[result.size()]);
    }
    public static String join(List list, String seperator) {
        return join(list.toArray(new Object[0]),seperator);
    }

    public static String replace(int start, int end, String str,String replacement) {
        String before = str.substring(0,start);
        String after = str.substring(end);
        return before + replacement + after;
    }

    public static String join(Object[] array, String seperator) {
        if(array == null) return null;
        StringBuffer result = new StringBuffer();
        for(int i = 0; i < array.length; i++) {
            result.append(array[i]);
            if(i != array.length - 1)  {
                result.append(seperator);
            }
        }
        return result.toString();
    }
    public static int containsCount(String string, String keyword) {
        if(string == null) return 0;
        int count = 0;
        for(int i = 0; i < string.length(); i++ ) {
            int indexOf = string.indexOf(keyword,i);
            if(indexOf < 0) {
                break;
            }
            count ++;
            i = indexOf;
        }
        return count;
    }
}

DataBaseUtils工具类

获取所有的数据库database列表

package cn.itcast.generate.utils;

import cn.itcast.generate.entity.DataBase;

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

public class DataBaseUtils {

    //获取到mysql中所有的数据库名称

    //获取数据库连接
    public static Connection getConnection(DataBase db) throws Exception {
        Properties props = new Properties();
        props.put("remarksReporting","true");//获取数据库的备注信息
        props.put("user",db.getUserName());
        props.put("password",db.getPassWord());
        Class.forName(db.getDriver());//注册驱动
        return DriverManager.getConnection(db.getUrl(),props);
    }


    //获取数据库列表
    public static List<String> getSchemas(DataBase db) throws Exception {
        //1.获取元数据
        Connection connection = getConnection(db);
        DatabaseMetaData metaData = connection.getMetaData();
        //2.获取所有数据库列表
        ResultSet rs = metaData.getCatalogs();
        List<String> list = new ArrayList<>();
        while (rs.next()) {
            list.add(rs.getString(1));
        }
        rs.close();
        connection.close();
        return list;
    }
}

配置UI界面

为了方便演示,使用swing程序构造了一套UI页面,对于swing不需要掌握,直接使用即可

DatabaseUtil代码生成器swing程序代码

/*
 * DatabaseUtil.java
 *
 * Created on __DATE__, __TIME__
 */

package cn.itcast.generate.ui;


import cn.itcast.generate.entity.DataBase;
import cn.itcast.generate.utils.DataBaseUtils;

import javax.swing.*;
import java.sql.SQLException;
import java.util.List;


public class DatabaseUtil extends JFrame {

	/** Creates new form DatabaseUtil */
	public DatabaseUtil() {
		initComponents();
	}

	/** This method is called from within the constructor to
	 * initialize the form.
	 * WARNING: Do NOT modify this code. The content of this method is
	 * always regenerated by the Form Editor.
	 */
	//GEN-BEGIN:initComponents
	// <editor-fold defaultstate="collapsed" desc="Generated Code">
	private void initComponents() {

		jLabel1 = new JLabel();
		jComboBox1 = new JComboBox();
		jLabel2 = new JLabel();
		jTextField1 = new JTextField();
		jLabel3 = new JLabel();
		jTextField2 = new JTextField();
		jLabel4 = new JLabel();
		jComboBox2 = new JComboBox();
		jButton1 = new JButton();
		jButton2 = new JButton();
		jTextField3 = new JTextField();
		jLabel5 = new JLabel();

		//setTitle("\u4f20\u667a\u5218\u5907\u4ee3\u7801\u751f\u6210\u56682.3");
		setTitle("代码生成器v1.0");
		setBackground(new java.awt.Color(204, 255, 204));
		addWindowListener(new java.awt.event.WindowAdapter() {
			public void windowClosed(java.awt.event.WindowEvent evt) {
				formWindowClosed(evt);
			}

			public void windowOpened(java.awt.event.WindowEvent evt) {
				formWindowOpened(evt);
			}

			public void windowClosing(java.awt.event.WindowEvent evt) {
				formWindowClosing(evt);
			}
		});

		jLabel1.setText("\u9009\u62e9\u6570\u636e\u5e93\u7c7b\u578b");

		jComboBox1.setModel(new DefaultComboBoxModel(
				new String[] { "--请选择--" }));

		jLabel2.setText("\u7528\u6237\u540d");

		jLabel3.setText("\u5bc6\u7801");

		jLabel4.setText("\u6570\u636e\u5e93");

		jComboBox2.setModel(new DefaultComboBoxModel(
				new String[] { "--请选择数据库--" }));

		jButton1.setText("\u6d4b\u8bd5\u8fde\u63a5");
		jButton1.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				jButton1ActionPerformed(evt);
			}
		});

		jButton2.setLabel("\u8df3\u8fc7");
		jButton2.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				jButton2ActionPerformed(evt);
			}
		});

		jTextField3.setText("127.0.0.1");

		jLabel5.setText("\u670d\u52a1\u5668IP");

		GroupLayout layout = new GroupLayout(
				getContentPane());
		getContentPane().setLayout(layout);
		layout.setHorizontalGroup(layout
				.createParallelGroup(GroupLayout.Alignment.LEADING)
				.addGroup(
						GroupLayout.Alignment.TRAILING,
						layout.createSequentialGroup()
								.addGap(75, 75, 75)
								.addGroup(
										layout.createParallelGroup(
												GroupLayout.Alignment.LEADING)
												.addComponent(jLabel3)
												.addComponent(jLabel5)
												.addComponent(jLabel1)
												.addComponent(jLabel2)
												.addComponent(jLabel4)
												.addComponent(jButton1))
								.addGroup(
										layout.createParallelGroup(
												GroupLayout.Alignment.TRAILING)
												.addGroup(
														layout.createSequentialGroup()
																.addPreferredGap(
																		LayoutStyle.ComponentPlacement.RELATED)
																.addComponent(
																		jButton2,
																		GroupLayout.PREFERRED_SIZE,
																		99,
																		GroupLayout.PREFERRED_SIZE))
												.addGroup(
														GroupLayout.Alignment.LEADING,
														layout.createSequentialGroup()
																.addGap(34, 34,
																		34)
																.addGroup(
																		layout.createParallelGroup(
																				GroupLayout.Alignment.LEADING)
																				.addComponent(
																						jComboBox2,
																						GroupLayout.Alignment.TRAILING,
																						0,
																						174,
																						Short.MAX_VALUE)
																				.addComponent(
																						jTextField1,
																						GroupLayout.Alignment.TRAILING,
																						GroupLayout.DEFAULT_SIZE,
																						174,
																						Short.MAX_VALUE)
																				.addComponent(
																						jComboBox1,
																						GroupLayout.Alignment.TRAILING,
																						0,
																						174,
																						Short.MAX_VALUE)
																				.addComponent(
																						jTextField3,
																						GroupLayout.DEFAULT_SIZE,
																						174,
																						Short.MAX_VALUE)
																				.addComponent(
																						jTextField2,
																						GroupLayout.DEFAULT_SIZE,
																						174,
																						Short.MAX_VALUE))))
								.addGap(106, 106, 106)));
		layout.setVerticalGroup(layout
				.createParallelGroup(GroupLayout.Alignment.LEADING)
				.addGroup(
						layout.createSequentialGroup()
								.addGap(53, 53, 53)
								.addGroup(
										layout.createParallelGroup(
												GroupLayout.Alignment.BASELINE)
												.addComponent(jLabel1)
												.addComponent(
														jComboBox1,
														GroupLayout.PREFERRED_SIZE,
														GroupLayout.DEFAULT_SIZE,
														GroupLayout.PREFERRED_SIZE))
								.addGap(18, 18, 18)
								.addGroup(
										layout.createParallelGroup(
												GroupLayout.Alignment.BASELINE)
												.addComponent(
														jTextField3,
														GroupLayout.PREFERRED_SIZE,
														GroupLayout.DEFAULT_SIZE,
														GroupLayout.PREFERRED_SIZE)
												.addComponent(jLabel5))
								.addPreferredGap(
										LayoutStyle.ComponentPlacement.RELATED)
								.addGroup(
										layout.createParallelGroup(
												GroupLayout.Alignment.BASELINE)
												.addComponent(
														jTextField1,
														GroupLayout.PREFERRED_SIZE,
														GroupLayout.DEFAULT_SIZE,
														GroupLayout.PREFERRED_SIZE)
												.addComponent(jLabel2))
								.addPreferredGap(
										LayoutStyle.ComponentPlacement.RELATED)
								.addGroup(
										layout.createParallelGroup(
												GroupLayout.Alignment.BASELINE)
												.addComponent(
														jTextField2,
														GroupLayout.PREFERRED_SIZE,
														GroupLayout.DEFAULT_SIZE,
														GroupLayout.PREFERRED_SIZE)
												.addComponent(jLabel3))
								.addGap(11, 11, 11)
								.addGroup(
										layout.createParallelGroup(
												GroupLayout.Alignment.LEADING)
												.addComponent(jLabel4)
												.addComponent(
														jComboBox2,
														GroupLayout.PREFERRED_SIZE,
														GroupLayout.DEFAULT_SIZE,
														GroupLayout.PREFERRED_SIZE))
								.addGap(11, 11, 11)
								.addGroup(
										layout.createParallelGroup(
												GroupLayout.Alignment.BASELINE)
												.addComponent(jButton1)
												.addComponent(jButton2))
								.addContainerGap()));

		pack();
	}// </editor-fold>
	//GEN-END:initComponents

	private void formWindowClosing(java.awt.event.WindowEvent evt) {
		dispose();
		System.exit(0);
		System.out.println("释放");
	}

	private void formWindowClosed(java.awt.event.WindowEvent evt) {
		dispose();
		System.exit(0);
		System.out.println("释放");
	}

	private void formWindowOpened(java.awt.event.WindowEvent evt) {
		setLocationRelativeTo(null);

		String [] dbTypes = new String[]{"MYSQL","ORACLE"};

		for (String key : dbTypes) {
			this.jComboBox1.addItem(key);
		}

		setLocationRelativeTo(null);
	}
	
	private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
		if (this.jButton2.getText().equals("下一步")) {
			this.jButton2.setText("运行中...");
			this.jButton2.setEnabled(false);
			final Thread t=new Thread(new Runnable(){
				  public void run(){
					  String dbName = jComboBox2.getSelectedItem().toString();
					  String ip = jTextField3.getText();
					  String username = jTextField1.getText();
					  String password = jTextField2.getText();
					  String dbType = (String)jComboBox1.getSelectedItem();
					  DataBase db = new DataBase(dbType,ip,"3306",dbName);
					  db.setUserName(username);
					  db.setPassWord(password);
					  CodeUtil codeUtil = new CodeUtil(db,null);
					  codeUtil.setDbInfo(db,dbName);
					  codeUtil.setVisible(true);
					  setVisible(false);
				  }}
				 );
			t.start();
			
		 }else{
			JOptionPane.showMessageDialog(null, "请选择数据库", "提示",
					JOptionPane.OK_OPTION);
		 }
	}

	private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
		//
		jButton1.setText("连接中...");
		jButton1.setEnabled(false);
		
		final Thread t=new Thread(new Runnable(){
			  public void run(){
				  try{
				  	  String ip = jTextField3.getText();
					  String username = jTextField1.getText();
					  String password = jTextField2.getText();
					  String dbType = (String)jComboBox1.getSelectedItem();
					  DataBase db = new DataBase(dbType,ip,"3306","");
					  db.setUserName(username);
					  db.setPassWord(password);
					  List<String> catalogs = DataBaseUtils.getSchemas(db);
						jComboBox2.removeAllItems();
						for (String c : catalogs) {
							jComboBox2.addItem(c);
						}
						
						JOptionPane.showMessageDialog(null, "连接成功", "提示",
									JOptionPane.DEFAULT_OPTION);
						jButton2.setText("下一步");
					  
				  }catch (ClassNotFoundException e) {
						e.printStackTrace();
						JOptionPane.showMessageDialog(null, "无法加载驱动类", "提示",
								JOptionPane.OK_OPTION);
						
				  } catch (SQLException e) {
						e.printStackTrace();
						JOptionPane.showMessageDialog(null, "无法连接数据库,请核对连接信息是否正确", "提示",
								JOptionPane.OK_OPTION);
				   }catch (Exception e) {
				     e.printStackTrace();
				     JOptionPane.showMessageDialog(null, "发生错误", "错误详情请查看error.log",
								JOptionPane.INFORMATION_MESSAGE);
				  }
				  jButton1.setEnabled(true);
				  jButton1.setText("测试连接");
			  }}
			 );
		t.start();
	}

	/**
	 * @param args the command line arguments
	 */
	public static void main(String args[]) {
		java.awt.EventQueue.invokeLater(new Runnable() {
			public void run() {
				new DatabaseUtil().setVisible(true);
			}
		});
	}

	//GEN-BEGIN:variables
	// Variables declaration - do not modify
	private JButton jButton1;
	private JButton jButton2;
	private JComboBox<String> jComboBox1;
	private JComboBox jComboBox2;
	private JLabel jLabel1;
	private JLabel jLabel2;
	private JLabel jLabel3;
	private JLabel jLabel4;
	private JLabel jLabel5;
	private JTextField jTextField1;
	private JTextField jTextField2;
	private JTextField jTextField3;
	// End of variables declaration//GEN-END:variables

}

CodeUtil 工具类

/*
 * CodeUtil.java
 * CodeUtil.java
 *
 * Created on __DATE__, __TIME__
 */

package cn.itcast.generate.ui;


import cn.itcast.generate.entity.DataBase;
import cn.itcast.generate.entity.Settings;
import javax.swing.*;
import java.io.File;
import java.util.HashMap;
import java.util.Map;


public class CodeUtil extends JFrame {

	private DataBase db;
	private String dbName;

	/** Creates new form CodeUtil */
	public CodeUtil(DataBase db,String dbName) {
		this.db = db;
		this.dbName = dbName;
		initComponents();
	}

	/** This method is called from within the constructor to
	 * initialize the form.
	 * WARNING: Do NOT modify this code. The content of this method is
	 * always regenerated by the Form Editor.
	 */
	//GEN-BEGIN:initComponents
	// <editor-fold defaultstate="collapsed" desc="Generated Code">
	private void initComponents() {

		jLabel1 = new JLabel();
		jLabel4 = new JLabel();
		jSeparator1 = new JSeparator();
		//jTextField4 = new javax.swing.JTextField();
		jLabel5 = new JLabel();
		jTextField5 = new JTextField();
		jSeparator2 = new JSeparator();
		jLabel6 = new JLabel();
		jTextField6 = new JTextField();
		jLabel7 = new JLabel();
		jTextField7 = new JTextField();
		jLabel8 = new JLabel();
		jTextField8 = new JTextField();
		jLabel9 = new JLabel();
		jTextField9 = new JTextField();
		jButton1 = new JButton();
		jButton2 = new JButton();
		//jButton6 = new javax.swing.JButton();
		jButton7 = new JButton();
		数据库 = new JLabel();
		jTextField10 = new JTextField();
		jLabel10 = new JLabel();
		jTextField11 = new JTextField();
		jLabel11 = new JLabel();
		jTextField12 = new JTextField();
		jComboBox1 = new JComboBox();

		setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
		//setTitle("\u4f20\u667a\u5218\u5907\u4ee3\u7801\u751f\u6210\u5668 V2.3");
		setTitle("代码生成器v1.0");
		addWindowListener(new java.awt.event.WindowAdapter() {
			public void windowActivated(java.awt.event.WindowEvent evt) {
				formWindowActivated(evt);
			}

			public void windowOpened(java.awt.event.WindowEvent evt) {
				formWindowOpened(evt);
			}

			public void windowClosing(java.awt.event.WindowEvent evt) {
				formWindowClosing(evt);
			}
		});

		jLabel1.setText("\u6a21\u677f");

		//jLabel4.setText("\u7ed3\u6784\u6587\u6863\u8def\u5f84");

		jLabel5.setText("\u4ee3\u7801\u751f\u6210\u8def\u5f84");

		jLabel6.setText("\u9879\u76ee\u540d\uff08\u82f1\u6587\uff09");

		jLabel7.setText("\u9879\u76ee\u4e2d\u6587\u540d\u79f0");

		jLabel8.setText("\u5305\u540d");

		jLabel9.setText("\u4f5c\u8005");

		jButton1.setText("\u751f\u6210\u4ee3\u7801");
		jButton1.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				jButton1ActionPerformed(evt);
			}
		});

		jButton2.setText("\u5173\u95ed");
		jButton2.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				jButton2ActionPerformed(evt);
			}
		});

//		jButton6.setText("\u9009\u62e9");
//		jButton6.addActionListener(new java.awt.event.ActionListener() {
//			public void actionPerformed(java.awt.event.ActionEvent evt) {
//				jButton6ActionPerformed(evt);
//			}
//		});

		jButton7.setText("\u9009\u62e9");
		jButton7.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				jButton7ActionPerformed(evt);
			}
		});

		数据库.setText("\u6570\u636e\u5e93");

		jLabel10.setText("\u7528\u6237\u540d");

		jLabel11.setText("\u5bc6\u7801");

		jComboBox1.setModel(new DefaultComboBoxModel(
				new String[] { "--请选择模板--" }));

		GroupLayout layout = new GroupLayout(
				getContentPane());
		getContentPane().setLayout(layout);
		layout.setHorizontalGroup(layout
				.createParallelGroup(GroupLayout.Alignment.LEADING)
				.addComponent(jSeparator2,
						GroupLayout.DEFAULT_SIZE, 543,
						Short.MAX_VALUE)
				.addComponent(jSeparator1,
						GroupLayout.Alignment.TRAILING,
						GroupLayout.DEFAULT_SIZE, 543,
						Short.MAX_VALUE)
				.addGroup(
						GroupLayout.Alignment.TRAILING,
						layout.createSequentialGroup()
								.addGroup(
										layout.createParallelGroup(
												GroupLayout.Alignment.LEADING)
												.addGroup(
														layout.createSequentialGroup()
																.addGap(26, 26,
																		26)
																.addGroup(
																		layout.createParallelGroup(
																				GroupLayout.Alignment.LEADING)
																				.addComponent(
																						jLabel4)
																				.addGroup(
																						layout.createSequentialGroup()
																								.addPreferredGap(
																										LayoutStyle.ComponentPlacement.RELATED)
																								.addComponent(
																										jLabel5))))
												.addGroup(
														layout.createSequentialGroup()
																.addGap(25, 25,
																		25)
																.addGroup(
																		layout.createParallelGroup(
																				GroupLayout.Alignment.LEADING)
																				.addComponent(
																						jLabel6)
																				.addComponent(
																						jLabel8)
																				.addComponent(
																						jLabel7)
																				.addComponent(
																						jLabel9)
																				.addComponent(
																						数据库)
																				.addComponent(
																						jLabel10))))
								.addGap(0, 0, 0)
								.addGroup(
										layout.createParallelGroup(
												GroupLayout.Alignment.LEADING)
												.addGroup(
														layout.createSequentialGroup()
																.addComponent(
																		jTextField11,
																		GroupLayout.PREFERRED_SIZE,
																		104,
																		GroupLayout.PREFERRED_SIZE)
																.addGap(18, 18,
																		18)
																.addComponent(
																		jLabel11)
																.addGap(36, 36,
																		36)
																.addComponent(
																		jTextField12,
																		GroupLayout.DEFAULT_SIZE,
																		118,
																		Short.MAX_VALUE))
												.addComponent(
														jTextField10,
														GroupLayout.DEFAULT_SIZE,
														300, Short.MAX_VALUE)
												.addGroup(
														GroupLayout.Alignment.TRAILING,
														layout.createSequentialGroup()
																.addComponent(
																		jButton1)
																.addPreferredGap(
																		LayoutStyle.ComponentPlacement.RELATED,
																		140,
																		Short.MAX_VALUE)
																.addComponent(
																		jButton2,
																		GroupLayout.PREFERRED_SIZE,
																		79,
																		GroupLayout.PREFERRED_SIZE))
//												.addComponent(
//														jTextField4,
//														javax.swing.GroupLayout.DEFAULT_SIZE,
//														300, Short.MAX_VALUE)
												.addComponent(
														jTextField5,
														GroupLayout.DEFAULT_SIZE,
														300, Short.MAX_VALUE)
												.addComponent(
														jTextField6,
														GroupLayout.DEFAULT_SIZE,
														300, Short.MAX_VALUE)
												.addComponent(
														jTextField7,
														GroupLayout.DEFAULT_SIZE,
														300, Short.MAX_VALUE)
												.addComponent(
														jTextField8,
														GroupLayout.DEFAULT_SIZE,
														300, Short.MAX_VALUE)
												.addComponent(
														jTextField9,
														GroupLayout.DEFAULT_SIZE,
														300, Short.MAX_VALUE))
								.addPreferredGap(
										LayoutStyle.ComponentPlacement.RELATED)
								.addGroup(
										layout.createParallelGroup(
												GroupLayout.Alignment.TRAILING,
												false)
//												.addComponent(
//														jButton7,
//														javax.swing.GroupLayout.Alignment.LEADING,
//														0, 0, Short.MAX_VALUE)
												.addComponent(
														jButton7,
														GroupLayout.Alignment.LEADING,
														GroupLayout.DEFAULT_SIZE,
														73, Short.MAX_VALUE)
									)
								.addGap(54, 54, 54))
				.addGroup(
						GroupLayout.Alignment.TRAILING,
						layout.createSequentialGroup()
								.addGap(27, 27, 27)
								.addComponent(jLabel1)
								.addGap(57, 57, 57)
								.addComponent(jComboBox1,
										GroupLayout.PREFERRED_SIZE,
										299,
										GroupLayout.PREFERRED_SIZE)
								.addGap(136, 136, 136)));
		layout.setVerticalGroup(layout
				.createParallelGroup(GroupLayout.Alignment.LEADING)
				.addGroup(
						layout.createSequentialGroup()
								.addGap(96, 96, 96)
								.addGroup(
										layout.createParallelGroup(
												GroupLayout.Alignment.BASELINE)
												.addComponent(
														jComboBox1,
														GroupLayout.PREFERRED_SIZE,
														GroupLayout.DEFAULT_SIZE,
														GroupLayout.PREFERRED_SIZE)
												.addComponent(jLabel1))
								.addGap(18, 18, 18)
								.addComponent(jSeparator1,
										GroupLayout.PREFERRED_SIZE,
										10,
										GroupLayout.PREFERRED_SIZE)
								.addPreferredGap(
										LayoutStyle.ComponentPlacement.RELATED)
								.addGroup(
										layout.createParallelGroup(
												GroupLayout.Alignment.BASELINE)
												.addComponent(jLabel4)
//												.addComponent(jTextField4)
												//.addComponent(jButton6)
								)
								.addGap(15, 15, 15)
								.addGroup(
										layout.createParallelGroup(
												GroupLayout.Alignment.BASELINE)
												.addComponent(jLabel5)
												.addComponent(jTextField5)
												.addComponent(jButton7))
								.addPreferredGap(
										LayoutStyle.ComponentPlacement.UNRELATED)
								.addComponent(jSeparator2,
										GroupLayout.PREFERRED_SIZE,
										10,
										GroupLayout.PREFERRED_SIZE)
								.addPreferredGap(
										LayoutStyle.ComponentPlacement.RELATED)
								.addGroup(
										layout.createParallelGroup(
												GroupLayout.Alignment.BASELINE)
												.addComponent(jLabel6)
												.addComponent(jTextField6))
								.addPreferredGap(
										LayoutStyle.ComponentPlacement.UNRELATED)
								.addGroup(
										layout.createParallelGroup(
												GroupLayout.Alignment.LEADING)
												.addComponent(jLabel8)
												.addComponent(jTextField7))
								.addPreferredGap(
										LayoutStyle.ComponentPlacement.RELATED)
								.addGroup(
										layout.createParallelGroup(
												GroupLayout.Alignment.BASELINE)
												.addComponent(jLabel7)
												.addComponent(jTextField8))
								.addPreferredGap(
										LayoutStyle.ComponentPlacement.UNRELATED)
								.addGroup(
										layout.createParallelGroup(
												GroupLayout.Alignment.BASELINE)
												.addComponent(jTextField9)
												.addComponent(jLabel9))
								.addGap(18, 18, 18)
								.addGroup(
										layout.createParallelGroup(
												GroupLayout.Alignment.BASELINE)
												.addComponent(数据库)
												.addComponent(jTextField10))
								.addGap(18, 18, 18)
								.addGroup(
										layout.createParallelGroup(
												GroupLayout.Alignment.BASELINE)
												.addComponent(jLabel10)
												.addComponent(
														jTextField11,
														GroupLayout.PREFERRED_SIZE,
														GroupLayout.DEFAULT_SIZE,
														GroupLayout.PREFERRED_SIZE)
												.addComponent(jLabel11)
												.addComponent(
														jTextField12,
														GroupLayout.PREFERRED_SIZE,
														GroupLayout.DEFAULT_SIZE,
														GroupLayout.PREFERRED_SIZE))
								.addGap(26, 26, 26)
								.addGroup(
										layout.createParallelGroup(
												GroupLayout.Alignment.BASELINE)
												.addComponent(jButton2)
												.addComponent(jButton1))
								.addGap(24, 24, 24)));

		pack();
	}// </editor-fold>
	//GEN-END:initComponents

	private void formWindowClosing(java.awt.event.WindowEvent evt) {
		dispose();
		System.exit(0);

	}


	private void formWindowOpened(java.awt.event.WindowEvent evt) {
		setLocationRelativeTo(null);
		//获取当前文件夹下的模板目录下的所有文件夹
		File directory = new File(new File("").getAbsolutePath() + "\\模板");//设定为当前文件夹
		File[] listFiles = directory.listFiles();
		if (listFiles != null) {
			for (File f : listFiles) {
				if (f.isDirectory()) {
					this.jComboBox1.addItem(f.getName());
				}
			}
		}
		//this.jTextField4.setText(new File("").getAbsolutePath() + "\\db");
	}

	private void formWindowActivated(java.awt.event.WindowEvent evt) {

	}

	private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
		//this.dispose();
		System.exit(0);
	}

	public void setDbInfo(DataBase dbs,String name) {
		this.jTextField10.setText(name);
		this.jTextField11.setText(dbs.getUserName());
		this.jTextField12.setText(dbs.getPassWord());

	}

	private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
		jButton1.setEnabled(false);
		jButton1.setText("代码生成中...");
		final Thread t=new Thread(new Runnable(){
			  public void run(){
				  try{
					//路径map封装
						Map<String, String> pathMap = new HashMap<String, String>();
						//获取当前文件夹下的模板目录下的所有文件夹
						String basePath = new File("").getAbsolutePath() + "\\模板\\"
								+ jComboBox1.getSelectedItem();//设定为当前文件夹

						String templetPath = basePath;
						String outpath = jTextField5.getText();

						//全局替换符
						Map<String, String> publicMap = new HashMap<String, String>();
						String project = jTextField6.getText();
						String pPackage = jTextField7.getText();
						String projectComment = jTextField8.getText();
						String author = jTextField9.getText();
					  Settings settings = new Settings(project,pPackage,projectComment,author);
					  generator(templetPath,outpath,settings,db);
					  JOptionPane.showMessageDialog(null, "代码生成成功", "提示",
								JOptionPane.DEFAULT_OPTION);
				  }catch (Exception e) {
				     e.printStackTrace();
				     JOptionPane.showMessageDialog(null, "发生错误", "错误详情请查看error.log",
								JOptionPane.INFORMATION_MESSAGE);
				     
				  }
				  jButton1.setEnabled(true);
				  jButton1.setText("生成代码");
				  
			  }}
		  );
		t.start();
	}

	private void jButton7ActionPerformed(java.awt.event.ActionEvent evt) {
		this.jTextField5.setText(selectPath("选择代码生成路径"));
	}

//	private void jButton6ActionPerformed(java.awt.event.ActionEvent evt) {
//		this.jTextField4.setText(selectPath("选择结构文档路径"));
//	}

	private void jButton4ActionPerformed(java.awt.event.ActionEvent evt) {
		//this.jTextField2.setText(selectPath("选择表级模板路径"));
	}

	/**
	 * 选择路径
	 * @param title
	 * @return
	 */
	private String selectPath(String title) {
		JFileChooser jfc = new JFileChooser();
		jfc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
		jfc.showDialog(new JLabel(), title);
		File file = jfc.getSelectedFile();
		if (file == null) {
			return null;
		}
		return file.getPath();
	}

	public static void main(String args[]) {
		java.awt.EventQueue.invokeLater(new Runnable() {
			public void run() {
				DataBase db = new DataBase("mysql","ihrm");
				db.setUserName("root");
				db.setPassWord("111111");
				new CodeUtil(db,null).setVisible(true);
			}
		});
	}

	//GEN-BEGIN:variables
	// Variables declaration - do not modify
	private JButton jButton1;
	private JButton jButton2;
	private JButton jButton6;
	private JButton jButton7;
	private JComboBox jComboBox1;
	private JLabel jLabel1;
	private JLabel jLabel10;
	private JLabel jLabel11;
	private JLabel jLabel4;
	private JLabel jLabel5;
	private JLabel jLabel6;
	private JLabel jLabel7;
	private JLabel jLabel8;
	private JLabel jLabel9;
	private JSeparator jSeparator1;
	private JSeparator jSeparator2;
	private JTextField jTextField10;
	private JTextField jTextField11;
	private JTextField jTextField12;
	private JTextField jTextField4;
	private JTextField jTextField5;
	private JTextField jTextField6;
	private JTextField jTextField7;
	private JTextField jTextField8;
	private JTextField jTextField9;
	private JLabel 数据库;
	// End of variables declaration//GEN-END:variables


	//UI调用程序入口

	/**
	 *
	 * @param templetPath		模板所在路径
	 * @param outpath			选择代码生成路径
	 * @param settings			工程配置对象
	 * @param db				数据库信息
	 */
	private void generator(String templetPath,String outpath,Settings settings,DataBase db) {
		System.out.println(templetPath);
		System.out.println(outpath);
		System.out.println(settings);
		System.out.println(db);
//		GeneratorFacade gf = new GeneratorFacade(templetPath,outpath,settings);
//		gf.generatorByTable(db);
	}

}

猜你喜欢

转载自blog.csdn.net/qq_50954361/article/details/130941854