|
@@ -15,23 +15,9 @@
|
|
|
*/
|
|
|
package com.baomidou.mybatisplus.generator;
|
|
|
|
|
|
-import java.io.BufferedWriter;
|
|
|
-import java.io.File;
|
|
|
-import java.io.FileOutputStream;
|
|
|
-import java.io.IOException;
|
|
|
-import java.io.OutputStreamWriter;
|
|
|
import java.io.Serializable;
|
|
|
-import java.text.SimpleDateFormat;
|
|
|
-import java.util.Date;
|
|
|
-import java.util.HashMap;
|
|
|
import java.util.List;
|
|
|
-import java.util.Map;
|
|
|
-import java.util.Properties;
|
|
|
|
|
|
-import org.apache.velocity.Template;
|
|
|
-import org.apache.velocity.VelocityContext;
|
|
|
-import org.apache.velocity.app.Velocity;
|
|
|
-import org.apache.velocity.app.VelocityEngine;
|
|
|
import org.slf4j.Logger;
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
|
@@ -39,9 +25,7 @@ import com.baomidou.mybatisplus.activerecord.Model;
|
|
|
import com.baomidou.mybatisplus.annotations.TableLogic;
|
|
|
import com.baomidou.mybatisplus.annotations.TableName;
|
|
|
import com.baomidou.mybatisplus.annotations.Version;
|
|
|
-import com.baomidou.mybatisplus.generator.config.ConstVal;
|
|
|
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
|
|
|
-import com.baomidou.mybatisplus.generator.config.FileOutConfig;
|
|
|
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
|
|
|
import com.baomidou.mybatisplus.generator.config.PackageConfig;
|
|
|
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
|
|
@@ -49,20 +33,26 @@ import com.baomidou.mybatisplus.generator.config.TemplateConfig;
|
|
|
import com.baomidou.mybatisplus.generator.config.builder.ConfigBuilder;
|
|
|
import com.baomidou.mybatisplus.generator.config.po.TableField;
|
|
|
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
|
|
|
-import com.baomidou.mybatisplus.toolkit.CollectionUtils;
|
|
|
+import com.baomidou.mybatisplus.generator.engine.AbstractTemplateEngine;
|
|
|
+import com.baomidou.mybatisplus.generator.engine.VelocityTemplateEngine;
|
|
|
import com.baomidou.mybatisplus.toolkit.StringUtils;
|
|
|
|
|
|
/**
|
|
|
* 生成文件
|
|
|
*
|
|
|
- * @author YangHu, tangguo
|
|
|
+ * @author YangHu, tangguo, hubin
|
|
|
* @since 2016-08-30
|
|
|
*/
|
|
|
public class AutoGenerator {
|
|
|
|
|
|
private static final Logger logger = LoggerFactory.getLogger(AutoGenerator.class);
|
|
|
-
|
|
|
+ /**
|
|
|
+ * 配置信息
|
|
|
+ */
|
|
|
protected ConfigBuilder config;
|
|
|
+ /**
|
|
|
+ * 注入配置
|
|
|
+ */
|
|
|
protected InjectionConfig injectionConfig;
|
|
|
/**
|
|
|
* 数据源配置
|
|
@@ -85,9 +75,9 @@ public class AutoGenerator {
|
|
|
*/
|
|
|
private GlobalConfig globalConfig;
|
|
|
/**
|
|
|
- * velocity引擎
|
|
|
+ * 模板引擎
|
|
|
*/
|
|
|
- private VelocityEngine engine;
|
|
|
+ private AbstractTemplateEngine templateEngine;
|
|
|
|
|
|
/**
|
|
|
* 生成代码
|
|
@@ -95,32 +85,18 @@ public class AutoGenerator {
|
|
|
public void execute() {
|
|
|
logger.debug("==========================准备生成文件...==========================");
|
|
|
// 初始化配置
|
|
|
- initConfig();
|
|
|
- // 创建输出文件路径
|
|
|
- mkdirs(config.getPathInfo());
|
|
|
- // 获取上下文
|
|
|
- Map<String, VelocityContext> ctxData = analyzeData(config);
|
|
|
- // 循环生成文件
|
|
|
- for (Map.Entry<String, VelocityContext> ctx : ctxData.entrySet()) {
|
|
|
- batchOutput(ctx.getKey(), ctx.getValue());
|
|
|
- }
|
|
|
- // 打开输出目录
|
|
|
- if (config.getGlobalConfig().isOpen()) {
|
|
|
- try {
|
|
|
- String osName = System.getProperty("os.name");
|
|
|
- if (osName != null) {
|
|
|
- if (osName.contains("Mac")) {
|
|
|
- Runtime.getRuntime().exec("open " + config.getGlobalConfig().getOutputDir());
|
|
|
- } else if (osName.contains("Windows")) {
|
|
|
- Runtime.getRuntime().exec("cmd /c start " + config.getGlobalConfig().getOutputDir());
|
|
|
- } else {
|
|
|
- logger.debug("文件输出目录:" + config.getGlobalConfig().getOutputDir());
|
|
|
- }
|
|
|
- }
|
|
|
- } catch (IOException e) {
|
|
|
- e.printStackTrace();
|
|
|
+ if (null == config) {
|
|
|
+ config = new ConfigBuilder(packageInfo, dataSource, strategy, template, globalConfig);
|
|
|
+ if (null != injectionConfig) {
|
|
|
+ injectionConfig.setConfig(config);
|
|
|
}
|
|
|
}
|
|
|
+ if (null == templateEngine) {
|
|
|
+ // 为了兼容之前逻辑,采用 Velocity 引擎 【 默认 】
|
|
|
+ templateEngine = new VelocityTemplateEngine();
|
|
|
+ }
|
|
|
+ // 模板引擎初始化执行文件输出
|
|
|
+ templateEngine.init(this.pretreatmentConfigBuilder(config)).mkdirs().batchOutput().open();
|
|
|
logger.debug("==========================文件生成完成!!!==========================");
|
|
|
}
|
|
|
|
|
@@ -138,32 +114,25 @@ public class AutoGenerator {
|
|
|
|
|
|
/**
|
|
|
* <p>
|
|
|
- * 分析数据
|
|
|
+ * 预处理配置
|
|
|
* </p>
|
|
|
*
|
|
|
* @param config 总配置信息
|
|
|
* @return 解析数据结果集
|
|
|
*/
|
|
|
- private Map<String, VelocityContext> analyzeData(ConfigBuilder config) {
|
|
|
+ protected ConfigBuilder pretreatmentConfigBuilder(ConfigBuilder config) {
|
|
|
+ /**
|
|
|
+ * 注入自定义配置
|
|
|
+ */
|
|
|
+ if (null != injectionConfig) {
|
|
|
+ injectionConfig.initMap();
|
|
|
+ config.setInjectionConfig(injectionConfig);
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 表信息列表
|
|
|
+ */
|
|
|
List<TableInfo> tableList = this.getAllTableInfoList(config);
|
|
|
- Map<String, String> packageInfo = config.getPackageInfo();
|
|
|
- Map<String, VelocityContext> ctxData = new HashMap<>();
|
|
|
- String superEntityClass = getSuperClassName(config.getSuperEntityClass());
|
|
|
- String superMapperClass = getSuperClassName(config.getSuperMapperClass());
|
|
|
- String superServiceClass = getSuperClassName(config.getSuperServiceClass());
|
|
|
- String superServiceImplClass = getSuperClassName(config.getSuperServiceImplClass());
|
|
|
- String superControllerClass = getSuperClassName(config.getSuperControllerClass());
|
|
|
- String date = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
|
|
|
- VelocityContext ctx;
|
|
|
for (TableInfo tableInfo : tableList) {
|
|
|
- ctx = new VelocityContext();
|
|
|
- if (null != injectionConfig) {
|
|
|
- /**
|
|
|
- * 注入自定义配置
|
|
|
- */
|
|
|
- injectionConfig.initMap();
|
|
|
- ctx.put("cfg", injectionConfig.getMap());
|
|
|
- }
|
|
|
/* ---------- 添加导入包 ---------- */
|
|
|
if (config.getGlobalConfig().isActiveRecord()) {
|
|
|
// 开启 ActiveRecord 模式
|
|
@@ -193,220 +162,17 @@ public class AutoGenerator {
|
|
|
if (field.getPropertyType().equalsIgnoreCase("boolean")) {
|
|
|
if (field.getPropertyName().startsWith("is")) {
|
|
|
field.setPropertyName(config.getStrategyConfig(),
|
|
|
- StringUtils.removePrefixAfterPrefixToLower(field.getPropertyName(), 2));
|
|
|
+ StringUtils.removePrefixAfterPrefixToLower(field.getPropertyName(), 2));
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- // RequestMapping 连字符风格 user-info
|
|
|
- if (config.getStrategyConfig().isControllerMappingHyphenStyle()) {
|
|
|
- ctx.put("controllerMappingHyphenStyle", config.getStrategyConfig().isControllerMappingHyphenStyle());
|
|
|
- ctx.put("controllerMappingHyphen", StringUtils.camelToHyphen(tableInfo.getEntityPath()));
|
|
|
- }
|
|
|
-
|
|
|
- ctx.put("restControllerStyle", config.getStrategyConfig().isRestControllerStyle());
|
|
|
- ctx.put("package", packageInfo);
|
|
|
- GlobalConfig globalConfig = config.getGlobalConfig();
|
|
|
- ctx.put("author", globalConfig.getAuthor());
|
|
|
- ctx.put("idType", globalConfig.getIdType() == null ? null : globalConfig.getIdType().toString());
|
|
|
- ctx.put("logicDeleteFieldName", config.getStrategyConfig().getLogicDeleteFieldName());
|
|
|
- ctx.put("versionFieldName", config.getStrategyConfig().getVersionFieldName());
|
|
|
- ctx.put("activeRecord", globalConfig.isActiveRecord());
|
|
|
- ctx.put("kotlin", globalConfig.isKotlin());
|
|
|
- ctx.put("date", date);
|
|
|
- ctx.put("table", tableInfo);
|
|
|
- ctx.put("enableCache", globalConfig.isEnableCache());
|
|
|
- ctx.put("baseResultMap", globalConfig.isBaseResultMap());
|
|
|
- ctx.put("baseColumnList", globalConfig.isBaseColumnList());
|
|
|
- ctx.put("entity", tableInfo.getEntityName());
|
|
|
- ctx.put("entityColumnConstant", config.getStrategyConfig().isEntityColumnConstant());
|
|
|
- ctx.put("entityBuilderModel", config.getStrategyConfig().isEntityBuilderModel());
|
|
|
- ctx.put("entityLombokModel", config.getStrategyConfig().isEntityLombokModel());
|
|
|
- ctx.put("entityBooleanColumnRemoveIsPrefix", config.getStrategyConfig().isEntityBooleanColumnRemoveIsPrefix());
|
|
|
- ctx.put("superEntityClass", superEntityClass);
|
|
|
- ctx.put("superMapperClassPackage", config.getSuperMapperClass());
|
|
|
- ctx.put("superMapperClass", superMapperClass);
|
|
|
- ctx.put("superServiceClassPackage", config.getSuperServiceClass());
|
|
|
- ctx.put("superServiceClass", superServiceClass);
|
|
|
- ctx.put("superServiceImplClassPackage", config.getSuperServiceImplClass());
|
|
|
- ctx.put("superServiceImplClass", superServiceImplClass);
|
|
|
- ctx.put("superControllerClassPackage", config.getSuperControllerClass());
|
|
|
- ctx.put("superControllerClass", superControllerClass);
|
|
|
- ctxData.put(tableInfo.getEntityName(), ctx);
|
|
|
}
|
|
|
- return ctxData;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * <p>
|
|
|
- * 获取类名
|
|
|
- * </p>
|
|
|
- *
|
|
|
- * @param classPath
|
|
|
- * @return
|
|
|
- */
|
|
|
- private String getSuperClassName(String classPath) {
|
|
|
- if (StringUtils.isEmpty(classPath)) {
|
|
|
- return null;
|
|
|
- }
|
|
|
- return classPath.substring(classPath.lastIndexOf(".") + 1);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * <p>
|
|
|
- * 处理输出目录
|
|
|
- * </p>
|
|
|
- *
|
|
|
- * @param pathInfo 路径信息
|
|
|
- */
|
|
|
- private void mkdirs(Map<String, String> pathInfo) {
|
|
|
- for (Map.Entry<String, String> entry : pathInfo.entrySet()) {
|
|
|
- File dir = new File(entry.getValue());
|
|
|
- if (!dir.exists()) {
|
|
|
- boolean result = dir.mkdirs();
|
|
|
- if (result) {
|
|
|
- logger.debug("创建目录: [" + entry.getValue() + "]");
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * <p>
|
|
|
- * 合成上下文与模板
|
|
|
- * </p>
|
|
|
- *
|
|
|
- * @param context vm上下文
|
|
|
- */
|
|
|
- private void batchOutput(String entityName, VelocityContext context) {
|
|
|
- try {
|
|
|
- TableInfo tableInfo = (TableInfo) context.get("table");
|
|
|
- Map<String, String> pathInfo = config.getPathInfo();
|
|
|
- String entityFile = String.format((pathInfo.get(ConstVal.ENTITY_PATH) + File.separator + "%s" + this.suffixJavaOrKt()), entityName);
|
|
|
- String mapperFile = String.format((pathInfo.get(ConstVal.MAPPER_PATH) + File.separator + tableInfo.getMapperName() + this.suffixJavaOrKt()), entityName);
|
|
|
- String xmlFile = String.format((pathInfo.get(ConstVal.XML_PATH) + File.separator + tableInfo.getXmlName() + ConstVal.XML_SUFFIX), entityName);
|
|
|
- String serviceFile = String.format((pathInfo.get(ConstVal.SERIVCE_PATH) + File.separator + tableInfo.getServiceName() + this.suffixJavaOrKt()), entityName);
|
|
|
- String implFile = String.format((pathInfo.get(ConstVal.SERVICEIMPL_PATH) + File.separator + tableInfo.getServiceImplName() + this.suffixJavaOrKt()), entityName);
|
|
|
- String controllerFile = String.format((pathInfo.get(ConstVal.CONTROLLER_PATH) + File.separator + tableInfo.getControllerName() + this.suffixJavaOrKt()), entityName);
|
|
|
-
|
|
|
- TemplateConfig template = config.getTemplate();
|
|
|
-
|
|
|
- // 根据override标识来判断是否需要创建文件
|
|
|
- if (isCreate(entityFile)) {
|
|
|
- vmToFile(context, template.getEntity(config.getGlobalConfig().isKotlin()), entityFile);
|
|
|
- }
|
|
|
- if (isCreate(mapperFile)) {
|
|
|
- vmToFile(context, template.getMapper(), mapperFile);
|
|
|
- }
|
|
|
- if (isCreate(xmlFile)) {
|
|
|
- vmToFile(context, template.getXml(), xmlFile);
|
|
|
- }
|
|
|
- if (isCreate(serviceFile)) {
|
|
|
- vmToFile(context, template.getService(), serviceFile);
|
|
|
- }
|
|
|
- if (isCreate(implFile)) {
|
|
|
- vmToFile(context, template.getServiceImpl(), implFile);
|
|
|
- }
|
|
|
- if (isCreate(controllerFile)) {
|
|
|
- vmToFile(context, template.getController(), controllerFile);
|
|
|
- }
|
|
|
- if (injectionConfig != null) {
|
|
|
- /**
|
|
|
- * 输出自定义文件内容
|
|
|
- */
|
|
|
- List<FileOutConfig> focList = injectionConfig.getFileOutConfigList();
|
|
|
- if (CollectionUtils.isNotEmpty(focList)) {
|
|
|
- for (FileOutConfig foc : focList) {
|
|
|
- // 判断自定义文件是否存在
|
|
|
- if (isCreate(foc.outputFile(tableInfo))) {
|
|
|
- vmToFile(context, foc.getTemplatePath(), foc.outputFile(tableInfo));
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- } catch (IOException e) {
|
|
|
- logger.error("无法创建文件,请检查配置信息!", e);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 文件后缀
|
|
|
- */
|
|
|
- protected String suffixJavaOrKt() {
|
|
|
- return config.getGlobalConfig().isKotlin() ? ConstVal.KT_SUFFIX : ConstVal.JAVA_SUFFIX;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * <p>
|
|
|
- * 将模板转化成为文件
|
|
|
- * </p>
|
|
|
- *
|
|
|
- * @param context 内容对象
|
|
|
- * @param templatePath 模板文件
|
|
|
- * @param outputFile 文件生成的目录
|
|
|
- */
|
|
|
- private void vmToFile(VelocityContext context, String templatePath, String outputFile) throws IOException {
|
|
|
- if (StringUtils.isEmpty(templatePath)) {
|
|
|
- return;
|
|
|
- }
|
|
|
- VelocityEngine velocity = getVelocityEngine();
|
|
|
- Template template = velocity.getTemplate(templatePath, ConstVal.UTF8);
|
|
|
- File file = new File(outputFile);
|
|
|
- if (!file.getParentFile().exists()) {
|
|
|
- // 如果文件所在的目录不存在,则创建目录
|
|
|
- if (!file.getParentFile().mkdirs()) {
|
|
|
- logger.debug("创建文件所在的目录失败!");
|
|
|
- return;
|
|
|
- }
|
|
|
- }
|
|
|
- FileOutputStream fos = new FileOutputStream(outputFile);
|
|
|
- BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(fos, ConstVal.UTF8));
|
|
|
- template.merge(context, writer);
|
|
|
- writer.close();
|
|
|
- logger.debug("模板:" + templatePath + "; 文件:" + outputFile);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 设置模版引擎,主要指向获取模版路径
|
|
|
- */
|
|
|
- private VelocityEngine getVelocityEngine() {
|
|
|
- if (engine == null) {
|
|
|
- Properties p = new Properties();
|
|
|
- p.setProperty(ConstVal.VM_LOADPATH_KEY, ConstVal.VM_LOADPATH_VALUE);
|
|
|
- p.setProperty(Velocity.FILE_RESOURCE_LOADER_PATH, "");
|
|
|
- p.setProperty(Velocity.ENCODING_DEFAULT, ConstVal.UTF8);
|
|
|
- p.setProperty(Velocity.INPUT_ENCODING, ConstVal.UTF8);
|
|
|
- p.setProperty("file.resource.loader.unicode", "true");
|
|
|
- engine = new VelocityEngine(p);
|
|
|
- }
|
|
|
- return engine;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 检测文件是否存在
|
|
|
- *
|
|
|
- * @return 是否
|
|
|
- */
|
|
|
- private boolean isCreate(String filePath) {
|
|
|
- File file = new File(filePath);
|
|
|
- return !file.exists() || config.getGlobalConfig().isFileOverride();
|
|
|
+ return config.setTableInfoList(tableList);
|
|
|
}
|
|
|
|
|
|
// ================================== 相关配置 ==================================
|
|
|
|
|
|
- /**
|
|
|
- * 初始化配置
|
|
|
- */
|
|
|
- protected void initConfig() {
|
|
|
- if (null == config) {
|
|
|
- config = new ConfigBuilder(packageInfo, dataSource, strategy, template, globalConfig);
|
|
|
- if (null != injectionConfig) {
|
|
|
- injectionConfig.setConfig(config);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
public DataSourceConfig getDataSource() {
|
|
|
return dataSource;
|
|
|
}
|
|
@@ -469,4 +235,13 @@ public class AutoGenerator {
|
|
|
this.injectionConfig = injectionConfig;
|
|
|
return this;
|
|
|
}
|
|
|
+
|
|
|
+ public AbstractTemplateEngine getTemplateEngine() {
|
|
|
+ return templateEngine;
|
|
|
+ }
|
|
|
+
|
|
|
+ public AutoGenerator setTemplateEngine(AbstractTemplateEngine templateEngine) {
|
|
|
+ this.templateEngine = templateEngine;
|
|
|
+ return this;
|
|
|
+ }
|
|
|
}
|