前后端分离项目使用代码生成器生成前后端

1.代码生成器页面

代码生成菜单—— 显示所有数据库表的信息 可点击操作栏——生成按钮——弹出生成配置对话框框——填写配置——生成按钮——生成代码压缩包到本地下载后即可放入对应项目

前后端分离项目使用代码生成器生成前后端_第1张图片

前后端分离项目使用代码生成器生成前后端_第2张图片

2.代码生成菜单—— 显示所有数据库表的信息

调用后台接口/generator/page?current=1&size=20,实则为执行sql返回该数据库里数据表名称不为空且取出空白字符后不为‘’的所有数据库表的表名、存储引擎、表注释、数据表的创建时间并根据时间排序,返回给前端后显示在页面

IPage>> queryList(Page page, @Param("tableName") String tableName)

information_schema.tables存储了数据表的元数据信息,下面对常用的字段进行介绍:

  • table_schema: 记录数据库名
  • table_name: 记录数据表名
  • engine : 存储引擎
  • table_rows: 关于表的粗略行估计;
  • data_length : 记录表的大小(单位字节);
  • index_length : 记录表的索引的大小
  • row_format: 可以查看数据表是否压缩过;
  • table_comment :数据表的注释
  • create_time:数据表的创建时间

3.生成代码

调用后台接口/generator/code

 填写生成配置接收类:

package com.amiba.crm.common.codegen.entity;
import lombok.Data;

/**
 * @author HZI.HUI
 * @since 2019/2/1
 * 生成配置
 */
@Data
public class GenConfig {
	/**
	 * 包名
	 */
	private String packageName;
	/**
	 * 作者
	 */
	private String author;
	/**
	 * 模块名称
	 */
	private String moduleName;
	/**
	 * 表前缀
	 */
	private String tablePrefix;

	/**
	 * 表名称
	 */
	private String tableName;

	/**
	 * 表备注
	 */
	private String comments;
}
package com.amiba.crm.admin.controller;

import cn.hutool.core.io.IoUtil;
import com.amiba.crm.common.codegen.entity.GenConfig;
import com.amiba.crm.common.util.R;
import com.amiba.crm.service.SysGeneratorService;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 代码生成操作层
 */
@RestController
@AllArgsConstructor
@RequestMapping("/generator")
public class SysGeneratorController {
	private final SysGeneratorService sysGeneratorService;

	/**
	 * 列表
	 *
	 * @param tableName 参数集
	 * @return 数据库表
	 */
	@GetMapping("/page")
	public R list(Page page, String tableName) {
		return new R<>(sysGeneratorService.queryPage(page,tableName));
	}

	/**
	 * 生成代码
	 */
	@PostMapping("/code")
	public void code(@RequestBody GenConfig genConfig, HttpServletResponse response) throws IOException {
		byte[] data = sysGeneratorService.generatorCode(genConfig);

		response.reset();
		response.setHeader("Content-Disposition", String.format("attachment; filename=%s.zip", genConfig.getTableName()));
		response.addHeader("Content-Length", "" + data.length);
		response.setContentType("application/octet-stream; charset=UTF-8");

		IoUtil.write(response.getOutputStream(), Boolean.TRUE, data);
	}
}

实则调用

	/**
	 * 生成代码
	 *
	 * @param genConfig 生成配置
	 * @return
	 */
	@Override
	public byte[] generatorCode(GenConfig genConfig) {
		ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
		ZipOutputStream zip = new ZipOutputStream(outputStream);

		//查询表信息  得到该表的 tableName, engine, tableComment, create_time 
		Map table = queryTable(genConfig.getTableName());
		//查询列信息columnName, dataType, columnComment, columnKey, extra
		List> columns = queryColumns(genConfig.getTableName());
		//生成代码
		GenUtils.generatorCode(genConfig, table, columns, zip);
		IoUtil.close(zip);
		return outputStream.toByteArray();
	}

生成代码方法:

	/**
	 * 生成代码   
         * 参数genConfig为用户在生成配置中填写的配置信息
         * 参数table   该数据表的信息
         * 参数columns 该数据表的列信息
         * 参数zip     压缩文件输出流
	 */
	public static void generatorCode(GenConfig genConfig, Map table,
									 List> columns, ZipOutputStream zip) {
		//获取本地配置文件信息
		Configuration config = getConfig();
		boolean hasBigDecimal = false;
		//表的名称
		TableEntity tableEntity = new TableEntity();
		tableEntity.setTableName(table.get("tableName"));
                //表注释
		if (StrUtil.isNotBlank(genConfig.getComments())) {
			tableEntity.setComments(genConfig.getComments());
		} else {
			tableEntity.setComments(table.get("tableComment"));
		}
                //得到需要删除的表前缀
		String tablePrefix;
		if (StrUtil.isNotBlank(genConfig.getTablePrefix())) {
			tablePrefix = genConfig.getTablePrefix();
		} else {
			tablePrefix = config.getString("tablePrefix");
		}

		//表名转换成Java类名
		String className = tableToJava(tableEntity.getTableName(), tablePrefix);
		tableEntity.setCaseClassName(className);
		tableEntity.setLowerClassName(StringUtils.uncapitalize(className));

		//列信息
		List columnList = new ArrayList<>();
		for (Map column : columns) {
			ColumnEntity columnEntity = new ColumnEntity();
			columnEntity.setColumnName(column.get("columnName"));
			columnEntity.setDataType(column.get("dataType"));
			columnEntity.setComments(column.get("columnComment"));
			columnEntity.setExtra(column.get("extra"));

			//列名转换成Java属性名
			String attrName = columnToJava(columnEntity.getColumnName());
			columnEntity.setCaseAttrName(attrName);
			columnEntity.setLowerAttrName(StringUtils.uncapitalize(attrName));

			//列的数据类型,转换成Java类型
			String attrType = config.getString(columnEntity.getDataType(), "unknowType");
			columnEntity.setAttrType(attrType);
			if (!hasBigDecimal && "BigDecimal".equals(attrType)) {
				hasBigDecimal = true;
			}
			//是否主键
			if ("PRI".equalsIgnoreCase(column.get("columnKey")) && tableEntity.getPk() == null) {
				tableEntity.setPk(columnEntity);
			}

			columnList.add(columnEntity);
		}
		tableEntity.setColumns(columnList);

		//没主键,则第一个字段为主键
		if (tableEntity.getPk() == null) {
			tableEntity.setPk(tableEntity.getColumns().get(0));
		}

		//设置velocity资源加载器
		Properties prop = new Properties();
		prop.put("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
		Velocity.init(prop);
		//封装模板数据
		Map map = new HashMap<>(16);
		map.put("tableName", tableEntity.getTableName());
		map.put("pk", tableEntity.getPk());
		map.put("className", tableEntity.getCaseClassName());
		map.put("classname", tableEntity.getLowerClassName());
		map.put("pathName", tableEntity.getLowerClassName().toLowerCase());
		map.put("columns", tableEntity.getColumns());
		map.put("hasBigDecimal", hasBigDecimal);
		map.put("date", DateUtil.format(new Date(),"yyyy/MM/dd"));

		if (StrUtil.isNotBlank(genConfig.getComments())) {
			map.put("comments", genConfig.getComments());
		} else {
			map.put("comments", tableEntity.getComments());
		}

		if (StrUtil.isNotBlank(genConfig.getAuthor())) {
			map.put("author", genConfig.getAuthor());
		} else {
			map.put("author", config.getString("author"));
		}

		if (StrUtil.isNotBlank(genConfig.getModuleName())) {
			map.put("moduleName", genConfig.getModuleName());
		} else {
			map.put("moduleName", config.getString("moduleName"));
		}

		if (StrUtil.isNotBlank(genConfig.getPackageName())) {
			map.put("package", genConfig.getPackageName());
			map.put("mainPath", genConfig.getPackageName());
		} else {
			map.put("package", config.getString("package"));
			map.put("mainPath", config.getString("mainPath"));
		}
		VelocityContext context = new VelocityContext(map);

		//获取模板列表
		List templates = getTemplates();
		for (String template : templates) {
			//渲染模板
			StringWriter sw = new StringWriter();
			Template tpl = Velocity.getTemplate(template, CharsetUtil.UTF_8);
			tpl.merge(context, sw);

			try {
				//添加到zip
				zip.putNextEntry(new ZipEntry(Objects
					.requireNonNull(getFileName(template, tableEntity.getCaseClassName() ,tableEntity.getLowerClassName()
						, map.get("package").toString(), map.get("moduleName").toString()))));
				IoUtil.write(zip, CharsetUtil.UTF_8, false, sw.toString());
				IoUtil.close(sw);
				zip.closeEntry();
			} catch (IOException e) {
				throw new CheckedException("渲染模板失败,表名:" + tableEntity.getTableName(), e);
			}
		}
	}

 

 

 

你可能感兴趣的:(前后端分离项目使用代码生成器生成前后端)