2019-11-14
网上关于代码自动生成的开源项目很多,基本可以拿来之后修改模板文件直接使用.本项目的代码自动生成主要是17年左右借鉴人人开源上面的代码而来.
基本思路都是一样的:
generator-config.properties
#代码生成器,配置信息
#包名
packageName=pers.vic
#模块名
moduleName=system
#作者
author=Vic.xu
email=xuduochoua@163.com
#表前缀(类名不会包含表前缀)
tablePrefix=
#需要填充的模板
templates[0]=generator/templates/Entity.java.vm
#略
#数据类型转换,配置信息:数据库类型->java类型
tinyint=Integer
#略
TableEntity
对应一张表的基本数据:表名/备注/主键/对应的类名/创建时间/关联的ColumnEntity
列表等ColumnEntity
对应列的属性:列名/列属性/备注/属性名/属性类型/是否主键/对应的ColumnExtend
等ColumnExtend
列的扩展:本项目额外增加的根据备注对列做的额外的处理说明
@Service
public class GeneratorService{
@Resource
private ConfigurationOfGenerator configurationOfGenerator;
@Resource
private GeneratorMapper generatorMapper;
public List<TableEntity> list(Lookup lookup) {
List<TableEntity> datas = generatorMapper.queryList(lookup);
return datas;
}
private List<ColumnEntity> queryColumns(String tableName) {
return generatorMapper.queryColumns(tableName);
}
private TableEntity queryTable(String tableName) {
return generatorMapper.queryTable(tableName);
}
/**
* 根据表名生成代码
*
* @param moduleName
* @param packageName
*/
public byte[] generatorCode(String[] tableNames, String packageName, String moduleName) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ZipOutputStream zip = new ZipOutputStream(outputStream);
for (String tableName : tableNames) {
// 查询表信息
TableEntity table = queryTable(tableName);
// 查询列信息
List<ColumnEntity> columns = queryColumns(tableName);
// 生成代码
generatorCode(table, packageName, moduleName, columns, zip);
}
IOUtils.closeQuietly(zip);
return outputStream.toByteArray();
}
private void generatorCode(TableEntity table, String packageName, String moduleName, List<ColumnEntity> columns,
ZipOutputStream zip) {
Map<String, Object> map = getTemplateData(table, packageName, moduleName, columns);
VelocityContext context = new VelocityContext(map);
// 获取模板列表
List<String> templates = getTemplates();
for (String template : templates) {
// 渲染模板
StringWriter sw = new StringWriter();
Template tpl = Velocity.getTemplate(template, "UTF-8");
tpl.merge(context, sw);
try {
// 添加到zip
String fileName = getFileName(template, table.getClassName(), configurationOfGenerator.getPackageName(),
configurationOfGenerator.getModuleName());
zip.putNextEntry(new ZipEntry(fileName));
IOUtils.write(sw.toString(), zip, "UTF-8");
IOUtils.closeQuietly(sw);
zip.closeEntry();
} catch (Exception e) {
throw new RuntimeException("渲染模板失败,表名:" + table.getTableName(), e);
}
}
}
//获得渲染模板的数据
private Map<String, Object> getTemplateData(TableEntity table, String packageName, String moduleName, List<ColumnEntity> columns) {
// 配置信息
Configuration config = getConfig();
boolean hasBigDecimal = false;
String className = tableToJava(table.getTableName(), configurationOfGenerator.getTablePrefix());
table.setClassName(className);
// 第一个字母小写
table.setClassname(StringUtils.uncapitalize(className));
// 列信息
for (ColumnEntity column : columns) {
// 列名转换成Java属性名
String attrName = columnToJava(column.getColumnName());
column.setAttrName(attrName);
column.setAttrname(StringUtils.uncapitalize(attrName));
// 列的数据类型,转换成Java类型
String attrType = config.getString(column.getDataType(), "unknowType");
column.setAttrType(attrType);
if (!hasBigDecimal && attrType.equals("BigDecimal")) {
hasBigDecimal = true;
}
if ("Date".equals(attrType)) {
table.setHasDate(true);
}
// 是否主键
if ("PRI".equalsIgnoreCase(column.getColumnKey()) && table.getPk() == null) {
table.setPk(column);
}
// 根据列是否是图片和日期 判断表中是否含有图片和日期
ColumnExtend extend = ColumnExtend.initExtends(column);
table.findExtend(extend);
}
// 没主键,则第一个字段为主键
table.setColumns(columns);
if (table.getPk() == null) {
table.setPk(columns.get(0));
}
// 设置velocity资源加载器
Properties prop = new Properties();
prop.put("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
Velocity.init(prop);
// 封装模板数据
Map<String, Object> map = new HashMap<String, Object>();
map.put("table", table);
map.put("tableName", table.getTableName());
map.put("comments", table.getComments());
map.put("pk", table.getPk());
map.put("className", table.getClassName());
map.put("classname", table.getClassname());
map.put("pathName", table.getClassname().toLowerCase());
map.put("columns", table.getColumns());
map.put("hasBigDecimal", hasBigDecimal);
if (StringUtils.isEmpty(packageName)) {
map.put("package", config.getString("packageName"));
} else {
map.put("package", packageName);
}
if (StringUtils.isEmpty(packageName)) {
map.put("moduleName", config.getString("moduleName"));
} else {
map.put("moduleName", moduleName);
}
map.put("author", config.getString("author"));
map.put("email", config.getString("email"));
map.put("datetime", DateFormatUtils.format(new Date(), "yyyy-mm-dd HH:mm"));
return map;
}
/**
* 获取文件名
*/
public static String getFileName(String template, String className, String packageName, String moduleName) {
String packagePath = "generator" + File.separator + className;
/*
* packagePath = "main" + File.separator + "java" + File.separator; if
* (StringUtils.isNotBlank(packageName)) { packagePath +=
* packageName.replace(".", File.separator) + File.separator + moduleName +
* File.separator; }
*/
// 实体
if (template.contains("Entity.java.vm")) {
return packagePath + File.separator + className + ".java";
}
// 查询条件
if (template.contains("Lookup.java.vm")) {
return packagePath + File.separator + className + "Lookup.java";
}
// mapper.java
if (template.contains("Mapper.java.vm")) {
return packagePath + File.separator + className + "Mapper.java";
}
// service
if (template.contains("Service.java.vm")) {
return packagePath + File.separator + className + "Service.java";
}
// controller
if (template.contains("Controller.java.vm")) {
return packagePath + File.separator + className + "Controller.java";
}
// mapper.xnl
if (template.contains("Mapper.xml.vm")) {
return packagePath + File.separator + className + "Mapper.xml";
}
// list.jsp
if (template.contains("list.jsp.vm")) {
return packagePath + File.separator + "list.jsp";
}
// form.jsp
if (template.contains("form.jsp.vm")) {
return packagePath + File.separator + "form.jsp";
}
return null;
}
/**
* 获取要填充的模板
* @return
*/
public List<String> getTemplates() {
return configurationOfGenerator.getTemplates();
}
/**
* 表名转换成Java类名
*/
private String tableToJava(String tableName, String tablePrefix) {
if (StringUtils.isNotBlank(tablePrefix)) {
tableName = tableName.replaceFirst(tablePrefix, "");
}
return columnToJava(tableName);
}
/**
* 列名转换成Java属性名
*/
public static String columnToJava(String columnName) {
// return WordUtils.capitalizeFully(columnName, new char[] { '_' }).replace("_", "");//aaBBcc-->aabbcc 不是我想要的
return underlineToCamel(columnName);
}
/**
* 下划线转驼峰 但是不小写
*
* @param str
* @return
*/
static String UNDERLINE = "_";
public static String underlineToCamel(String str) {
if (StringUtils.isEmpty(str)) {
return str;
}
StringBuffer sb = new StringBuffer();
for (String s : str.split(UNDERLINE)) {
sb.append(StringUtils.capitalize(s));
}
return sb.toString();
}
/**
* 获取配置信息
*/
public static Configuration getConfig() {
try {
return new PropertiesConfiguration("config/generator-config.properties");
} catch (ConfigurationException e) {
throw new RuntimeException("获取配置文件失败,", e);
}
}
public Map<String, String> findTableDetail(String tableName, String packageName, String moduleName) {
// 查询表信息
TableEntity table = queryTable(tableName);
// 查询列信息
List<ColumnEntity> columns = queryColumns(tableName);
Map<String, Object> map = getTemplateData(table, packageName, moduleName, columns);
VelocityContext context = new VelocityContext(map);
// 获取模板列表
List<String> templates = getTemplates();
Map<String, String> data = new LinkedHashMap<String, String>();
for (String template : templates) {
// 渲染模板
StringWriter sw = new StringWriter();
Template tpl = Velocity.getTemplate(template, "UTF-8");
tpl.merge(context, sw);
try {
// 添加到zip
String fileName = getFileName(template, table.getClassName(), configurationOfGenerator.getPackageName(),
configurationOfGenerator.getModuleName());
data.put(fileName.replace("generator" + File.separator, "").replace(File.separator, "_"), sw.toString());
} catch (Exception e) {
throw new RuntimeException("渲染模板失败,表名:" + table.getTableName(), e);
}
}
return data;
}
}