返回博文列表

JFinal 生成 markdown 格式数据字典

借用 JFinal 内置的 DataDictionaryGenerator,重写表头与单元格生成逻辑,把 MySQL 命令行风格的数据字典直接输出成 markdown 表格。

如梦技术 5 分钟
# jfinal # markdown

设计初衷

利用JFinal的代码生成可以为我们生成漂亮的数据字典。其格式类似Mysql的命令行,可见波总的用心。

html
Table: t_ad (广告表)
----------------+---------------------+------+-----+-------------------+---------
 Field          | Type                | Null | Key | Default           | Remarks 
----------------+---------------------+------+-----+-------------------+---------
 id             | INT UNSIGNED(10)    | NO   | PRI |                   | 主键id    
 ad_position_id | INT UNSIGNED(10)    | NO   |     | 0                 | 广告位id   
 title          | VARCHAR(64)         | NO   |     |                   | 广告标题    
 content        | VARCHAR(255)        | NO   |     |                   | 广告内容    
 media_type     | TINYINT UNSIGNED(2) | NO   |     | 0                 | 媒体类型    
 link           | VARCHAR(255)        | NO   |     |                   | 链接地址    
 image_url      | VARCHAR(255)        | NO   |     |                   | 图片地址    
 end_time       | DATETIME(19)        | NO   |     | CURRENT_TIMESTAMP | 结束时间    
 seq            | TINYINT(3)          | NO   |     | 0                 | 排序      
 enabled        | TINYINT UNSIGNED(2) | NO   |     | 1                 | 是否启用     
 creator        | VARCHAR(32)         | NO   |     |                   | 格式:创建者[id]
 updator        | VARCHAR(32)         | NO   |     |                   | 格式:创建者[id]
 create_time    | DATETIME(19)        | NO   |     | CURRENT_TIMESTAMP | 创建时间    
 update_time    | DATETIME(19)        | NO   |     | CURRENT_TIMESTAMP | 更新时间    
----------------+---------------------+------+-----+-------------------+---------

在实际工作中现在我们更多的是采用markdown格式的文档,研究一番可以发现JFinal生成的数据字典和markdown的Table比较类型。下面来看看我的改造过程。

改造数据字典格式

添加Druid链接参数

java
DruidPlugin druidPlugin = new DruidPlugin(jdbcUrl, user, password);
// remarks=true设置可以获取column remarks信息
// useInformationSchema=true设置可以获取tables remarks信息
druidPlugin.setConnectionProperties("useInformationSchema=true;remarks=true");
druidPlugin.start();
return druidPlugin.getDataSource();

重写DataDictionaryGenerator

java
import javax.sql.DataSource;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.generator.ColumnMeta;
import com.jfinal.plugin.activerecord.generator.TableMeta;

public class MyDataDictionaryGenerator extends com.jfinal.plugin.activerecord.generator.DataDictionaryGenerator {

	public DataDictionaryGenerator(DataSource dataSource, String dataDictionaryOutputDir) {
		super(dataSource, dataDictionaryOutputDir);
	}

	/**
	 * 重写掉生成换行
	 */
	@Override
	protected String genSeparateLine(TableMeta tm) {
		return "";
	}

	protected void generateTable(TableMeta tableMeta, StringBuilder ret) {
		ret.append("Table: ").append(tableMeta.name);
		if (StrKit.notBlank(tableMeta.remarks)) {
			ret.append("(").append(clearBlank(tableMeta.remarks)).append(")");
		}
		ret.append("\n");
		
		String sparateLine = genSeparateLine(tableMeta);
		ret.append(sparateLine);
		genTableHead(tableMeta, ret);
		ret.append(sparateLine);
		for (ColumnMeta columnMeta : tableMeta.columnMetas) {
			genColumn(tableMeta, columnMeta, ret);
		}
		ret.append(sparateLine);
		ret.append("\n");
	}

	/**
	 * 表头
	 */
	@Override
	protected void genTableHead(TableMeta tm, StringBuilder ret) {
		ret.append('\n').append('|');
		genCell(tm.colNameMaxLen, " ", "Field", " ", "|",  ret);
		genCell(tm.colTypeMaxLen, " ", "Type", " ", "|", ret);
		genCell("Null".length(), " ", "Null",  " ","|", ret);
		genCell("Key".length(), " ", "Key",  " ","|", ret);
		genCell(tm.colDefaultValueMaxLen, " ", "Default", " ", "|", ret);
		genCell("Remarks".length(), " ", "Remarks", " ", "|", ret);
		ret.append('\n').append('|');
		genCell(tm.colNameMaxLen, " ", "-", "-", "|",  ret);
		ret.replace(ret.length() - 2, ret.length() - 1, " ");
		genCell(tm.colTypeMaxLen, " ", "-", "-", "|", ret);
		ret.replace(ret.length() - 2, ret.length() - 1, " ");
		genCell("Null".length(), " ", "-",  "-","|", ret);
		ret.replace(ret.length() - 2, ret.length() - 1, " ");
		genCell("Key".length(), " ", "-",  "-","|", ret);
		ret.replace(ret.length() - 2, ret.length() - 1, " ");
		genCell(tm.colDefaultValueMaxLen, " ", "-", "-", "|", ret);
		ret.replace(ret.length() - 2, ret.length() - 1, " ");
		genCell("Remarks".length(), " ", "-", "-", "|", ret);
		ret.replace(ret.length() - 2, ret.length() - 1, " ");
		ret.append('\n');
	}

	/**
	 * 列
	 */
	@Override
	protected void genColumn(TableMeta tableMeta, ColumnMeta columnMeta, StringBuilder ret) {
		ret.append('|');
		genCell(tableMeta.colNameMaxLen, " ", columnMeta.name, " ", "|",  ret);
		genCell(tableMeta.colTypeMaxLen, " ", columnMeta.type, " ", "|", ret);
		genCell("Null".length(), " ", columnMeta.isNullable, " ", "|", ret);
		genCell("Key".length(), " ", columnMeta.isPrimaryKey, " ", "|", ret);
		genCell(tableMeta.colDefaultValueMaxLen, " ", columnMeta.defaultValue, " ", "|", ret);
		genCell("Remarks".length(), " ", clearBlank(columnMeta.remarks), " ", "|", ret);
		ret.append("\n");
	}
	
	/**
	 * 清除注释中的空白符
	 */
	private String clearBlank(String str) {
		return str.replaceAll("[ |\t|\n]+", "");
	}
}

配置新数据字典生成类

java
// 创建生成器
Generator generator = new Generator(dataSource, baseModelPackageName, baseModelOutputDir, modelPackageName, modelOutputDir);
DataDictionaryGenerator dg = new MyDataDictionaryGenerator(dataSource, modelOutputDir);
dg.setDataDictionaryFileName("数据字典.md");
generator.setDataDictionaryGenerator(dg);

到此大工搞成,迫不及待的看看效果展示了~

效果展示

Table: t_ad (广告表)

FieldTypeNullKeyDefaultRemarks
idINT UNSIGNED(10)NOPRI主键id
ad_position_idINT UNSIGNED(10)NO0广告位id
titleVARCHAR(64)NO广告标题
contentVARCHAR(255)NO广告内容
media_typeTINYINT UNSIGNED(3)NO0媒体类型
linkVARCHAR(255)NO链接地址
image_urlVARCHAR(255)NO图片地址
end_timeDATETIME(19)NOCURRENT_TIMESTAMP结束时间
seqTINYINT(3)NO0排序
enabledTINYINT UNSIGNED(3)NO1
creatorVARCHAR(32)NO格式:创建者[id]
updatorVARCHAR(32)NO格式:创建者[id]
create_timeDATETIME(19)NOCURRENT_TIMESTAMP创建时间
update_timeDATETIME(19)NOCURRENT_TIMESTAMP更新时间

开源推荐

微信公众号

如梦技术

精彩内容每日推荐!!!