2019-11-14
网上关于代码自动生成的开源项目很多,基本可以拿来之后修改模板文件直接使用.本项目的代码自动生成主要是17年左右借鉴人人开源上面的代码而来.
基本思路都是一样的:
generator-config.properties
#代码生成器,配置信息#包名packageName=pers.vic#模块名moduleName=system#作者author=Vic.xuemail=xuduochoua@163.com#表前缀(类名不会包含表前缀)tablePrefix=#需要填充的模板templates[0]=generator/templates/Entity.java.vm#略#数据类型转换,配置信息:数据库类型->java类型tinyint=Integer#略
TableEntity 对应一张表的基本数据:表名/备注/主键/对应的类名/创建时间/关联的ColumnEntity列表等ColumnEntity对应列的属性:列名/列属性/备注/属性名/属性类型/是否主键/对应的ColumnExtend等ColumnExtend列的扩展:本项目额外增加的根据备注对列做的额外的处理说明
@Servicepublic class GeneratorService{@Resourceprivate ConfigurationOfGenerator configurationOfGenerator;@Resourceprivate 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 {// 添加到zipString 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.javaif (template.contains("Mapper.java.vm")) {return packagePath + File.separator + className + "Mapper.java";}// serviceif (template.contains("Service.java.vm")) {return packagePath + File.separator + className + "Service.java";}// controllerif (template.contains("Controller.java.vm")) {return packagePath + File.separator + className + "Controller.java";}// mapper.xnlif (template.contains("Mapper.xml.vm")) {return packagePath + File.separator + className + "Mapper.xml";}// list.jspif (template.contains("list.jsp.vm")) {return packagePath + File.separator + "list.jsp";}// form.jspif (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 {// 添加到zipString 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;}}