commit f4a0cfdfdc32b0b54d73b095c999c052241fbe34 Author: panxiaohe <1074118755@qq.com> Date: Wed Feb 15 22:10:12 2023 +0800 初始化项目 diff --git a/ceres-generator-master/.gitignore b/ceres-generator-master/.gitignore new file mode 100644 index 0000000..6db043d --- /dev/null +++ b/ceres-generator-master/.gitignore @@ -0,0 +1,2 @@ +.idea +/target diff --git a/ceres-generator-master/ReadMe.md b/ceres-generator-master/ReadMe.md new file mode 100644 index 0000000..3ce4794 --- /dev/null +++ b/ceres-generator-master/ReadMe.md @@ -0,0 +1,12 @@ +[TOC] + +# 介绍 + +本项目为Cereshop多商户版本。 + +专注于客单价,转化率提升!便捷高效,助力各大商家提升客单价,客户引导,提高复购,只为更好的服务每一位用户。 + + + +# 功能 +按照当前项目结构生成后端代码,请参考/src/test/java/CommonGenerator.java的案例 diff --git a/ceres-generator-master/pom.xml b/ceres-generator-master/pom.xml new file mode 100644 index 0000000..15b1d8c --- /dev/null +++ b/ceres-generator-master/pom.xml @@ -0,0 +1,67 @@ + + + + org.springframework.boot + spring-boot-starter-parent + 2.2.6.RELEASE + + 4.0.0 + + com.zkthink + ceres-generator + 1.0 + + + 3.3.1 + 1.18.12 + 8.0.19 + 3.9 + 5.3.1 + + + + com.baomidou + mybatis-plus-generator + ${mybatisplus.version} + + + org.springframework + spring-core + + + + org.freemarker + freemarker + + + org.projectlombok + lombok + ${lombok.version} + + + ch.qos.logback + logback-classic + + + org.apache.commons + commons-lang3 + + + cn.hutool + hutool-all + ${hutool.version} + + + + + + mysql + mysql-connector-java + 6.0.6 + + + + + diff --git a/ceres-generator-master/src/main/java/com/zkthink/ceres/generator/CodeGenerator.java b/ceres-generator-master/src/main/java/com/zkthink/ceres/generator/CodeGenerator.java new file mode 100644 index 0000000..9c9e4ab --- /dev/null +++ b/ceres-generator-master/src/main/java/com/zkthink/ceres/generator/CodeGenerator.java @@ -0,0 +1,269 @@ +package com.zkthink.ceres.generator; + +import com.baomidou.mybatisplus.annotation.DbType; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.core.toolkit.StringPool; +import com.baomidou.mybatisplus.core.toolkit.StringUtils; +import com.baomidou.mybatisplus.generator.AutoGenerator; +import com.baomidou.mybatisplus.generator.InjectionConfig; +import com.baomidou.mybatisplus.generator.config.*; +import com.baomidou.mybatisplus.generator.config.querys.*; +import com.baomidou.mybatisplus.generator.config.rules.DateType; +import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy; +import com.zkthink.ceres.generator.config.CodeGeneratorConfig; +import com.zkthink.ceres.generator.ext.FileOutConfigExt; +import com.zkthink.ceres.generator.ext.FreemarkerTemplateEngineExt; +import com.zkthink.ceres.generator.ext.MySqlQueryExt; +import com.zkthink.ceres.generator.ext.OracleQueryExt; +import com.zkthink.ceres.generator.type.GenerateType; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 代码生成 + * + * @author ceres + * @date 2019/05/25 + */ +public class CodeGenerator { + + public static final String QUERY_PATH = "Query"; + // public static final String API_PATH = "Api"; + public static final String ENUM_PATH = "Enum"; + public static final String CONSTANT_PATH = "Constant"; + public static final String SAVE_DTO_PATH = "SaveDTO"; + public static final String UPDATE_DTO_PATH = "UpdateDTO"; + public static final String PAGE_DTO_PATH = "PageDTO"; + + public static final String SRC_MAIN_JAVA = "src" + File.separator + "main" + File.separator + "java"; + public static final String SRC_MAIN_RESOURCE = "src" + File.separator + "main" + File.separator + "resources"; + + public static void run(final CodeGeneratorConfig config) { + // 代码生成器 + AutoGenerator mpg = new AutoGenerator(); + //项目的根路径 + String projectRootPath = config.getProjectRootPath(); + + //全局配置 + GlobalConfig gc = globalConfig(config, projectRootPath); + mpg.setGlobalConfig(gc); + + // 数据源配置 + DataSourceConfig dsc = dataSourceConfig(config); + mpg.setDataSource(dsc); + + PackageConfig pc = packageConfig(config); + mpg.setPackageInfo(pc); + + // 配置模板 + TemplateConfig templateConfig = new TemplateConfig(); + // 不生成下列文件 + templateConfig.setController(null); + templateConfig.setServiceImpl(null); + templateConfig.setService(null); + templateConfig.setMapper(null); + templateConfig.setXml(null); + templateConfig.setEntity(null); + mpg.setTemplate(templateConfig); + + // 自定义配置 + InjectionConfig cfg = injectionConfig(config, projectRootPath, pc); + mpg.setCfg(cfg); + + // 策略配置 + StrategyConfig strategy = strategyConfig(config); + mpg.setStrategy(strategy); + mpg.setTemplateEngine(new FreemarkerTemplateEngineExt(config)); +// mpg.setTemplateEngine(new FreemarkerTemplateEngine()); + + mpg.execute(); + } + + /** + * 全局配置 + * + * @param config 参数 + * @param projectPath 项目根路径 + * @return + */ + private static GlobalConfig globalConfig(final CodeGeneratorConfig config, String projectPath) { + GlobalConfig gc = new GlobalConfig(); + gc.setOutputDir(String.format("%s/%s", projectPath, SRC_MAIN_JAVA)); + gc.setAuthor(config.getAuthor()); + gc.setOpen(false); + gc.setServiceName("%sService"); + gc.setFileOverride(true); + gc.setBaseResultMap(true); + gc.setBaseColumnList(true); + gc.setDateType(DateType.TIME_PACK); + gc.setIdType(IdType.INPUT); + // 实体属性 Swagger2 注解 + gc.setSwagger2(true); + return gc; + } + + /** + * 数据库设置 + * + * @param config + * @return + */ + private static DataSourceConfig dataSourceConfig(CodeGeneratorConfig config) { + DataSourceConfig dsc = new DataSourceConfig(); + dsc.setUrl(config.getUrl()); + dsc.setDriverName(config.getDriverName()); + dsc.setUsername(config.getUsername()); + dsc.setPassword(config.getPassword()); + if (dsc.getDbType() == DbType.MYSQL) { + dsc.setDbQuery(new MySqlQueryExt()); + } + // oracle 没完全测试 + else if (dsc.getDbType() == DbType.ORACLE) { + dsc.setDbQuery(new OracleQueryExt()); + } + // 以下的都没测试过 + else if (dsc.getDbType() == DbType.DB2) { + dsc.setDbQuery(new DB2Query()); + } else if (dsc.getDbType() == DbType.DM) { + dsc.setDbQuery(new DMQuery()); + } else if (dsc.getDbType() == DbType.H2) { + dsc.setDbQuery(new H2Query()); + } else if (dsc.getDbType() == DbType.MARIADB) { + dsc.setDbQuery(new MariadbQuery()); + } else if (dsc.getDbType() == DbType.POSTGRE_SQL) { + dsc.setDbQuery(new PostgreSqlQuery()); + } else if (dsc.getDbType() == DbType.SQLITE) { + dsc.setDbQuery(new SqliteQuery()); + } else if (dsc.getDbType() == DbType.SQL_SERVER) { + dsc.setDbQuery(new SqlServerQuery()); + } + return dsc; + } + + + private static PackageConfig packageConfig(final CodeGeneratorConfig config) { + PackageConfig pc = new PackageConfig(); +// pc.setModuleName(config.getChildPackageName()); + pc.setParent(config.getPackageBase()); + pc.setMapper("dao"); + if (StringUtils.isNotEmpty(config.getChildPackageName())) { + pc.setMapper(config.getCurrentModule() + StringPool.DOT + pc.getMapper() + StringPool.DOT + config.getChildPackageName()); + pc.setEntity("commons.domain" + StringPool.DOT + config.getChildPackageName()); + pc.setService(config.getCurrentModule() + StringPool.DOT + pc.getService() + StringPool.DOT + config.getChildPackageName()); + pc.setServiceImpl(pc.getService() + StringPool.DOT + "impl"); + pc.setController(config.getCurrentModule() + StringPool.DOT + pc.getController() + StringPool.DOT + config.getChildPackageName()); + } +// pc.setPathInfo(pathInfo(config)); + return pc; + } + + private static StrategyConfig strategyConfig(CodeGeneratorConfig pc) { + StrategyConfig strategy = new StrategyConfig(); + strategy.setNaming(NamingStrategy.underline_to_camel); + strategy.setColumnNaming(NamingStrategy.underline_to_camel); + strategy.setEntityTableFieldAnnotationEnable(true); + strategy.setEntityLombokModel(true); + strategy.setEntityBuilderModel(false); + strategy.setInclude(pc.getTableInclude()); + strategy.setExclude(pc.getTableExclude()); + strategy.setTablePrefix(pc.getTablePrefix()); + strategy.setFieldPrefix(pc.getFieldPrefix()); + strategy.setEntityColumnConstant(GenerateType.IGNORE.neq(pc.getFileCreateConfig().getGenerateConstant())); + strategy.setRestControllerStyle(true); + strategy.setSuperEntityClass(pc.getSuperEntity().getVal()); + strategy.setSuperServiceClass(pc.getSuperServiceClass()); + strategy.setSuperServiceImplClass(pc.getSuperServiceImplClass()); + strategy.setSuperMapperClass(pc.getSuperMapperClass()); + //strategy.setSuperControllerClass(pc.getSuperControllerClass()); + + strategy.setSuperEntityColumns(pc.getSuperEntity().getColumns()); + return strategy; + } + + /** + * InjectionConfig 自定义配置 这里可以进行包路径的配置,自定义的代码生成器的接入配置。这里定义了xmlmapper 及query两个文件的自动生成配置 + */ + private static InjectionConfig injectionConfig(final CodeGeneratorConfig config, String projectRootPath, PackageConfig pc) { + InjectionConfig cfg = new InjectionConfig() { + @Override + public void initMap() { + Map map = initImportPackageInfo(config.getPackageBase(), config.getChildPackageName()); + this.setMap(map); + } + }; + cfg.setFileCreate(config.getFileCreateConfig()); + + // 自定义输出配置 + cfg.setFileOutConfigList(getFileConfig(config)); + return cfg; + } + + /** + * 配置包信息 配置规则是: parentPackage + "层" + "模块" + */ + public static Map initImportPackageInfo(String parentPackage, String childPackageName) { + Map packageMap = new HashMap<>(); + if (childPackageName != null && !"".equals(childPackageName.trim())) { + childPackageName = "." + childPackageName; + } + +// packageMap.put(API_PATH, parentPackage + ".api" + childPackageName); +// packageMap.put(ConstVal.CONTROLLER, parentPackage + ".controller" + childPackageName); + +// packageMap.put(ConstVal.SERVICE, parentPackage + ".service" + childPackageName); +// packageMap.put(ConstVal.SERVICE_IMPL, parentPackage + ".service" + childPackageName + ".impl"); + +// packageMap.put(ConstVal.MAPPER, parentPackage + ".dao" + childPackageName); + packageMap.put(QUERY_PATH, parentPackage + ".query" + childPackageName); +// packageMap.put(ConstVal.ENTITY, parentPackage + ".entity" + childPackageName); + + packageMap.put(ENUM_PATH, parentPackage + ".entity" + childPackageName); + packageMap.put(CONSTANT_PATH, parentPackage + ".constant" + childPackageName); + packageMap.put("constantSuffix", "Constant"); +// packageMap.put(DTO_PATH, parentPackage + ".dto" + childPackageName); + packageMap.put(SAVE_DTO_PATH, parentPackage + ".dto" + childPackageName); + packageMap.put(UPDATE_DTO_PATH, parentPackage + ".dto" + childPackageName); + packageMap.put(PAGE_DTO_PATH, parentPackage + ".dto" + childPackageName); + + return packageMap; + } + + private static List getFileConfig(CodeGeneratorConfig config) { + List focList = new ArrayList<>(); + + String projectRootPath = config.getProjectRootPath(); + if (!projectRootPath.endsWith(File.separator)) { + projectRootPath += File.separator; + } + String packageBase = config.getPackageBase().replace(".", File.separator); + + StringBuilder basePathSb = new StringBuilder(projectRootPath).append("%s"); + basePathSb.append(SRC_MAIN_JAVA).append(File.separator) + .append(packageBase) + .toString(); + + final String basePath = basePathSb.toString(); + + focList.add(new FileOutConfigExt(basePath, ConstVal.CONTROLLER, config)); + focList.add(new FileOutConfigExt(basePath, ConstVal.SERVICE, config)); + focList.add(new FileOutConfigExt(basePath, ConstVal.SERVICE_IMPL, config)); + focList.add(new FileOutConfigExt(basePath, ConstVal.MAPPER, config)); + focList.add(new FileOutConfigExt(basePath, ConstVal.XML, config)); + + focList.add(new FileOutConfigExt(basePath, QUERY_PATH, config)); + focList.add(new FileOutConfigExt(basePath, CONSTANT_PATH, config)); + + //focList.add(new FileOutConfigExt(basePath, DTO_PATH, config)); + //focList.add(new FileOutConfigExt(basePath, SAVE_DTO_PATH, config)); + //focList.add(new FileOutConfigExt(basePath, UPDATE_DTO_PATH, config)); + //focList.add(new FileOutConfigExt(basePath, PAGE_DTO_PATH, config)); + + return focList; + } + + +} diff --git a/ceres-generator-master/src/main/java/com/zkthink/ceres/generator/ProjectGenerator.java b/ceres-generator-master/src/main/java/com/zkthink/ceres/generator/ProjectGenerator.java new file mode 100644 index 0000000..8c2b4d4 --- /dev/null +++ b/ceres-generator-master/src/main/java/com/zkthink/ceres/generator/ProjectGenerator.java @@ -0,0 +1,330 @@ +package com.zkthink.ceres.generator; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.toolkit.StringPool; +import com.baomidou.mybatisplus.generator.config.ConstVal; +import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine; +import com.zkthink.ceres.generator.config.CodeGeneratorConfig; +import freemarker.template.Configuration; +import freemarker.template.Template; +import lombok.extern.slf4j.Slf4j; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.OutputStreamWriter; +import java.nio.file.Paths; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +/** + * 项目生成工具 + * + * @author ceres + * @date 2019/05/25 + */ +@Slf4j +public class ProjectGenerator { + /** + * 项目模块名称 + */ + private final static String API = "api"; + private final static String ENTITY = "entity"; + private final static String BIZ = "biz"; + private final static String CONTROLLER = "controller"; + private final static String SERVER = "server"; + + + private final static String[] ALL_MODULAR_LIST = new String[]{ + API, ENTITY, BIZ, CONTROLLER, SERVER, + }; + private final static String[] CHILD_MODULAR_LIST = new String[]{ + BIZ, CONTROLLER + }; + + /** + * 模板路径 + */ + private static final String INIT_JAVA_FTL = "init/java/%s.java.ftl"; + private static final String INIT_RESOURCES_FTL = "init/resources/%s.java.ftl"; + private static final String INIT_FTL = "init/pom/%s.java.ftl"; + + private final static String SRC_MAIN_JAVA = "src/main/java"; + private final static String SRC_MAIN_RESOURCES = "src/main/resources"; + private final static String[] MAVEN_PATH = new String[]{ + SRC_MAIN_JAVA, SRC_MAIN_RESOURCES, "src/test/java", "src/test/resources" + }; + + private Configuration configuration; + private CodeGeneratorConfig config; + + public ProjectGenerator(CodeGeneratorConfig config) { + this.init(); + this.config = config; + } + + + private void init() { + this.configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS); + this.configuration.setDefaultEncoding(ConstVal.UTF8); + this.configuration.setClassForTemplateLoading(FreemarkerTemplateEngine.class, StringPool.SLASH); + } + + public void build() { + boolean isChildModule = !this.config.getServiceName().equalsIgnoreCase(this.config.getChildModuleName()); + + // 创建项目跟文件夹 + File parentPath = new File(this.config.getProjectRootPath()); + if (!parentPath.exists()) { + parentPath.mkdirs(); + } + + //创建服务文件夹 + String serviceName = this.config.getProjectPrefix() + this.config.getServiceName(); + log.info("服务名:{}", serviceName); + String servicePath = Paths.get(this.config.getProjectRootPath(), serviceName).toString(); + Map objectMap = this.getObjectMap(this.config); + + String[] modularList = ALL_MODULAR_LIST; + if (isChildModule) { + modularList = CHILD_MODULAR_LIST; + } + for (String modular : modularList) { + //创建模块文件夹 + String modularPath = this.mkModular(servicePath, serviceName, modular, isChildModule); + + this.mkMaven(modularPath); + this.mkBasePackage(modularPath); + + this.generatorPom(objectMap, String.format(INIT_FTL, modular), modularPath); + } + + if (!isChildModule) { + //根 pom + this.writer(objectMap, String.format(INIT_FTL, "pom"), Paths.get(servicePath, "pom.xml").toString()); + + // api 模块 生成在 ceres-api 模块下 +// this.generatorApiModular(serviceName, objectMap); + + // server 模块 + String serverApplicationPath = this.mkServer(servicePath, serviceName); + this.generatorServerJava(objectMap, serverApplicationPath); + + String modularName = serviceName + "-" + SERVER; + String serverResourcePath = Paths.get(servicePath, modularName, SRC_MAIN_RESOURCES).toString(); + this.generatorServerResources(objectMap, serverResourcePath); + } else { + String modulerName = this.config.getProjectPrefix() + this.config.getChildModuleName(); + System.err.println("------------------------------------------"); + System.err.println(String.format("生成完毕,请将以下配置手工加入:%s/pom.xml", serviceName)); + System.err.println(String.format( + " \n" + + " %s\n" + + " %s-biz\n" + + " ${project.version}\n" + + " ", config.getGroupId(), modulerName)); + System.err.println(String.format( + " \n" + + " %s\n" + + " %s-controller\n" + + " ${project.version}\n" + + " ", config.getGroupId(), modulerName)); + System.err.println(""); + System.err.println(String.format( + " %s-biz\n" + + " %s-controller", modulerName, modulerName)); + + System.err.println("------------------------------------------"); + System.err.println(String.format("生成完毕,请将以下配置手工加入:%s/%s/pom.xml", serviceName, serviceName + "-server")); + + System.err.println(String.format( + " \n" + + " %s\n" + + " %s-controller\n" + + " ", config.getGroupId(), modulerName)); + } + + System.err.println("生成完毕,但请手动完成以下操作:"); + System.err.println("------------------------------------------"); + System.err.println(String.format("将以下配置手工加入:%s/pom.xml", this.config.getProjectPrefix() + "admin-cloud")); + System.err.println(String.format(" %s", serviceName)); + + System.err.println("------------------------------------------"); + String projectName = serviceName + "-server"; + String nacosProject = serviceName + "-server.yml"; + System.err.println(String.format("在nacos中新建一个名为: %s 的配置文件,并将: %s/src/main/resources/%s 配置文件的内容移动过去", nacosProject, projectName, nacosProject)); + + System.err.println("------------------------------------------"); + System.err.println("将下面的配置手动加入nacos中 ceres-zuul-server.yml"); + System.err.println(String.format(" %s:\n" + + " path: /%s/**\n" + + " serviceId: %s-server", config.getServiceName(), config.getServiceName(), serviceName)); + + System.err.println("------------------------------------------"); + System.err.println("将下面的配置手动加入nacos中 ceres-gateway-server.yml"); + System.err.println(String.format(" - id: %s\n" + + " uri: lb://%s-server\n" + + " predicates:\n" + + " - Path=/%s/**\n" + + " filters:\n" + + " - StripPrefix=1\n" + + " - name: Hystrix\n" + + " args:\n" + + " name: default\n" + + " fallbackUri: 'forward:/fallback'", config.getServiceName(), serviceName, config.getServiceName())); + + } + + private void generatorApiModular(String serviceName, Map objectMap) { + String apiName = this.config.getProjectPrefix() + "api"; + String apiModularName = serviceName + "-api"; + log.info("已经生成模块:{}", apiModularName); + String apiPath = Paths.get(this.config.getProjectRootPath(), apiName, apiModularName).toString(); + File apiPathFile = new File(apiPath); + if (!apiPathFile.exists()) { + apiPathFile.mkdirs(); + } + this.mkMaven(apiPath); + this.generatorPom(objectMap, String.format(INIT_FTL, "api"), apiPath); + } + + private void generatorServerResources(Map objectMap, String serverResourcePath) { + this.writer(objectMap, String.format(INIT_RESOURCES_FTL, "banner"), Paths.get(serverResourcePath, "banner.txt").toString()); + this.writer(objectMap, String.format(INIT_RESOURCES_FTL, "bootstrap"), Paths.get(serverResourcePath, "bootstrap.yml").toString()); + this.writer(objectMap, String.format(INIT_RESOURCES_FTL, "logback-spring"), Paths.get(serverResourcePath, "logback-spring.xml").toString()); + this.writer(objectMap, String.format(INIT_RESOURCES_FTL, "spy"), Paths.get(serverResourcePath, "spy.properties").toString()); + + //dev 废除 +// String serviceNameDev = this.config.getProjectPrefix() + this.config.getServiceName() + "-server-dev.yml"; +// this.writer(objectMap, String.format(INIT_RESOURCES_FTL, "application-dev"), Paths.get(serverResourcePath, serviceNameDev).toString()); + String serviceName = this.config.getProjectPrefix() + this.config.getServiceName() + "-server.yml"; + this.writer(objectMap, String.format(INIT_RESOURCES_FTL, "application"), Paths.get(serverResourcePath, serviceName).toString()); + } + + /** + * 生成 server项目下的jar代码 + * + * @param objectMap + * @param serverApplicationPath + */ + private void generatorServerJava(Map objectMap, String serverApplicationPath) { + Object service = objectMap.get("service"); + + String serverApplicationParentPath = StrUtil.subPre(serverApplicationPath, serverApplicationPath.lastIndexOf(File.separator)); + //启动类 + this.writer(objectMap, String.format(INIT_JAVA_FTL, "Application"), Paths.get(serverApplicationParentPath, service + "ServerApplication.java").toString()); + // 通用控制器 +// this.writer(objectMap, String.format(INIT_JAVA_FTL, "GeneralController"), Paths.get(serverApplicationParentPath, "general", "controller", service + "GeneralController.java").toString()); + + String serverConfigPath = Paths.get(serverApplicationPath, "config").toString(); + // 全局异常 + this.writer(objectMap, String.format(INIT_JAVA_FTL, "ExceptionConfiguration"), Paths.get(serverConfigPath, service + "ExceptionConfiguration.java").toString()); + //Web + this.writer(objectMap, String.format(INIT_JAVA_FTL, "WebConfiguration"), Paths.get(serverConfigPath, service + "WebConfiguration.java").toString()); + //数据源 + this.writer(objectMap, String.format(INIT_JAVA_FTL, "DatabaseAutoConfiguration"), Paths.get(serverConfigPath, "datasource", service + "DatabaseAutoConfiguration.java").toString()); + this.writer(objectMap, String.format(INIT_JAVA_FTL, "MybatisAutoConfiguration"), Paths.get(serverConfigPath, "datasource", service + "MybatisAutoConfiguration.java").toString()); + } + + private String mkServer(String servicePath, String serviceName) { + String modularName = serviceName + "-" + SERVER; + String packageBase = this.config.getPackageBase().replace(".", File.separator); + + String serverApplicationPath = Paths.get(servicePath, modularName, SRC_MAIN_JAVA, packageBase).toString(); + String modularConfigPath = Paths.get(serverApplicationPath, "config").toString(); + File modularConfigFile = new File(modularConfigPath); + if (!modularConfigFile.exists()) { + modularConfigFile.mkdirs(); + } + return serverApplicationPath; + } + + + private Map getObjectMap(CodeGeneratorConfig globalConfig) { + boolean isChildModule = !this.config.getServiceName().equalsIgnoreCase(this.config.getChildModuleName()); + Map objectMap = new HashMap<>(); + objectMap.put("author", globalConfig.getAuthor()); + objectMap.put("serviceName", globalConfig.getServiceName()); + objectMap.put("isChildModule", isChildModule); + objectMap.put("childModuleName", globalConfig.getChildModuleName()); + objectMap.put("packageBase", globalConfig.getPackageBase()); + objectMap.put("projectPrefix", globalConfig.getProjectPrefix()); + objectMap.put("service", StrUtil.upperFirst(globalConfig.getServiceName())); + objectMap.put("date", new SimpleDateFormat("yyyy-MM-dd").format(new Date())); + objectMap.put("version", globalConfig.getVersion()); + objectMap.put("packageBaseParent", globalConfig.getPackageBaseParent()); + objectMap.put("serverPort", globalConfig.getServerPort()); + objectMap.put("groupId", globalConfig.getGroupId()); + objectMap.put("description", globalConfig.getDescription()); + return objectMap; + } + + + private void writer(Map objectMap, String templatePath, String outputFile) { + File file = new File(outputFile); + if (!file.getParentFile().exists()) { + file.getParentFile().mkdirs(); + } + try { + Template template = this.configuration.getTemplate(templatePath); + try (FileOutputStream fileOutputStream = new FileOutputStream(file)) { + template.process(objectMap, new OutputStreamWriter(fileOutputStream, ConstVal.UTF8)); + } + } catch (Exception e) { + log.error("生成失败", e); + } + } + + /** + * 生成pom + * + * @param templatePath + */ + private void generatorPom(Map objectMap, String templatePath, String outputFile) { + this.writer(objectMap, templatePath, Paths.get(outputFile, "pom.xml").toString()); + } + + + private String mkModular(String servicePath, String serviceName, String modular, boolean isChildModule) { + //String modularName = serviceName + "-" + modular; + String modularName = modular; + if (isChildModule) { + String childModuleName = this.config.getProjectPrefix() + this.config.getChildModuleName(); + modularName = childModuleName + "-" + modular; + } + log.info("已经生成模块:{}", modularName); + String modularPath = Paths.get(servicePath, modularName).toString(); + File modularPathFile = new File(modularPath); + if (!modularPathFile.exists()) { + modularPathFile.mkdirs(); + } + return modularPath; + } + + + /** + * 创建 maven 目录文件夹 + * + * @param modularPath + */ + private void mkMaven(String modularPath) { + for (String maven : MAVEN_PATH) { + String mavenPath = Paths.get(modularPath, maven).toString(); + File mavenPathFile = new File(mavenPath); + if (!mavenPathFile.exists()) { + mavenPathFile.mkdirs(); + } + } + } + + private void mkBasePackage(String modularPath) { + String basePackage = Paths.get(modularPath, SRC_MAIN_JAVA, StrUtil.replace(config.getPackageBase(), ".", File.separator)).toString(); + File mavenPathFile = new File(basePackage); + if (!mavenPathFile.exists()) { + mavenPathFile.mkdirs(); + } + + + } +} diff --git a/ceres-generator-master/src/main/java/com/zkthink/ceres/generator/config/CodeGeneratorConfig.java b/ceres-generator-master/src/main/java/com/zkthink/ceres/generator/config/CodeGeneratorConfig.java new file mode 100644 index 0000000..43d887c --- /dev/null +++ b/ceres-generator-master/src/main/java/com/zkthink/ceres/generator/config/CodeGeneratorConfig.java @@ -0,0 +1,253 @@ +package com.zkthink.ceres.generator.config; + + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.toolkit.StringUtils; +import com.zkthink.ceres.generator.model.GenTableColumn; +import com.zkthink.ceres.generator.type.EntityFiledType; +import com.zkthink.ceres.generator.type.EntityType; +import com.zkthink.ceres.generator.type.SuperClass; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.io.File; +import java.util.*; + +/** + * 代码生成配置 + *

+ * 微服务项目默认会创建4个项目, + * cloud-authority-api、cloud-authority-rest、cloud-authority-entity、cloud-authority-repository + * 匹配符为:${projectPrefix}${serviceName}-${apiSuffix} + *

+ * 然后在每个项目的src/main/java下创建包: + * ${packageBase}.api.${childModuleName} + * ${packageBase}.rest.${childModuleName} + * ${packageBase}.entity.${childModuleName} + * ${packageBase}.enumeration.${childModuleName} + * ${packageBase}.constant.${childModuleName} + * ${packageBase}.dto.${childModuleName} + * ${packageBase}.service.${childModuleName} + * ${packageBase}.service.${childModuleName}.impl + * ${packageBase}.dao.${childModuleName} + * ${projectPrefix}${serviceName}-${serviceSuffix}项目的src/main/resource下创建包: + * mapper_${serviceName}.base.${childModuleName} + * + * @author ceres + * @date 2019年05月25日20:59:57 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Accessors(chain = true) +public class CodeGeneratorConfig { + + /** + * 项目跟路径 + */ + String projectRootPath = System.getProperty("user.dir"); + /** + * 服务名 + * 如消息服务 (用于创建cloud-%s-api、cloud-%s-entity等项目) + */ + String serviceName = ""; + /** + * 子模块名称 + * 如消息服务(cloud-msgs-new)包含消息、短信、邮件3个模块 + * 则分别填入 msgs、sms、email + * (用于创建cloud-%s-rest、cloud-%s-repository等项目) + */ + String childModuleName = ""; + /** + * 基础包 所有的代码都放置在这个包之下 + */ + String packageBase = "com.zkthink.authority"; + + /** + * common包 用于存放基础类 + */ + String packageCommon = "com.shop.cereshop.commons"; + + /** + * 子包名称 + * 会在api、controller、service、serviceImpl、dao、entity等包下面创建子包 + */ + String childPackageName = ""; + /** + * 作者 + */ + String author = "ceres"; + + /** + * 是否需要生成admin包的内容 + */ + boolean needAdmin = true; + + /** + * 是否需要生成app包的内容 + */ + boolean needApp = true; + + /** + * 是否需要生成business包的内容 + */ + boolean needBusiness = true; + + /** + * 项目统一前缀 比如: cloud- + */ + private String projectPrefix = "cereshop"; + + private String apiSuffix = "-api"; + private String entitySuffix = "-commons"; + private String adminSuffix = "-admin"; + private String appSuffix = "-app"; + private String businessSuffix = "-business"; + private String serviceSuffix = "-biz"; + private String controllerSuffix = "-controller"; + /** + * 版本 + */ + String version = "1.0-SNAPSHOT"; + /** + * 端口号 + */ + String serverPort = "8080"; + String groupId = "com.zkthin"; + String description = "服务"; +// private String serverSuffix = "-server"; + + public String getPackageBaseParent() { + return StrUtil.subPre(this.packageBase, this.packageBase.lastIndexOf(".")); + } + + /** + * entity的父类 + */ + private EntityType superEntity = EntityType.ENTITY; + /** + * controller的父类 + */ + private String superControllerClass = SuperClass.SUPER_CLASS.getController(); + + /** + * 自定义继承的Mapper类全称,带包名 + */ + private String superMapperClass = SuperClass.SUPER_CLASS.getMapper(); + /** + * 自定义继承的Service类全称,带包名 + */ + private String superServiceClass = SuperClass.SUPER_CLASS.getService(); + /** + * 自定义继承的ServiceImpl类全称,带包名 + */ + private String superServiceImplClass = SuperClass.SUPER_CLASS.getServiceImpl(); + /** + * 表前缀 + */ + private String tablePrefix = ""; + /** + * 字段前缀 + */ + private String fieldPrefix = ""; + /** + * 需要包含的表名,允许正则表达式;用来自动生成代码 + */ + private String[] tableInclude = {"c_user"}; + /** + * 基础的xml路径 + */ +// private String xmlPath = ""; + private String[] tableExclude = {}; + /** + * 驱动连接的URL + */ + private String url = "jdbc:mysql://127.0.0.1:3306/ceres_base_0000?serverTimezone=CTT&characterEncoding=utf8&useUnicode=true&useSSL=false&autoReconnect=true&zeroDateTimeBehavior=convertToNull"; + /** + * 驱动名称 + */ + private String driverName = "com.mysql.cj.jdbc.Driver"; + /** + * 数据库连接用户名 + */ + private String username = "root"; + /** + * 数据库连接密码 + */ + private String password = "root"; + /** + * 仅仅在微服务架构下面才进行分包 + */ + private boolean enableMicroService = true; + + private FileCreateConfig fileCreateConfig = new FileCreateConfig(); + /** + * 需要制定生成路径的枚举类列表 + */ + private Set filedTypes = new HashSet<>(); + + /** + * 当前处理的模块 + */ + private String currentModule = null; + + /** + * + */ + public final static String[] CERESHOP_MODULAR_LIST = new String[]{ + "admin", "app", "business" + }; + + private Vue vue = new Vue(); + + @Data + public static class Vue { + private String viewsPath = "views" + File.separator + "ceres"; + + /** + * 表名 - <字段名 - 字段信息> + */ + private Map> tableFieldMap = new HashMap<>(); + } + + /** + * 必填项 构造器 + * + * @param serviceName 服务名 + * eg: msgs + * @param childModuleName 子模块名 + * eg: sms、emial + * @param author 作者 + * @param tablePrefix 表前缀 + * @param tableInclude 生成的表 支持通配符 + * eg: msgs_.* 会生成msgs_开头的所有表 + * @return + */ + public static CodeGeneratorConfig build(String serviceName, String childModuleName, String author, String tablePrefix, List tableInclude) { + CodeGeneratorConfig config = new CodeGeneratorConfig(); + config.setServiceName(serviceName).setAuthor(author).setTablePrefix(tablePrefix) + .setTableInclude(tableInclude.stream().toArray(String[]::new)) + .setChildModuleName(childModuleName == null ? "" : childModuleName); + config.setPackageBase("com.zkthink." + config.getChildModuleName()); + return config; + } + + + public static CodeGeneratorConfig buildVue(String serviceName, String tablePrefix, List tableInclude) { + CodeGeneratorConfig config = new CodeGeneratorConfig(); + config.setServiceName(serviceName).setTablePrefix(tablePrefix) + .setTableInclude(tableInclude.stream().toArray(String[]::new)) + .setChildModuleName(""); + config.setPackageBase("com.zkthink." + config.getChildModuleName()); + return config; + } + + public String getChildModuleName() { + if (StringUtils.isBlank(this.childModuleName)) { + this.childModuleName = this.serviceName; + } + return this.childModuleName; + } +} diff --git a/ceres-generator-master/src/main/java/com/zkthink/ceres/generator/config/FileCreateConfig.java b/ceres-generator-master/src/main/java/com/zkthink/ceres/generator/config/FileCreateConfig.java new file mode 100644 index 0000000..6610ba1 --- /dev/null +++ b/ceres-generator-master/src/main/java/com/zkthink/ceres/generator/config/FileCreateConfig.java @@ -0,0 +1,235 @@ +package com.zkthink.ceres.generator.config; + +import com.baomidou.mybatisplus.generator.config.IFileCreate; +import com.baomidou.mybatisplus.generator.config.builder.ConfigBuilder; +import com.baomidou.mybatisplus.generator.config.rules.FileType; +import com.zkthink.ceres.generator.ext.FileOutConfigExt; +import com.zkthink.ceres.generator.type.GenerateType; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.io.File; + +/** + * 文件创建配置类 + * + * @author ceres + * @date 2019-05-25 + */ +@Data +@Accessors(chain = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class FileCreateConfig implements IFileCreate { + + private GenerateType generate; + private GenerateType generateEnum = GenerateType.OVERRIDE; + private GenerateType generateEntity = GenerateType.OVERRIDE; + private GenerateType generateConstant = GenerateType.IGNORE; + private GenerateType generateDao = GenerateType.IGNORE; + private GenerateType generateXml = GenerateType.IGNORE; + private GenerateType generateService = GenerateType.IGNORE; + private GenerateType generateServiceImpl = GenerateType.IGNORE; + private GenerateType generateController = GenerateType.IGNORE; + + private GenerateType generateDto = GenerateType.IGNORE; + private GenerateType generateQuery = GenerateType.IGNORE; + + private GenerateType generateApi = GenerateType.IGNORE; + private GenerateType generatePageIndex = GenerateType.IGNORE; + private GenerateType generateTreeIndex = GenerateType.IGNORE; + private GenerateType generateEdit = GenerateType.IGNORE; + private Boolean isVue = false; + + /** + * 指定了generate后, 会覆盖 controller、service、dao等生成策略 + * + * @param generate + */ + public FileCreateConfig(GenerateType generate) { + this.generate = generate; + if (generate != null) { + this.generateEntity = generate; + this.generateDao = generate; + this.generateXml = generate; + this.generateService = generate; + this.generateServiceImpl = generate; + this.generateController = generate; + this.generateEnum = generate; + this.generateDto = generate; + } + this.generateConstant = GenerateType.IGNORE; + this.generateQuery = GenerateType.IGNORE; + this.generateApi = GenerateType.IGNORE; + } + + public FileCreateConfig(GenerateType generate, boolean isVue) { + this.generate = generate; + this.isVue = isVue; + if (isVue) { + this.generateEntity = GenerateType.IGNORE; + this.generateDao = GenerateType.IGNORE; + this.generateXml = GenerateType.IGNORE; + this.generateService = GenerateType.IGNORE; + this.generateServiceImpl = GenerateType.IGNORE; + this.generateController = GenerateType.IGNORE; + this.generateEnum = GenerateType.IGNORE; + this.generateDto = GenerateType.IGNORE; + + //index 和 Tree 只能生成一种 + if (GenerateType.OVERRIDE.eq(this.generatePageIndex)) { + this.generateTreeIndex = GenerateType.IGNORE; + } else if (GenerateType.OVERRIDE.eq(this.generateTreeIndex)) { + this.generatePageIndex = GenerateType.IGNORE; + this.generateEdit = GenerateType.IGNORE; + } + + if (generate != null) { + this.generateApi = generate; + this.generatePageIndex = generate; + this.generateTreeIndex = GenerateType.IGNORE; + this.generateEdit = generate; + } + } else { + this.generateConstant = GenerateType.IGNORE; + this.generateQuery = GenerateType.IGNORE; + if (generate != null) { + this.generateEntity = generate; + this.generateDao = generate; + this.generateXml = generate; + this.generateService = generate; + this.generateServiceImpl = generate; + this.generateController = generate; + this.generateEnum = generate; + this.generateDto = generate; + } + } + + } + + /** + * 判断文件是否存在 + * + * @param path 路径 + */ + public static boolean isExists(String path) { + File file = new File(path); + return file.exists(); + } + + @Override + public boolean isCreate(ConfigBuilder configBuilder, FileType fileType, String filePath) { + File file = new File(filePath); + if (this.generate != null) { + if (filePath.contains(File.separator + "constant" + File.separator)) { + return isCreate(generateConstant, file); + } + if (filePath.contains(File.separator + "query" + File.separator)) { + return isCreate(generateQuery, file); + } + + // api.js + if (filePath.contains(File.separator + "api" + File.separator)) { + return isCreate(generateApi, file); + } + //edit.vue + if (filePath.endsWith("Edit" + FileOutConfigExt.DOT_VUE)) { + return isCreate(generateEdit, file); + } + //Index.vue + if (filePath.endsWith("Index" + FileOutConfigExt.DOT_VUE)) { + return isCreate(generatePageIndex, file); + } + //Tree.vue + if (filePath.endsWith("Tree" + FileOutConfigExt.DOT_VUE)) { + return isCreate(generateTreeIndex, file); + } + + return isCreate(generate, file); + } + //实体 + if (FileType.ENTITY == fileType) { + return isCreate(generateEntity, file); + //控制器 + } else if (FileType.CONTROLLER == fileType) { + return isCreate(generateController, file); + //dao + } else if (FileType.XML == fileType) { + return isCreate(generateXml, file); + } else if (FileType.MAPPER == fileType) { + return isCreate(generateDao, file); + //service + } else if (FileType.SERVICE == fileType) { + return isCreate(generateService, file); + } else if (FileType.SERVICE_IMPL == fileType) { + return isCreate(generateServiceImpl, file); + } else if (FileType.OTHER == fileType) { + if (filePath.contains(File.separator + "enumeration" + File.separator)) { + return isCreate(generateEnum, file); + } + if (filePath.contains(File.separator + "constant" + File.separator)) { + return isCreate(generateConstant, file); + } + if (filePath.contains(File.separator + "query" + File.separator)) { + return isCreate(generateQuery, file); + } + if (filePath.contains(File.separator + "entity" + File.separator)) { + return isCreate(generateEntity, file); + } + if (filePath.contains(File.separator + "dto" + File.separator)) { + return isCreate(generateDto, file); + } + //控制器 + if (filePath.contains(File.separator + "controller" + File.separator)) { + return isCreate(generateController, file); + } + //dao + if (filePath.contains(File.separator + "mapper_")) { + return isCreate(generateXml, file); + } + if (filePath.contains(File.separator + "dao" + File.separator)) { + return isCreate(generateDao, file); + } + if (filePath.contains(File.separator + "service" + File.separator)) { + return isCreate(generateService, file); + } + if (filePath.contains(File.separator + "impl" + File.separator)) { + return isCreate(generateServiceImpl, file); + } + + // api.js + if (filePath.contains(File.separator + "api" + File.separator)) { + return isCreate(generateApi, file); + } + //edit.vue + if (filePath.endsWith("Edit" + FileOutConfigExt.DOT_VUE)) { + return isCreate(generateEdit, file); + } + //Index.vue + if (filePath.endsWith("Index" + FileOutConfigExt.DOT_VUE)) { + return isCreate(generatePageIndex, file); + } + //Tree.vue + if (filePath.endsWith("Tree" + FileOutConfigExt.DOT_VUE)) { + return isCreate(generateTreeIndex, file); + } + + } + return true; + } + + private boolean isCreate(GenerateType gen, File file) { + if (GenerateType.IGNORE.eq(gen)) { + return false; + } + if (!file.exists()) { + file.getParentFile().mkdirs(); + } + return true; + } + +} diff --git a/ceres-generator-master/src/main/java/com/zkthink/ceres/generator/ext/FileOutConfigExt.java b/ceres-generator-master/src/main/java/com/zkthink/ceres/generator/ext/FileOutConfigExt.java new file mode 100644 index 0000000..1a4c64b --- /dev/null +++ b/ceres-generator-master/src/main/java/com/zkthink/ceres/generator/ext/FileOutConfigExt.java @@ -0,0 +1,192 @@ +package com.zkthink.ceres.generator.ext; + +import com.baomidou.mybatisplus.core.toolkit.StringPool; +import com.baomidou.mybatisplus.core.toolkit.StringUtils; +import com.baomidou.mybatisplus.generator.config.ConstVal; +import com.baomidou.mybatisplus.generator.config.FileOutConfig; +import com.baomidou.mybatisplus.generator.config.po.TableInfo; +import com.zkthink.ceres.generator.CodeGenerator; +import com.zkthink.ceres.generator.config.CodeGeneratorConfig; +import com.zkthink.ceres.generator.config.FileCreateConfig; +import com.zkthink.ceres.generator.type.GenerateType; + +import java.io.File; +import java.nio.file.Paths; + +/** + * 文件输出扩展 + * + * @author ceres + * @date 2019/05/26 + */ +public class FileOutConfigExt extends FileOutConfig { + public static final String DOT_VUE = ".vue"; + public static final String DOT_JS = ".js"; + String innerBasePath; + + String projectSuffix; + String modularSuffix; + GenerateType generateType; + CodeGeneratorConfig config; + + public FileOutConfigExt(String innerBasePath, String modularSuffix, CodeGeneratorConfig config) { + this.innerBasePath = innerBasePath; + this.modularSuffix = modularSuffix; + this.projectSuffix = "-" + config.getCurrentModule(); + this.config = config; + FileCreateConfig fileCreateConfig = config.getFileCreateConfig(); + switch (modularSuffix) { + case CodeGenerator.ENUM_PATH: + this.setTemplatePath("/templates/enum.java.ftl"); + this.generateType = fileCreateConfig.getGenerateEnum(); + break; + case CodeGenerator.SAVE_DTO_PATH: + this.setTemplatePath("/templates/saveDto.java.ftl"); + this.generateType = fileCreateConfig.getGenerateDto(); + break; + case CodeGenerator.PAGE_DTO_PATH: + this.setTemplatePath("/templates/pageDto.java.ftl"); + this.generateType = fileCreateConfig.getGenerateDto(); + break; + case CodeGenerator.UPDATE_DTO_PATH: + this.setTemplatePath("/templates/updateDto.java.ftl"); + this.generateType = fileCreateConfig.getGenerateDto(); + break; + case CodeGenerator.CONSTANT_PATH: + this.setTemplatePath("/templates/constant.java.ftl"); + this.generateType = fileCreateConfig.getGenerateConstant(); + break; + case CodeGenerator.QUERY_PATH: + this.setTemplatePath("/templates/query.java.ftl"); + this.generateType = fileCreateConfig.getGenerateQuery(); + break; + case ConstVal.ENTITY: + this.setTemplatePath(ConstVal.TEMPLATE_ENTITY_JAVA + ".ftl"); + this.generateType = fileCreateConfig.getGenerateEntity(); + break; + case ConstVal.SERVICE: + this.setTemplatePath(ConstVal.TEMPLATE_SERVICE + ".ftl"); + this.generateType = fileCreateConfig.getGenerateService(); + break; + case ConstVal.SERVICE_IMPL: + this.setTemplatePath(ConstVal.TEMPLATE_SERVICE_IMPL + ".ftl"); + this.generateType = fileCreateConfig.getGenerateServiceImpl(); + break; + case ConstVal.MAPPER: + this.setTemplatePath(ConstVal.TEMPLATE_MAPPER + ".ftl"); + this.generateType = fileCreateConfig.getGenerateDao(); + break; + case ConstVal.XML: + this.setTemplatePath(ConstVal.TEMPLATE_XML + ".ftl"); + this.generateType = fileCreateConfig.getGenerateXml(); + break; + case ConstVal.CONTROLLER: + this.setTemplatePath(ConstVal.TEMPLATE_CONTROLLER + ".ftl"); + this.generateType = fileCreateConfig.getGenerateController(); + break; + default: + break; + } + } + + @Override + public String outputFile(TableInfo tableInfo) { + + if (ConstVal.XML.equals(modularSuffix)) { + String projectRootPath = config.getProjectRootPath(); + if (!projectRootPath.endsWith(File.separator)) { + projectRootPath += File.separator; + } + + StringBuilder basePathSb = new StringBuilder(projectRootPath); + if (config.isEnableMicroService()) { + basePathSb.append(config.getProjectPrefix()); + basePathSb.append(config.getChildModuleName()); + basePathSb.append(projectSuffix) + .append(File.separator); + } + basePathSb.append(CodeGenerator.SRC_MAIN_RESOURCE) + .append(File.separator) + .append("mybatis") + .append(File.separator) + .append("mapper"); + //.append(config.getChildModuleName()) + //.append(File.separator) + //.append(config.getCurrentModule()); + if (StringUtils.isNotEmpty(config.getChildPackageName())) { + basePathSb.append(File.separator).append(config.getChildPackageName()); + } + + //basePath = basePath + File.separator + tableInfo.getEntityName() + modularSuffix + StringPool.DOT_JAVA; + basePathSb.append(File.separator) + .append(tableInfo.getEntityName()) + .append("DAO") + .append(StringPool.DOT_XML); + + if (GenerateType.ADD.eq(generateType) && FileCreateConfig.isExists(basePathSb.toString())) { + basePathSb.append(".new"); + } + return basePathSb.toString(); + } + + // 根路径 + 项目名 + SRC_MAIN_JAVA + 基础包 + service + 子模块 + EntityName+后缀 + + String projectName = ""; + if (config.isEnableMicroService()) { + if (CodeGenerator.ENUM_PATH.equals(modularSuffix) + || CodeGenerator.SAVE_DTO_PATH.equals(modularSuffix) + || CodeGenerator.UPDATE_DTO_PATH.equals(modularSuffix) + || CodeGenerator.PAGE_DTO_PATH.equals(modularSuffix) + || CodeGenerator.CONSTANT_PATH.equals(modularSuffix) + || CodeGenerator.QUERY_PATH.equals(modularSuffix) + || ConstVal.ENTITY.equals(modularSuffix)) { + projectName = config.getProjectPrefix() + config.getServiceName() + projectSuffix + File.separator; + } else { + projectName = config.getProjectPrefix() + config.getChildModuleName() + projectSuffix + File.separator; + } + } + String basePath = String.format(innerBasePath, projectName); + + String innerModularSuffix = modularSuffix; + if (ConstVal.SERVICE_IMPL.equals(innerModularSuffix)) { + innerModularSuffix = "service"; + } else if (CodeGenerator.SAVE_DTO_PATH.equals(innerModularSuffix)) { + innerModularSuffix = "domain"; + } else if (CodeGenerator.UPDATE_DTO_PATH.equals(innerModularSuffix)) { + innerModularSuffix = "domain"; + } else if (CodeGenerator.PAGE_DTO_PATH.equals(innerModularSuffix)) { + innerModularSuffix = "domain"; + } else if (ConstVal.MAPPER.equals(innerModularSuffix)) { + innerModularSuffix = "dao"; + } else if (ConstVal.ENTITY.equals(innerModularSuffix)) { + innerModularSuffix = "domain"; + } else { + innerModularSuffix = StringUtils.firstCharToLower(modularSuffix); + } + + basePath = basePath + File.separator + projectSuffix.substring(1) + File.separator + innerModularSuffix; + if (StringUtils.isNotEmpty(config.getChildPackageName())) { + basePath = basePath + File.separator + config.getChildPackageName(); + } + if (ConstVal.SERVICE_IMPL.equals(modularSuffix)) { + basePath = basePath + File.separator + "impl"; + } + + if (ConstVal.ENTITY.equals(modularSuffix)) { + basePath = basePath + File.separator + tableInfo.getEntityName() + StringPool.DOT_JAVA; + } else if (ConstVal.XML.equals(modularSuffix)) { + basePath = basePath + File.separator + tableInfo.getEntityName() + "DAO" + StringPool.DOT_JAVA; + } else if (ConstVal.MAPPER.equals(modularSuffix)) { + basePath = basePath + File.separator + tableInfo.getEntityName() + "DAO" + StringPool.DOT_JAVA; + } else if (CodeGenerator.QUERY_PATH.equals(modularSuffix)) { + basePath = basePath + File.separator + tableInfo.getEntityName() + "Wrapper" + StringPool.DOT_JAVA; + } else { + basePath = basePath + File.separator + tableInfo.getEntityName() + modularSuffix + StringPool.DOT_JAVA; + } + + if (GenerateType.ADD.eq(generateType) && FileCreateConfig.isExists(basePath)) { + basePath += ".new"; + } + return basePath; + } +} diff --git a/ceres-generator-master/src/main/java/com/zkthink/ceres/generator/ext/FreemarkerTemplateEngineExt.java b/ceres-generator-master/src/main/java/com/zkthink/ceres/generator/ext/FreemarkerTemplateEngineExt.java new file mode 100644 index 0000000..c8dca84 --- /dev/null +++ b/ceres-generator-master/src/main/java/com/zkthink/ceres/generator/ext/FreemarkerTemplateEngineExt.java @@ -0,0 +1,426 @@ +package com.zkthink.ceres.generator.ext; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.toolkit.StringPool; +import com.baomidou.mybatisplus.generator.InjectionConfig; +import com.baomidou.mybatisplus.generator.config.ConstVal; +import com.baomidou.mybatisplus.generator.config.FileOutConfig; +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.generator.config.rules.FileType; +import com.baomidou.mybatisplus.generator.engine.AbstractTemplateEngine; +import com.baomidou.mybatisplus.generator.engine.BeetlTemplateEngine; +import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine; +import com.zkthink.ceres.generator.CodeGenerator; +import com.zkthink.ceres.generator.config.CodeGeneratorConfig; +import com.zkthink.ceres.generator.config.FileCreateConfig; +import com.zkthink.ceres.generator.model.GenTableColumn; +import com.zkthink.ceres.generator.type.EntityFiledType; +import com.zkthink.ceres.generator.type.GenerateType; +import org.apache.commons.lang3.StringUtils; + +import java.io.File; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + + +/** + * 扩展 {@link BeetlTemplateEngine} + * 便于我们加入我们自己的模板 + * + * @author ceres + */ +public class FreemarkerTemplateEngineExt extends FreemarkerTemplateEngine { + + /** + * 注入字段 正则 + * 匹配: @InjectionField(api="", method="") RemoteData + * 匹配: @InjectionField(api="", method="" beanClass=Xxx.class) + * 匹配: @InjectionField(api="orgApi", method="findXx" beanClass=Org.class) RemoteData + * 匹配: @InjectionField(feign=OrgApi.class, method="findXx" beanClass=Org.class) RemoteData + */ + private final static Pattern INJECTION_FIELD_PATTERN = Pattern.compile("([@]InjectionField[(](api|feign)? *= *([a-zA-Z0-9\"._]+), method *= *([a-zA-Z0-9\"._]+)(, *beanClass *= *[a-zA-Z0-9._]+)?[)]){1}( *RemoteData(<[a-zA-Z0-9.]+,( *[a-zA-Z0-9.]+)>)?)*"); + + /** + * 枚举类 正则 + * 匹配: #{xxxx} 形式的注释 + */ + public final static String REG_EX_VAL = "#(.*?\\{(.*?)?\\})"; + /** + * 枚举类型 正则 + * 匹配 xx:xx; 形式的注释 + */ + public final static String REG_EX_KEY = "([A-Za-z1-9_-]+):(.*?)?;"; + + private CodeGeneratorConfig config; + + public FreemarkerTemplateEngineExt(CodeGeneratorConfig config) { + this.config = config; + } + + + /** + * 扩展父类 增加生成enum的代码。 + */ + @Override + public AbstractTemplateEngine batchOutput() { + ConfigBuilder cb = getConfigBuilder(); + + //生成枚举 + try { + List tableInfoList = getConfigBuilder().getTableInfoList(); + for (TableInfo tableInfo : tableInfoList) { + tableInfo.getFields().forEach(filed -> { + try { + generateEnum(tableInfo, filed); + } catch (Exception e) { + e.printStackTrace(); + } + }); + } + } catch (Exception e) { + logger.error("无法创建文件,请检查配置信息!", e); + } + List tableList = cb.getTableInfoList(); + + + CodeGeneratorConfig.Vue vue = config.getVue(); + Map> tableFieldMap = vue.getTableFieldMap(); + //构造实体中的枚举类型字段 + tableList.forEach(t -> { + t.getFields().forEach(field -> { + Map customMap = field.getCustomMap(); + if (customMap == null) { + customMap = new HashMap<>(); + } + Map fieldMap = tableFieldMap.get(t.getName()); + if (CollUtil.isNotEmpty(fieldMap)) { + GenTableColumn genFiled = fieldMap.get(field.getName()); + if(genFiled!= null) { + customMap.put("info", genFiled); + } + } + field.setCustomMap(customMap); + + build(t, field); + buildInjectionField(t, field); + }); + }); + + + //生成实体 + List focList = new ArrayList<>(); + if (!config.getFileCreateConfig().getIsVue()) { + StringBuilder basePathSb = getBasePath(); + String packageBase = config.getPackageBase().replace(".", File.separator); + basePathSb.append(File.separator).append(packageBase); + config.setCurrentModule("commons"); + focList.add(new FileOutConfigExt(basePathSb.toString(), ConstVal.ENTITY, config)); + } + + InjectionConfig cfg = new InjectionConfig() { + @Override + public void initMap() { + Map map = CodeGenerator.initImportPackageInfo(config.getPackageBase(), config.getChildPackageName()); + + //这里必须 在entity生成后,赋值 + map.put("filedTypes", config.getFiledTypes()); + this.setMap(map); + } + + @Override + public void initTableMap(TableInfo tableInfo) { + this.initMap(); + } + }; + + cfg.setFileCreate(cb.getInjectionConfig().getFileCreate()); + if (cb.getInjectionConfig().getFileOutConfigList() != null + && !cb.getInjectionConfig().getFileOutConfigList().isEmpty()) { + cb.getInjectionConfig().getFileOutConfigList().addAll(focList); + cfg.setFileOutConfigList(cb.getInjectionConfig().getFileOutConfigList()); + } else { + cfg.setFileOutConfigList(focList); + } + cfg.setConfig(cb.getInjectionConfig().getConfig()); + + cb.setInjectionConfig(cfg); + + + //执行mybatis plus的代码生成器 + super.batchOutput(); + + return this; + } + + + private static String trim(String val) { + return val == null ? StringPool.EMPTY : val.trim(); + } + + + public static void main(String[] args) { + String comment = "@InjectionField(api=\"xxxx\", method=\"bbbbb\", beanClass=1) RemoteData"; +// String comment = "@InjectionField(feign=FreemarkerTemplateEngineExt.class, method=\"bbbbb\" beanClass= Xxx.class) RemoteData"; + Matcher matcher = INJECTION_FIELD_PATTERN.matcher(comment); + if (matcher.find()) { + String annotation = trim(matcher.group(1)); //@InjectionField(api="xxxx", method="bbbbb") + String api = trim(matcher.group(3)); //xxxx + String method = trim(matcher.group(4)); //bbbbb + String type = trim(matcher.group(6)); //RemoteData + // 5 + String typePackage = trim(matcher.group(8)); //Org + System.out.println(111); + } + } + + + /** + * 生成 需要注入 类型的字段 + * + * @param table + * @param field + */ + private void buildInjectionField(TableInfo table, TableField field) { + //注释 + String comment = field.getComment(); + if (comment == null) { + return; + } + Set importPackages = table.getImportPackages(); + importPackages.remove("com.zkthink.base.entity.Entity"); + Matcher matcher = INJECTION_FIELD_PATTERN.matcher(comment); + if (matcher.find()) { + String annotation = trim(matcher.group(1)); + String api = trim(matcher.group(3)); + String method = trim(matcher.group(4)); + String type = trim(matcher.group(6)); + String typePackage = trim(matcher.group(8)); + + if (StrUtil.isNotEmpty(type) && StrUtil.contains(typePackage, ".")) { + String data = StrUtil.subAfter(typePackage, ".", true); + if (StrUtil.isNotEmpty(data)) { + type = StrUtil.replace(type, typePackage, data); + } + } + + field.getCustomMap().put("annotation", annotation); +// field.getCustomMap().put("api", api); +// field.getCustomMap().put("method", method); + field.getCustomMap().put("type", type); +// field.getCustomMap().put("type", type); + + if (!api.contains("\"")) { + if (api.contains(".")) { + if (api.endsWith("class")) { + // 导入feign class + importPackages.add(StrUtil.subBefore(api, ".", true)); + + + } else { + importPackages.add("com.zkthink.common.constant.InjectionFieldConstants"); + } + } else { + importPackages.add(String.format("static com.zkthink.common.constant.InjectionFieldConstants.%s", api)); + } + } + if (!method.contains("\"")) { + if (method.contains(".")) { + importPackages.add("com.zkthink.common.constant.InjectionFieldConstants"); + } else { + importPackages.add(String.format("static com.zkthink.common.constant.InjectionFieldConstants.%s", method)); + } + } + if (typePackage.contains(".")) { + importPackages.add(typePackage); + } + importPackages.add("com.zkthink.injection.annonation.InjectionField"); + importPackages.add("com.zkthink.model.RemoteData"); + } + } + + /** + * 生成枚举类型类 + * + * @throws Exception + */ + private void generateEnum(TableInfo tableInfo, TableField field) throws Exception { + String comment = field.getComment(); + if (StringUtils.isBlank(comment) || !comment.contains("{") || !comment.contains("}") || !comment.contains(";")) { + return; + } + // 排除boolean类型值 + if (Boolean.class.getSimpleName().equals(field.getColumnType().getType())) { + return; + } + String propertyName = field.getPropertyName(); + Set filedTypes = config.getFiledTypes(); + + Map objectMap = getObjectMap(tableInfo); + Map packageInfo = (Map) objectMap.get("package"); + String entityPackage = packageInfo.get("Entity"); + + String defEnumPackage = entityPackage.replaceAll("entity", "enumeration"); + + String enumName = comment.substring(comment.indexOf(StringPool.HASH) + 1, comment.indexOf(StringPool.LEFT_BRACE)); + if ("".equals(enumName)) { + enumName = tableInfo.getEntityName() + (Character.toUpperCase(propertyName.charAt(0)) + propertyName.substring(1)) + "Enum"; + } + String finalEnumName = enumName; + List collect = filedTypes.stream().filter((filed) -> filed.getType().equals(finalEnumName)).collect(Collectors.toList()); + EntityFiledType entityFiledType = EntityFiledType.builder() + .name(field.getPropertyName()).packagePath(defEnumPackage + "." + enumName).gen(GenerateType.OVERRIDE) + .build(); + if (!collect.isEmpty()) { + entityFiledType = collect.get(0); + } + + String firstTypeNumber = "true"; + Map> allFields = new LinkedHashMap<>(); + if (comment.contains(StringPool.HASH) && comment.contains(StringPool.RIGHT_BRACE)) { + String enumComment = comment.substring(comment.indexOf(StringPool.HASH), comment.indexOf(StringPool.RIGHT_BRACE) + 1); + // 编译正则表达式 + Pattern pattern = Pattern.compile(REG_EX_VAL); + Matcher matcher = pattern.matcher(enumComment); + while (matcher.find()) { + String val = matcher.group(2); + if (!val.endsWith(";")) { + val += ";"; + } + + Pattern keyPattern = Pattern.compile(REG_EX_KEY); + Matcher keyMatcher = keyPattern.matcher(val); + + while (keyMatcher.find()) { + String key = keyMatcher.group(1); + String value = keyMatcher.group(2); + + List subList = new ArrayList<>(); + if (value.contains(",")) { + String[] split = value.split(StringPool.COMMA); + subList = Arrays.asList(split); + try { + Integer.valueOf(split[0]); + } catch (Exception e) { + //字符串 + firstTypeNumber = "false"; + } + + } else { + try { + Integer.valueOf(value); + } catch (Exception e) { + //字符串 + firstTypeNumber = "false"; + } + subList.add(value); + } + + allFields.put(key, subList); + } + + } + } + + + Map enumCustom = new HashMap<>(); + enumCustom.put("package", entityFiledType); + enumCustom.put("enumName", enumName); + + enumCustom.put("comment", StringUtils.substring(comment, 0, comment.indexOf("\n")).trim()); + enumCustom.put("firstTypeNumber", firstTypeNumber); + enumCustom.put("list", allFields); + enumCustom.put("filedTypes", filedTypes); + + objectMap.put("enumCustom", enumCustom); + + field.getCustomMap().put("enumCustom", enumCustom); + + StringBuilder basePathSb = getBasePath(); + System.out.println("basePathSb: " + basePathSb); + basePathSb.append(File.separator).append(entityFiledType.getPath()) + .append(".java"); + + + Map customMap = field.getCustomMap(); + if (customMap == null) { + customMap = new HashMap<>(); + } + customMap.put("isEnum", "1"); + field.setCustomMap(customMap); + + FileCreateConfig fileCreateConfig = config.getFileCreateConfig(); + if (GenerateType.ADD.eq(fileCreateConfig.getGenerateEnum()) + && FileCreateConfig.isExists(basePathSb.toString())) { + basePathSb.append(".new"); + } + + if (isCreate(FileType.OTHER, basePathSb.toString()) && GenerateType.IGNORE.neq(entityFiledType.getGen())) { + writer(objectMap, templateFilePath("/templates/enum.java"), basePathSb.toString()); + } + + } + + + private StringBuilder getBasePath() { + String projectRootPath = config.getProjectRootPath(); + if (!projectRootPath.endsWith(File.separator)) { + projectRootPath += File.separator; + } + + StringBuilder basePathSb = new StringBuilder(projectRootPath); + basePathSb.append(config.getProjectPrefix()).append(config.getServiceName()) + .append(config.getEntitySuffix()).append(File.separator) + .append(CodeGenerator.SRC_MAIN_JAVA); + + + return basePathSb; + } + + + /** + * 生成实体类中字段的 枚举类型 + * + * @param tableInfo + * @param field + */ + private void build(TableInfo tableInfo, TableField field) { + String comment = field.getComment(); + String entityName = tableInfo.getEntityName(); + String propertyName = field.getPropertyName(); + if (StringUtils.isBlank(comment) || !comment.contains(StringPool.LEFT_BRACE) + || !comment.contains(StringPool.RIGHT_BRACE) || !comment.contains(StringPool.SEMICOLON)) { + return; + } + // 排除boolean类型值 + if (Boolean.class.getSimpleName().equals(field.getColumnType().getType())) { + return; + } + + String enumName = comment.substring(comment.indexOf(StringPool.HASH) + 1, comment.indexOf(StringPool.LEFT_BRACE)); + if (StringPool.EMPTY.equals(enumName)) { + enumName = entityName + (Character.toUpperCase(propertyName.charAt(0)) + propertyName.substring(1)) + "Enum"; + } + + Set filedTypes = config.getFiledTypes(); + + EntityFiledType cur = EntityFiledType.builder().name(propertyName).table(tableInfo.getName()).build(); + if (!filedTypes.contains(cur)) { + ConfigBuilder configBuilder = getConfigBuilder(); + Map packageInfo = configBuilder.getPackageInfo(); + String entityPackage = packageInfo.get("Entity"); + String defEnumPackage = entityPackage.replaceAll("entity", "enumeration"); + + filedTypes.add(EntityFiledType.builder() + .name(propertyName) + .packagePath(defEnumPackage + "." + enumName) + .table(tableInfo.getName()) + .gen(config.getFileCreateConfig().getGenerateEnum()) + .build()); + } + } +} diff --git a/ceres-generator-master/src/main/java/com/zkthink/ceres/generator/ext/MySqlQueryExt.java b/ceres-generator-master/src/main/java/com/zkthink/ceres/generator/ext/MySqlQueryExt.java new file mode 100644 index 0000000..fe3b388 --- /dev/null +++ b/ceres-generator-master/src/main/java/com/zkthink/ceres/generator/ext/MySqlQueryExt.java @@ -0,0 +1,16 @@ +package com.zkthink.ceres.generator.ext; + +import com.baomidou.mybatisplus.generator.config.querys.MySqlQuery; + +/** + * 扩展 {@link MySqlQuery} 方便加入sql查询表元数据信息 增加自定义列,辅助我们的检验器的自动生成 + * + * @author ceres + */ +public class MySqlQueryExt extends MySqlQuery { + + @Override + public String[] fieldCustom() { + return new String[]{"Null", "Default", "Collation"}; + } +} diff --git a/ceres-generator-master/src/main/java/com/zkthink/ceres/generator/ext/OracleQueryExt.java b/ceres-generator-master/src/main/java/com/zkthink/ceres/generator/ext/OracleQueryExt.java new file mode 100644 index 0000000..f9ba78b --- /dev/null +++ b/ceres-generator-master/src/main/java/com/zkthink/ceres/generator/ext/OracleQueryExt.java @@ -0,0 +1,32 @@ +package com.zkthink.ceres.generator.ext; + +import com.baomidou.mybatisplus.generator.config.querys.OracleQuery; + +/** + * 扩展 {@link OracleQuery} 方便加入sql查询表元数据信息 增加自定义列,辅助我们的检验器的自动生成 + * + * @author ceres + * @date 2020年01月19日10:23:23 + */ +public class OracleQueryExt extends OracleQuery { + + @Override + public String[] fieldCustom() { + return new String[]{"NULLABLE", "DATA_SCALE"}; + } + + @Override + public String tableFieldsSql() { + return "SELECT A.COLUMN_NAME, CASE WHEN A.DATA_TYPE='NUMBER' THEN " + + "(CASE WHEN A.DATA_PRECISION IS NULL THEN A.DATA_TYPE " + + "WHEN NVL(A.DATA_SCALE, 0) > 0 THEN A.DATA_TYPE||'('||A.DATA_PRECISION||','||A.DATA_SCALE||')' " + + "ELSE A.DATA_TYPE||'('||A.DATA_PRECISION||')' END) " + + "ELSE A.DATA_TYPE END DATA_TYPE, B.COMMENTS,DECODE(C.POSITION, '1', 'PRI') KEY " + + ", A.NULLABLE, A.DATA_SCALE " + + "FROM ALL_TAB_COLUMNS A " + + " INNER JOIN ALL_COL_COMMENTS B ON A.TABLE_NAME = B.TABLE_NAME AND A.COLUMN_NAME = B.COLUMN_NAME AND B.OWNER = '#schema'" + + " LEFT JOIN ALL_CONSTRAINTS D ON D.TABLE_NAME = A.TABLE_NAME AND D.CONSTRAINT_TYPE = 'P' AND D.OWNER = '#schema'" + + " LEFT JOIN ALL_CONS_COLUMNS C ON C.CONSTRAINT_NAME = D.CONSTRAINT_NAME AND C.COLUMN_NAME=A.COLUMN_NAME AND C.OWNER = '#schema'" + + "WHERE A.OWNER = '#schema' AND A.TABLE_NAME = '%s' ORDER BY A.COLUMN_ID "; + } +} diff --git a/ceres-generator-master/src/main/java/com/zkthink/ceres/generator/model/GenTableColumn.java b/ceres-generator-master/src/main/java/com/zkthink/ceres/generator/model/GenTableColumn.java new file mode 100644 index 0000000..6f26c5b --- /dev/null +++ b/ceres-generator-master/src/main/java/com/zkthink/ceres/generator/model/GenTableColumn.java @@ -0,0 +1,140 @@ +package com.zkthink.ceres.generator.model; + + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.ToString; +import lombok.experimental.Accessors; + +/** + * 代码生成业务字段表 + * + * @author ceres + */ +@Data +@Builder +@AllArgsConstructor +@ToString +@Accessors(chain = true) +public class GenTableColumn { + public static final String YES = "1"; + public static final String NO = "0"; + private static final long serialVersionUID = 1L; + /** + * 归属表 自动计算 + */ + private String tableName; + + /** + * 列名称 自动计算 + */ + private String name; + + /** + * 列描述 自动计算 + */ + private String columnComment; + + /** + * 列类型 自动计算 + */ + private String type; + + /** + * JAVA类型 自动计算 + */ + private String propertyType; + + /** + * JAVA字段名 自动计算 + */ + private String javaField; + /** + * Index页面 Table 的列宽度 + * + * @since 2.0 支持 + */ + private String width; + + /** + * 是否必填(1是) 为空时自动计算 暂时不支持 + */ + private String isRequired; + + /** + * 是否为插入字段(1是) 为空时自动计算 + * + * @since 2.0 支持 + */ + private String isInsert; + + /** + * 是否编辑字段(1是) 为空时自动计算 + * + * @since 2.0 支持 + */ + private String isEdit; + + /** + * 是否列表字段(1是)为空时自动计算 + * + * @since 2.0 支持 + */ + private String isList; + + /** + * 是否查询字段(1是) 为空时自动计算 + * + * @since 2.0 支持 + */ + private String isQuery; + + /** + * 查询方式(EQ等于、NE不等于、GT大于、LT小于、LIKE模糊、BETWEEN范围) 暂时不支持 + */ + private String queryType; + + /** + * 显示类型(input文本框、textarea文本域、select下拉框、checkbox复选框、radio单选框、datetime日期控件) 为空时自动计算 + * + * @since 2.0 支持 + */ + private String htmlType; + + /** + * 字典类型 + * + * @since 2.0 支持 + */ + private String dictType; + /** + * 枚举类型 + * + * @since 2.0 支持 + */ + private String enumType; + + public GenTableColumn() { + } + + /** + * 因为前段新增和报错共用一个页面,所以目前 isInsert 和 isEdit 必须都为0才不会显示在编辑页面 + * + * @param name 字段名 + * @param isInsert 是否显示在新增页面 1/0 空字符串就自动计算 + * @param isEdit 是否显示在修改页面 1/0 空字符串就自动计算 + * @param isList 是否显示在分页列表 1/0 空字符串就自动计算 + * @param isQuery 是否显示在分页查询条件 1/0 空字符串就自动计算 + * @param htmlType 输入框的类型 见: HtmlType + */ + public GenTableColumn(String name, String isInsert, String isEdit, String isList, String isQuery, String htmlType) { + this.name = name; + this.isInsert = isInsert; + this.isEdit = isEdit; + this.isList = isList; + this.isQuery = isQuery; + this.htmlType = htmlType; + } + +} diff --git a/ceres-generator-master/src/main/java/com/zkthink/ceres/generator/type/EntityFiledType.java b/ceres-generator-master/src/main/java/com/zkthink/ceres/generator/type/EntityFiledType.java new file mode 100644 index 0000000..9d768fc --- /dev/null +++ b/ceres-generator-master/src/main/java/com/zkthink/ceres/generator/type/EntityFiledType.java @@ -0,0 +1,76 @@ +package com.zkthink.ceres.generator.type; + + +import java.io.File; + +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.apache.commons.lang3.StringUtils; + +/** + * 实体字段类型 + * + * @author ceres + * @date 2019/05/14 + */ +@Data +@Builder +@ToString +@EqualsAndHashCode(of = {"name", "table"}) +public class EntityFiledType { + /** + * 枚举类型的字段名(不是数据库字段哦!!!) + */ + private String name; + /** + * 枚举类型的完整包路径 eg: com.xx.xx.Type + */ + private String packagePath = ""; + /** + * 表名 + */ + private String table = ""; + + /** + * 是否生成 + */ + private GenerateType gen = GenerateType.OVERRIDE; + + /** + * 枚举类型的完整路径,会根据 packagePath 自动解析 + */ + private String path; + /** + * 导包 + */ + private String importPackage; + /** + * 枚举类型: 会根据 packagePath 自动解析 + */ + private String type; + + public String getPath() { + if (packagePath != null && !"".equals(packagePath)) { + this.path = packagePath.replace(".", File.separator); + } + return path; + } + + public String getType() { + if (packagePath != null && !"".equals(packagePath)) { + this.type = packagePath.substring(packagePath.lastIndexOf(".") + 1); + } + return type; + } + + public String getImportPackage() { + if (this.importPackage == null || "".equals(this.importPackage)) { + this.importPackage = StringUtils.substring(packagePath, 0, packagePath.lastIndexOf(".")); + } + return this.importPackage; + } + +} + diff --git a/ceres-generator-master/src/main/java/com/zkthink/ceres/generator/type/EntityType.java b/ceres-generator-master/src/main/java/com/zkthink/ceres/generator/type/EntityType.java new file mode 100644 index 0000000..e927d26 --- /dev/null +++ b/ceres-generator-master/src/main/java/com/zkthink/ceres/generator/type/EntityType.java @@ -0,0 +1,53 @@ +package com.zkthink.ceres.generator.type; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 父类实体类型 + * + * @author ceres + * @date 2019/05/14 + */ +@Getter +@AllArgsConstructor +public enum EntityType { + /** + * 只有id + */ + SUPER_ENTITY("com.zkthink.base.entity.SuperEntity", new String[]{"id", "tenant_code", "create_time", "create_user"}), + /** + * 有创建人创建时间等 + */ + ENTITY("com.zkthink.base.entity.Entity", new String[]{}), + + /** + * 树形实体 + */ + TREE_ENTITY("com.zkthink.base.entity.TreeEntity", new String[]{"id", "tenant_code", "create_time", "create_user", "update_time", "update_user", "label", "parent_id", "sort_value"}), + + /** + * 不继承任何实体 + */ + NONE("", new String[]{""}), + ; + + private String val; + private String[] columns; + + + public boolean eq(String val) { + if (this.name().equals(val)) { + return true; + } + return false; + } + + public boolean eq(EntityType val) { + if (val == null) { + return false; + } + return eq(val.name()); + } + +} diff --git a/ceres-generator-master/src/main/java/com/zkthink/ceres/generator/type/GenerateType.java b/ceres-generator-master/src/main/java/com/zkthink/ceres/generator/type/GenerateType.java new file mode 100644 index 0000000..55508ba --- /dev/null +++ b/ceres-generator-master/src/main/java/com/zkthink/ceres/generator/type/GenerateType.java @@ -0,0 +1,43 @@ +package com.zkthink.ceres.generator.type; + +/** + * 生成策略 + * + * @author ceres + * @date 2019/05/14 + */ +public enum GenerateType { + /** + * 覆盖 + */ + OVERRIDE, + /** + * 新增 + */ + ADD, + /** + * 存在则忽略 + */ + IGNORE, + ; + + + public boolean eq(String val) { + if (this.name().equals(val)) { + return true; + } + return false; + } + + public boolean eq(GenerateType val) { + if (val == null) { + return false; + } + return eq(val.name()); + } + + public boolean neq(GenerateType val) { + return !eq(val); + } + +} diff --git a/ceres-generator-master/src/main/java/com/zkthink/ceres/generator/type/HtmlType.java b/ceres-generator-master/src/main/java/com/zkthink/ceres/generator/type/HtmlType.java new file mode 100644 index 0000000..7d7df91 --- /dev/null +++ b/ceres-generator-master/src/main/java/com/zkthink/ceres/generator/type/HtmlType.java @@ -0,0 +1,26 @@ +package com.zkthink.ceres.generator.type; + +public class HtmlType { + public static final String INPUT = "input"; + public static final String TEXTAREA = "textarea"; + public static final String SELECT = "select"; + /** + * 不支持 + * + * @since 2.0 不支持 + */ + public static final String SELECT_USER = "select_user"; + /** + * 不支持 + * + * @since 2.0 不支持 + */ + public static final String SELECT_ORG = "select_org"; + public static final String RADIO = "radio"; + public static final String RADIO_BUTTON = "radio-button"; + public static final String SWITCH = "switch"; + public static final String CHECKBOX = "checkbox"; + public static final String CHECKBOX_BUTTON = "checkbox-button"; + public static final String DATE_PICKER = "date-picker"; + public static final String DATE_TIME_PICKER = "datetime-picker"; +} diff --git a/ceres-generator-master/src/main/java/com/zkthink/ceres/generator/type/SuperClass.java b/ceres-generator-master/src/main/java/com/zkthink/ceres/generator/type/SuperClass.java new file mode 100644 index 0000000..1bb8625 --- /dev/null +++ b/ceres-generator-master/src/main/java/com/zkthink/ceres/generator/type/SuperClass.java @@ -0,0 +1,42 @@ +package com.zkthink.ceres.generator.type; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public enum SuperClass { + + SUPER_CLASS("com.zkthink.base.controller.SuperController", "com.zkthink.base.service.SuperService", + "com.zkthink.base.service.SuperServiceImpl", "com.baomidou.mybatisplus.core.mapper.BaseMapper"), + SUPER_CACHE_CLASS("com.zkthink.base.controller.SuperCacheController", "com.zkthink.base.service.SuperCacheService", + "com.zkthink.base.service.SuperCacheServiceImpl", "com.baomidou.mybatisplus.core.mapper.BaseMapper"), + NONE("", "", "", ""); + + private String controller; + private String service; + private String serviceImpl; + private String mapper; + + public SuperClass setController(String controller) { + this.controller = controller; + return this; + } + + public SuperClass setService(String service) { + this.service = service; + return this; + } + + public SuperClass setMapper(String mapper) { + this.mapper = mapper; + return this; + } + + public SuperClass setServiceImpl(String serviceImpl) { + this.serviceImpl = serviceImpl; + return this; + } +} diff --git a/ceres-generator-master/src/main/resources/init/java/Application.java.ftl b/ceres-generator-master/src/main/resources/init/java/Application.java.ftl new file mode 100644 index 0000000..c323c57 --- /dev/null +++ b/ceres-generator-master/src/main/resources/init/java/Application.java.ftl @@ -0,0 +1,55 @@ +package ${packageBaseParent}; + +import com.zkthink.security.annotation.EnableLoginArgResolver; +import com.zkthink.validator.config.EnableFormValidator; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.cloud.openfeign.EnableFeignClients; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.EnableAspectJAutoProxy; +<#if packageBaseParent != "com.zkthink"> +import org.springframework.context.annotation.ComponentScan; + +import org.springframework.core.env.Environment; + +import java.net.InetAddress; +import java.net.UnknownHostException; + +/** + * ${description}启动类 + * + * @author ${author} + * @date ${date} + */ +@SpringBootApplication +@EnableDiscoveryClient +@Configuration +<#if packageBaseParent != "com.zkthink"> +@EnableFeignClients(value = { "${packageBaseParent}", "com.zkthink" }) +@ComponentScan(basePackages = {"${packageBaseParent}", "com.zkthink"}) +<#else> +@EnableFeignClients(value = { "${packageBaseParent}" }) + +@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true) +@Slf4j +@EnableLoginArgResolver +@EnableFormValidator +public class ${service}ServerApplication { + public static void main(String[] args) throws UnknownHostException { + ConfigurableApplicationContext application = SpringApplication.run(${service}ServerApplication.class, args); + Environment env = application.getEnvironment(); + log.info("\n----------------------------------------------------------\n\t" + + "应用 '{}' 启动成功! 访问连接:\n\t" + + "Swagger文档: \t\thttp://{}:{}/doc.html\n\t" + + "数据库监控: \t\thttp://{}:{}/druid\n" + + "----------------------------------------------------------", + env.getProperty("spring.application.name"), + InetAddress.getLocalHost().getHostAddress(), + env.getProperty("server.port"), + "127.0.0.1", + env.getProperty("server.port")); + } +} diff --git a/ceres-generator-master/src/main/resources/init/java/DatabaseAutoConfiguration.java.ftl b/ceres-generator-master/src/main/resources/init/java/DatabaseAutoConfiguration.java.ftl new file mode 100644 index 0000000..3673b26 --- /dev/null +++ b/ceres-generator-master/src/main/resources/init/java/DatabaseAutoConfiguration.java.ftl @@ -0,0 +1,123 @@ +package ${packageBase}.config.datasource; + +import cn.hutool.core.util.ArrayUtil; +import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder; +import com.baomidou.mybatisplus.autoconfigure.ConfigurationCustomizer; +import com.baomidou.mybatisplus.autoconfigure.MybatisPlusProperties; +import com.baomidou.mybatisplus.autoconfigure.MybatisPlusPropertiesCustomizer; +import com.zkthink.database.datasource.BaseDatabaseConfiguration; +import com.zkthink.database.properties.DatabaseProperties; +import com.p6spy.engine.spy.P6DataSource; +import lombok.extern.slf4j.Slf4j; +import org.apache.ibatis.mapping.DatabaseIdProvider; +import org.apache.ibatis.plugin.Interceptor; +import org.apache.ibatis.scripting.LanguageDriver; +import org.apache.ibatis.session.ExecutorType; +import org.apache.ibatis.session.SqlSessionFactory; +import org.apache.ibatis.type.TypeHandler; +import org.mybatis.spring.SqlSessionTemplate; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.core.io.ResourceLoader; +import org.springframework.stereotype.Repository; + +import javax.sql.DataSource; +import java.util.List; + +/** + * ceres.database.multiTenantType != DATASOURCE 时,该类启用. + * 此时,项目的多租户模式切换成:${r"${ceres.database.multiTenantType}"}。 + *

+ * NONE("非租户模式"): 不存在租户的概念 + * COLUMN("字段模式"): 在sql中拼接 tenant_code 字段 + * SCHEMA("独立schema模式"): 在sql中拼接 数据库 schema + *

+ * COLUMN和SCHEMA模式的实现 参考下面的 @see 中的3个类 + * + * @author ${author} + * @date ${date} + * 断点查看原理:👇👇👇 + * @see com.zkthink.database.datasource.BaseMybatisConfiguration#paginationInterceptor() + * @see com.zkthink.database.servlet.TenantContextHandlerInterceptor + * @see com.zkthink.database.parsers.DynamicTableNameParser +*/ +@Configuration +@Slf4j +@MapperScan( + basePackages = { "${packageBaseParent}", <#if packageBaseParent != "com.zkthink">"com.zkthink"}, annotationClass = Repository.class, + sqlSessionFactoryRef = ${service}DatabaseAutoConfiguration.DATABASE_PREFIX + "SqlSessionFactory") +@EnableConfigurationProperties({MybatisPlusProperties.class}) +@ConditionalOnExpression("!'DATASOURCE'.equals('${r"${ceres.database.multiTenantType}"}')") +public class ${service}DatabaseAutoConfiguration extends BaseDatabaseConfiguration { + /** + * 每个数据源配置不同即可 + */ + final static String DATABASE_PREFIX = "master"; + + public ${service}DatabaseAutoConfiguration(MybatisPlusProperties properties, + DatabaseProperties databaseProperties, + ObjectProvider${r""} interceptorsProvider, + ObjectProvider${r""} typeHandlersProvider, + ObjectProvider${r""} languageDriversProvider, + ResourceLoader resourceLoader, + ObjectProvider${r""} databaseIdProvider, + ObjectProvider${r">"} configurationCustomizersProvider, + ObjectProvider${r">"} mybatisPlusPropertiesCustomizerProvider, + ApplicationContext applicationContext) { + super(properties, databaseProperties, interceptorsProvider, typeHandlersProvider, + languageDriversProvider, resourceLoader, databaseIdProvider, + configurationCustomizersProvider, mybatisPlusPropertiesCustomizerProvider, applicationContext); + log.debug("检测到 ceres.database.multiTenantType!=DATASOURCE,加载了 ${service}DatabaseAutoConfiguration"); + } + + @Bean(DATABASE_PREFIX + "SqlSessionTemplate") + public SqlSessionTemplate getSqlSessionTemplate(@Qualifier(DATABASE_PREFIX + "SqlSessionFactory") SqlSessionFactory sqlSessionFactory) { + ExecutorType executorType = this.properties.getExecutorType(); + if (executorType != null) { + return new SqlSessionTemplate(sqlSessionFactory, executorType); + } else { + return new SqlSessionTemplate(sqlSessionFactory); + } + } + + /** + * 数据源信息 + * + * @return + */ + @Primary + @Bean(name = DATABASE_PREFIX + "DruidDataSource") + @ConfigurationProperties(prefix = "spring.datasource.druid") + public DataSource druidDataSource() { + return DruidDataSourceBuilder.create().build(); + } + + @Bean(name = DATABASE_PREFIX + "DataSource") + public DataSource dataSource(@Qualifier(DATABASE_PREFIX + "DruidDataSource") DataSource dataSource) { + if (ArrayUtil.contains(DEV_PROFILES, this.profiles)) { + return new P6DataSource(dataSource); + } else { + return dataSource; + } + } + + /** + * mybatis Sql Session 工厂 + * + * @return + * @throws Exception + */ + @Bean(DATABASE_PREFIX + "SqlSessionFactory") + public SqlSessionFactory getSqlSessionFactory(@Qualifier(DATABASE_PREFIX + "DataSource") DataSource dataSource) throws Exception { + return super.sqlSessionFactory(dataSource); + } + +} diff --git a/ceres-generator-master/src/main/resources/init/java/ExceptionConfiguration.java.ftl b/ceres-generator-master/src/main/resources/init/java/ExceptionConfiguration.java.ftl new file mode 100644 index 0000000..d8f6517 --- /dev/null +++ b/ceres-generator-master/src/main/resources/init/java/ExceptionConfiguration.java.ftl @@ -0,0 +1,20 @@ +package ${packageBase}.config; + +import com.zkthink.boot.handler.DefaultGlobalExceptionHandler; +import org.springframework.context.annotation.Configuration; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; + +/** + * ${description}-全局异常处理 + * + * @author ${author} + * @date ${date} + */ +@Configuration +@ControllerAdvice(annotations = {RestController.class, Controller.class}) +@ResponseBody +public class ${service}ExceptionConfiguration extends DefaultGlobalExceptionHandler { +} diff --git a/ceres-generator-master/src/main/resources/init/java/MybatisAutoConfiguration.java.ftl b/ceres-generator-master/src/main/resources/init/java/MybatisAutoConfiguration.java.ftl new file mode 100644 index 0000000..a99794f --- /dev/null +++ b/ceres-generator-master/src/main/resources/init/java/MybatisAutoConfiguration.java.ftl @@ -0,0 +1,43 @@ +package ${packageBase}.config.datasource; + + +import com.zkthink.oauth.api.UserApi; +import com.zkthink.database.datasource.BaseMybatisConfiguration; +import com.zkthink.database.mybatis.auth.DataScopeInterceptor; +import com.zkthink.database.properties.DatabaseProperties; +import com.zkthink.utils.SpringUtils; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.annotation.Order; + +/** + * ${description}-Mybatis 常用重用拦截器 + * + * @author ${author} + * @date ${date} + */ +@Configuration +@Slf4j +@EnableConfigurationProperties({DatabaseProperties.class}) +public class ${service}MybatisAutoConfiguration extends BaseMybatisConfiguration { + + public ${service}MybatisAutoConfiguration(DatabaseProperties databaseProperties) { + super(databaseProperties); + } + + /** + * 数据权限插件 + * + * @return DataScopeInterceptor + */ + @Order(10) + @Bean + @ConditionalOnProperty(prefix = DatabaseProperties.PREFIX, name = "isDataScope", havingValue = "true", matchIfMissing = true) + public DataScopeInterceptor dataScopeInterceptor() { + return new DataScopeInterceptor((userId) -> SpringUtils.getBean(UserApi.class).getDataScopeById(userId)); + } + +} diff --git a/ceres-generator-master/src/main/resources/init/java/WebConfiguration.java.ftl b/ceres-generator-master/src/main/resources/init/java/WebConfiguration.java.ftl new file mode 100644 index 0000000..637ce67 --- /dev/null +++ b/ceres-generator-master/src/main/resources/init/java/WebConfiguration.java.ftl @@ -0,0 +1,30 @@ +package ${packageBase}.config; + +import com.zkthink.boot.config.BaseConfig; +import org.springframework.context.annotation.Configuration; +import com.zkthink.oauth.api.LogApi; +import com.zkthink.log.event.SysLogListener; +import org.springframework.context.annotation.Bean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; + +/** + * ${description}-Web配置 + * + * @author ${author} + * @date ${date} + */ +@Configuration +public class ${service}WebConfiguration extends BaseConfig { + + /** + * ceres.log.enabled = true 并且 ceres.log.type=DB时实例该类 + * + * @param optLogService + * @return + */ + @Bean + @ConditionalOnExpression("${r'${'}ceres.log.enabled:true${r'}'} && 'DB'.equals('${r'${'}ceres.log.type:LOGGER${r'}'}')") + public SysLogListener sysLogListener(LogApi logApi) { + return new SysLogListener((log) -> logApi.save(log)); + } +} diff --git a/ceres-generator-master/src/main/resources/init/pom/api.java.ftl b/ceres-generator-master/src/main/resources/init/pom/api.java.ftl new file mode 100644 index 0000000..116b051 --- /dev/null +++ b/ceres-generator-master/src/main/resources/init/pom/api.java.ftl @@ -0,0 +1,46 @@ + + + + ${projectPrefix}${serviceName} + ${groupId} + ${version} + ../ + + + 4.0.0 + ${projectPrefix}${serviceName}-api + ${r"${"}project.artifactId${r"}"} + ${description}-FeignApi模块 + + + + ${groupId} + ${projectPrefix}${serviceName}-entity + ${r"${"}ceres-project.version${r"}"} + + + + org.springframework.cloud + spring-cloud-starter-openfeign + + + com.google.guava + guava + + + + + org.springframework.cloud + spring-cloud-starter-netflix-hystrix + + + com.google.guava + guava + + + + + + diff --git a/ceres-generator-master/src/main/resources/init/pom/biz.java.ftl b/ceres-generator-master/src/main/resources/init/pom/biz.java.ftl new file mode 100644 index 0000000..524e048 --- /dev/null +++ b/ceres-generator-master/src/main/resources/init/pom/biz.java.ftl @@ -0,0 +1,61 @@ + + + + ${projectPrefix}${serviceName} + ${groupId} + ${version} + ../ + + + 4.0.0 + <#if isChildModule> + ${projectPrefix}${childModuleName}-biz + <#else> + ${projectPrefix}${serviceName}-biz + + ${r"${"}project.artifactId${r"}"} + ${description}-业务模块 + + + + ${groupId} + ${projectPrefix}${serviceName}-entity + + + + ${groupId} + ${projectPrefix}oauth-api + ${r"${"}ceres-project.version${r"}"} + + + com.zkthink + ceres-databases + + + com.zkthink + ceres-dozer-starter + + + com.zkthink + ceres-j2cache-starter + + + com.zkthink + ceres-boot + + + + org.springframework.boot + spring-boot-starter-web + + + + com.baomidou + mybatis-plus + + + + + diff --git a/ceres-generator-master/src/main/resources/init/pom/controller.java.ftl b/ceres-generator-master/src/main/resources/init/pom/controller.java.ftl new file mode 100644 index 0000000..95932bf --- /dev/null +++ b/ceres-generator-master/src/main/resources/init/pom/controller.java.ftl @@ -0,0 +1,42 @@ + + + + ${projectPrefix}${serviceName} + ${groupId} + ${version} + ../ + + + 4.0.0 + <#if isChildModule> + ${projectPrefix}${childModuleName}-controller + <#else> + ${projectPrefix}${serviceName}-controller + + ${r"${"}project.artifactId${r"}"} + ${description}-控制器模块 + + + + ${groupId} + <#if isChildModule> + ${projectPrefix}${childModuleName}-biz + <#else> + ${projectPrefix}${serviceName}-biz + + + + + com.zkthink + ceres-security-starter + + + com.zkthink + ceres-log-starter + + + + + diff --git a/ceres-generator-master/src/main/resources/init/pom/entity.java.ftl b/ceres-generator-master/src/main/resources/init/pom/entity.java.ftl new file mode 100644 index 0000000..845eace --- /dev/null +++ b/ceres-generator-master/src/main/resources/init/pom/entity.java.ftl @@ -0,0 +1,41 @@ + + + + ${projectPrefix}${serviceName} + ${groupId} + ${version} + ../ + + + 4.0.0 + ${projectPrefix}${serviceName}-entity + ${r"${"}project.artifactId${r"}"} + ${description}-实体模块 + + + + com.zkthink + ceres-common + ${r"${"}ceres-project.version${r"}"} + + + com.zkthink + ceres-injection-starter + + + com.baomidou + mybatis-plus-annotation + + + cn.afterturn + easypoi-annotation + + + cn.afterturn + easypoi-base + + + + diff --git a/ceres-generator-master/src/main/resources/init/pom/pom.java.ftl b/ceres-generator-master/src/main/resources/init/pom/pom.java.ftl new file mode 100644 index 0000000..0fee326 --- /dev/null +++ b/ceres-generator-master/src/main/resources/init/pom/pom.java.ftl @@ -0,0 +1,46 @@ + + + + ${groupId} + ${projectPrefix}admin-cloud + ${version} + ../ + + + 4.0.0 + ${projectPrefix}${serviceName} + ${r"${"}project.artifactId${r"}"} + ${description}服务 + pom + + + ${projectPrefix}${serviceName}-api + ${projectPrefix}${serviceName}-entity + ${projectPrefix}${serviceName}-biz + ${projectPrefix}${serviceName}-controller + ${projectPrefix}${serviceName}-server + + + + + + ${groupId} + ${projectPrefix}${serviceName}-entity + ${r"${"}ceres-project.version${r"}"} + + + ${groupId} + ${projectPrefix}${serviceName}-biz + ${r"${"}ceres-project.version${r"}"} + + + ${groupId} + ${projectPrefix}${serviceName}-controller + ${r"${"}ceres-project.version${r"}"} + + + + + diff --git a/ceres-generator-master/src/main/resources/init/pom/server.java.ftl b/ceres-generator-master/src/main/resources/init/pom/server.java.ftl new file mode 100644 index 0000000..4a463c1 --- /dev/null +++ b/ceres-generator-master/src/main/resources/init/pom/server.java.ftl @@ -0,0 +1,127 @@ + + + + ${projectPrefix}${serviceName} + ${groupId} + ${version} + ../ + + + 4.0.0 + ${projectPrefix}${serviceName}-server + ${r"${"}project.artifactId${r"}"} + ${description}-启动模块 + + + + ${groupId} + ${projectPrefix}${serviceName}-controller + + + + com.zkthink + ceres-scan-starter + + + com.zkthink + ceres-swagger2-starter + + + com.zkthink + ceres-validator-starter + + + com.zkthink + ceres-xss-starter + + + com.zkthink + ceres-j2cache-starter + + + com.zkthink + ceres-cloud-starter + + + com.zkthink + ceres-zipkin-client-starter + + + + org.springframework.boot + spring-boot-starter-web + + + org.apache.tomcat.embed + tomcat-embed-websocket + + + org.springframework.boot + spring-boot-starter-tomcat + + + + + org.springframework.boot + spring-boot-starter-undertow + + + org.springframework.boot + spring-boot-starter-aop + + + org.springframework.boot + spring-boot-starter-actuator + + + com.baomidou + mybatis-plus-boot-starter + + + cn.afterturn + easypoi-spring-boot-starter + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + ../../src/main/filters/config-${r"${"}profile.active${r"}"}.properties + + + + org.springframework.boot + spring-boot-maven-plugin + + + + repackage + + + + + + + + com.spotify + dockerfile-maven-plugin + ${r"${"}dockerfile-maven-plugin.version${r"}"} + + ${r"${"}docker.image.prefix${r"}"}/${r"${"}project.artifactId${r"}"} + ${r"${"}ceres-project.version${r"}"} + + target/${r"${"}project.build.finalName${r"}"}.jar + + + + + + + diff --git a/ceres-generator-master/src/main/resources/init/resources/application.java.ftl b/ceres-generator-master/src/main/resources/init/resources/application.java.ftl new file mode 100644 index 0000000..827aab3 --- /dev/null +++ b/ceres-generator-master/src/main/resources/init/resources/application.java.ftl @@ -0,0 +1,12 @@ +ceres: + swagger: + docket: + ${serviceName}: + title: ${description}服务 + base-package: ${packageBase}.controller +server: + port: ${serverPort} + + +## 请在nacos中新建一个名为: ${projectPrefix}${serviceName}-server.yml 的配置文件,并将: ${projectPrefix}${serviceName}-server/src/main/resources/${projectPrefix}${serviceName}-server.yml 配置文件的内容移动过去 +## 然后删除此文件!!! diff --git a/ceres-generator-master/src/main/resources/init/resources/banner.java.ftl b/ceres-generator-master/src/main/resources/init/resources/banner.java.ftl new file mode 100644 index 0000000..548cc39 --- /dev/null +++ b/ceres-generator-master/src/main/resources/init/resources/banner.java.ftl @@ -0,0 +1,10 @@ +${r"${"}AnsiColor.BRIGHT_YELLOW${r"}"} + .__.__ .___ .__ .__ .___ +__________ __|__| |__ ____ __ __ _____ __| _/_____ |__| ____ ____ | | ____ __ __ __| _/ +\___ / | \ | | \ / _ \| | \ ______ \__ \ / __ |/ \| |/ \ ______ _/ ___\| | / _ \| | \/ __ | + / /| | / | Y ( ${r"<_>"} ) | / /_____/ / __ \_/ /_/ | Y Y \ | | \ /_____/ \ \___| |_( ${r"<_>"} ) | / /_/ | +/_____ \____/|__|___| /\____/|____/ (____ /\____ |__|_| /__|___| / \___ >____/\____/|____/\____ | + \/ \/ \/ \/ \/ \/ \/ \/ +Application Version: @project.description@ - @project.version@ +Spring Boot Version: ${r"${"}spring-boot.version${r"}"}${r"${"}spring-boot.formatted-version${r"}"} +${r"${"}AnsiColor.DEFAULT${r"}"} diff --git a/ceres-generator-master/src/main/resources/init/resources/bootstrap.java.ftl b/ceres-generator-master/src/main/resources/init/resources/bootstrap.java.ftl new file mode 100644 index 0000000..2835d7d --- /dev/null +++ b/ceres-generator-master/src/main/resources/init/resources/bootstrap.java.ftl @@ -0,0 +1,50 @@ +# @xxx@ 从pom.xml中取值, 所以 @xx@ 标注的值,都不能从nacos中获取 +ceres: + nacos: + ip: ${r"${"}NACOS_IP:@nacos.ip@${r"}"} + port: ${r"${"}NACOS_PORT:@nacos.port@${r"}"} + namespace: ${r"${"}NACOS_ID:@nacos.namespace@${r"}"} + +spring: + main: + allow-bean-definition-overriding: true + application: + name: @project.artifactId@ + profiles: + active: @profile.active@ + cloud: + nacos: + config: + server-addr: ${r"${"}ceres.nacos.ip${r"}"}:${r"${"}ceres.nacos.port${r"}"} + file-extension: yml + namespace: ${r"${"}ceres.nacos.namespace${r"}"} + shared-configs: + - dataId: common.yml + refresh: true + - dataId: redis.yml + refresh: false + - dataId: mysql.yml + refresh: true + - dataId: rabbitmq.yml + refresh: false + enabled: true + discovery: + server-addr: ${r"${"}ceres.nacos.ip}:${r"${"}ceres.nacos.port${r"}"} + namespace: ${r"${"}ceres.nacos.namespace${r"}"} + metadata: # 元数据,用于权限服务实时获取各个服务的所有接口 + management.context-path: ${r"${"}server.servlet.context-path:${r"}"}${r"${"}spring.mvc.servlet.path:${r"}"}${r"${"}management.endpoints.web.base-path:${r"}"} + +# 只能配置在bootstrap.yml ,否则会生成 log.path_IS_UNDEFINED 文件夹 +# window会自动在 代码所在盘 根目录下自动创建文件夹, 如: D:/data/projects/logs +logging: + file: + path: @logging.file.path@ + name: ${r"${"}logging.file.path${r"}"}/${r"${"}spring.application.name}/root.log + +# 用于/actuator/info +info: + name: '@project.name@' + description: '@project.description@' + version: '@project.version@' + spring-boot-version: '${r"${spring.boot.version}"}' + spring-cloud-version: '@spring.cloud.version@' diff --git a/ceres-generator-master/src/main/resources/init/resources/logback-spring.java.ftl b/ceres-generator-master/src/main/resources/init/resources/logback-spring.java.ftl new file mode 100644 index 0000000..88b0083 --- /dev/null +++ b/ceres-generator-master/src/main/resources/init/resources/logback-spring.java.ftl @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ceres-generator-master/src/main/resources/init/resources/spy.java.ftl b/ceres-generator-master/src/main/resources/init/resources/spy.java.ftl new file mode 100644 index 0000000..04c82c1 --- /dev/null +++ b/ceres-generator-master/src/main/resources/init/resources/spy.java.ftl @@ -0,0 +1,21 @@ +module.log=com.p6spy.engine.logging.P6LogFactory,com.p6spy.engine.outage.P6OutageFactory +# \u81EA\u5B9A\u4E49\u65E5\u5FD7\u6253\u5370 +logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger +#\u65E5\u5FD7\u8F93\u51FA\u5230\u63A7\u5236\u53F0 +appender=com.baomidou.mybatisplus.extension.p6spy.StdoutLogger +# \u4F7F\u7528\u65E5\u5FD7\u7CFB\u7EDF\u8BB0\u5F55 sql +#appender=com.p6spy.engine.spy.appender.Slf4JLogger +# \u8BBE\u7F6E p6spy driver \u4EE3\u7406 +deregisterdrivers=true +# \u53D6\u6D88JDBC URL\u524D\u7F00 +useprefix=true +# \u914D\u7F6E\u8BB0\u5F55 Log \u4F8B\u5916,\u53EF\u53BB\u6389\u7684\u7ED3\u679C\u96C6\u6709error,info,batch,debug,statement,commit,rollback,result,resultset. +excludecategories=info,debug,result,commit,resultset +# \u65E5\u671F\u683C\u5F0F +dateformat=yyyy-MM-dd HH:mm:ss +# \u5B9E\u9645\u9A71\u52A8\u53EF\u591A\u4E2A +driverlist=com.mysql.cj.jdbc.Driver +# \u662F\u5426\u5F00\u542F\u6162SQL\u8BB0\u5F55 +outagedetection=true +# \u6162SQL\u8BB0\u5F55\u6807\u51C6 2 \u79D2 +outagedetectioninterval=2 diff --git a/ceres-generator-master/src/main/resources/logback.xml b/ceres-generator-master/src/main/resources/logback.xml new file mode 100644 index 0000000..a5cd9e1 --- /dev/null +++ b/ceres-generator-master/src/main/resources/logback.xml @@ -0,0 +1,16 @@ + + + + + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %class{36}:%L - %msg%n + + + + + + + + \ No newline at end of file diff --git a/ceres-generator-master/src/main/resources/templates/constant.java.ftl b/ceres-generator-master/src/main/resources/templates/constant.java.ftl new file mode 100644 index 0000000..9c0c649 --- /dev/null +++ b/ceres-generator-master/src/main/resources/templates/constant.java.ftl @@ -0,0 +1,32 @@ +package ${cfg.Constant}; + +import java.io.Serializable; + +/** + *

+ * 数据库常量 + * ${table.comment!?replace("\n","\n * ")} + *

+ * + * @author ${author} + * @date ${date} + */ +public class ${entity}${cfg.constantSuffix} implements Serializable { + + private static final long serialVersionUID = 1L; + + private ${entity}${cfg.constantSuffix}(){ + super(); + } + +<#-- 字段常量 --> +<#if entityColumnConstant> + /** + * 字段常量 + */ + <#list table.fields as field> + public static final String ${field.name?upper_case} = "${field.name}"; + + + +} diff --git a/ceres-generator-master/src/main/resources/templates/controller.java.ftl b/ceres-generator-master/src/main/resources/templates/controller.java.ftl new file mode 100644 index 0000000..734e8f6 --- /dev/null +++ b/ceres-generator-master/src/main/resources/templates/controller.java.ftl @@ -0,0 +1,81 @@ +/* +* Copyright (C) 2017-2021 +* All rights reserved, Designed By 深圳中科鑫智科技有限公司 +* Copyright authorization contact 18814114118 +*/ +package ${package.Controller}; + +<#if superControllerClass??> +import ${package.Entity}.${entity}; +import ${cfg.SaveDTO}.${entity}SaveDTO; +import ${cfg.SaveDTO}.${entity}UpdateDTO; +import ${cfg.SaveDTO}.${entity}PageDTO; +import ${package.Service}.${table.serviceName}; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +<#if superControllerClassPackage??> +import ${superControllerClassPackage}; + +import io.swagger.annotations.Api; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.RequestMapping; +<#if restControllerStyle> +import org.springframework.web.bind.annotation.RestController; +<#else> +import org.springframework.stereotype.Controller; + + + +<#assign tableComment = "${table.comment!''}"/> +<#if table.comment?? && table.comment!?contains('\n')> + <#assign tableComment = "${table.comment!?substring(0,table.comment?index_of('\n'))?trim}"/> + +/** + *

+ * 前端控制器 + * ${table.comment!?replace("\n","\n * ")} + *

+ * + * @author ${author} + * @date ${date} + */ +@Slf4j +<#if restControllerStyle> +@RestController +<#else> +@Controller + +@RequestMapping("<#if package.ModuleName??>/${package.ModuleName}/<#if controllerMappingHyphenStyle??>${controllerMappingHyphen}<#else>${table.entityPath}") +<#if swagger2> +@Api(value = "${entity}", tags = "${tableComment}") + +<#if kotlin> + class ${table.controllerName}<#if superControllerClass??> : ${superControllerClass}() +<#else> + <#if superControllerClass??> +public class ${table.controllerName} extends ${superControllerClass}<${table.serviceName}, <#list table.commonFields as field><#if field.keyFlag>${field.propertyType}<#list table.fields as field><#if field.keyFlag>${field.propertyType}, ${entity}, ${entity}PageDTO, ${entity}SaveDTO, ${entity}UpdateDTO> { + <#else> +public class ${table.controllerName} { + + +<#if superControllerClass??> + /** + * Excel导入后的操作 + * + * @param list + */ + @Override + public R handlerImport(List> list){ + List<${entity}> ${entity?uncap_first}List = list.stream().map((map) -> { + ${entity} ${entity?uncap_first} = ${entity}.builder().build(); + //TODO 请在这里完成转换 + return ${entity?uncap_first}; + }).collect(Collectors.toList()); + + return R.success(baseService.saveBatch(${entity?uncap_first}List)); + } + +} + diff --git a/ceres-generator-master/src/main/resources/templates/controller_bak.java.ftl b/ceres-generator-master/src/main/resources/templates/controller_bak.java.ftl new file mode 100644 index 0000000..e619aa5 --- /dev/null +++ b/ceres-generator-master/src/main/resources/templates/controller_bak.java.ftl @@ -0,0 +1,198 @@ +package ${package.Controller}; + + +import java.util.List; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.zkthink.base.R; +import com.zkthink.log.annotation.SysLog; +import com.zkthink.database.mybatis.conditions.query.LbqWrapper; +import com.zkthink.database.mybatis.conditions.Wraps; +import ${package.Entity}.${entity}; +import ${cfg.SaveDTO}.${entity}SaveDTO; +import ${cfg.SaveDTO}.${entity}UpdateDTO; +import ${cfg.SaveDTO}.${entity}PageDTO; +import ${package.Service}.${table.serviceName}; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import com.zkthink.base.entity.SuperEntity; +import com.zkthink.model.RemoteData; +import com.zkthink.utils.BeanPlusUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RequestMapping; +<#if restControllerStyle> +import org.springframework.web.bind.annotation.RestController; +<#else> +import org.springframework.stereotype.Controller; + +<#if superControllerClassPackage??> +import ${superControllerClassPackage}; + + +<#assign tableComment = "${table.comment!''}"/> +<#if table.comment?? && table.comment!?contains('\n')> + <#assign tableComment = "${table.comment!?substring(0,table.comment?index_of('\n'))?trim}"/> + +/** + *

+ * 前端控制器 + * ${table.comment!?replace("\n","\n * ")} + *

+ * + * @author ${author} + * @date ${date} + */ +@Slf4j +@Validated +<#if restControllerStyle> +@RestController +<#else> +@Controller + +@RequestMapping("<#if package.ModuleName??>/${package.ModuleName}/<#if controllerMappingHyphenStyle??>${controllerMappingHyphen}<#else>${table.entityPath}") +<#if swagger2> +@Api(value = "${entity}", tags = "${tableComment}") + +<#if kotlin> + class ${table.controllerName}<#if superControllerClass??> : ${superControllerClass}() +<#else> + <#if superControllerClass??> +public class ${table.controllerName} extends ${superControllerClass} { + <#else> +public class ${table.controllerName} { + + + @Autowired + private ${table.serviceName} ${table.serviceName?uncap_first}; + + /** + * 分页查询${tableComment} + * + * @param data 分页查询对象 + * @return 查询结果 + */ + @ApiOperation(value = "分页查询${tableComment}", notes = "分页查询${tableComment}") + @ApiImplicitParams({ + @ApiImplicitParam(name = "current", value = "当前页", dataType = "long", paramType = "query", defaultValue = "1"), + @ApiImplicitParam(name = "size", value = "每页显示几条", dataType = "long", paramType = "query", defaultValue = "10"), + }) + @GetMapping("/page") + @SysLog("分页查询${tableComment}") + public R> page(${entity}PageDTO data) { + ${entity} ${entity?uncap_first} = BeanPlusUtil.toBean(data, ${entity}.class); + <#list table.fields as field> + <#-- 自动注入注解 --> + <#if field.customMap.annotation??> + <#assign myPropertyName="${field.propertyName}"/> + <#assign capPropertyName="${field.propertyName?cap_first}"/> + <#assign entityCapPropertyName="${field.propertyName?cap_first}"/> + <#if entityCapPropertyName?ends_with("Id")> + <#assign entityCapPropertyName="${entityCapPropertyName!?substring(0,field.propertyName?index_of('Id'))}"/> + + + if (data != null && data.get${capPropertyName}() != null) { + ${entity?uncap_first}.set${entityCapPropertyName}(new RemoteData<>(data.get${capPropertyName}())); + } + + + + IPage<${entity}> page = getPage(); + // 构建值不为null的查询条件 + LbqWrapper<${entity}> query = Wraps.<${entity}>lbQ(${entity?uncap_first}) + .geHeader(${entity}::getCreateTime, data.getStartCreateTime()) + .leFooter(${entity}::getCreateTime, data.getEndCreateTime()) + .orderByDesc(${entity}::getCreateTime); + ${table.serviceName?uncap_first}.page(page, query); + return success(page); + } + + /** + * 查询${tableComment} + * + * @param id 主键id + * @return 查询结果 + */ + @ApiOperation(value = "查询${tableComment}", notes = "查询${tableComment}") + @GetMapping("/{id}") + @SysLog("查询${tableComment}") + public R<${entity}> get(@PathVariable <#list table.commonFields as field><#if field.keyFlag>${field.propertyType}<#list table.fields as field><#if field.keyFlag>${field.propertyType} id) { + return success(${table.serviceName?uncap_first}.getById(id)); + } + + /** + * 新增${tableComment} + * + * @param data 新增对象 + * @return 新增结果 + */ + @ApiOperation(value = "新增${tableComment}", notes = "新增${tableComment}不为空的字段") + @PostMapping + @SysLog("新增${tableComment}") + public R<${entity}> save(@RequestBody @Validated ${entity}SaveDTO data) { + ${entity} ${entity?uncap_first} = BeanPlusUtil.toBean(data, ${entity}.class); + ${table.serviceName?uncap_first}.save(${entity?uncap_first}); + return success(${entity?uncap_first}); + } + + /** + * 修改${tableComment} + * + * @param data 修改对象 + * @return 修改结果 + */ + @ApiOperation(value = "修改${tableComment}", notes = "修改${tableComment}不为空的字段") + @PutMapping + @SysLog("修改${tableComment}") + public R<${entity}> update(@RequestBody @Validated(SuperEntity.Update.class) ${entity}UpdateDTO data) { + ${entity} ${entity?uncap_first} = BeanPlusUtil.toBean(data, ${entity}.class); + ${table.serviceName?uncap_first}.updateById(${entity?uncap_first}); + return success(${entity?uncap_first}); + } + + /** + * 删除${tableComment} + * + * @param ids 主键id + * @return 删除结果 + */ + @ApiOperation(value = "删除${tableComment}", notes = "根据id物理删除${tableComment}") + @DeleteMapping + @SysLog("删除${tableComment}") + public R delete(@RequestParam("ids[]") <#list table.commonFields as field><#if field.keyFlag>List<${field.propertyType}><#list table.fields as field><#if field.keyFlag>List<${field.propertyType}> ids) { + ${table.serviceName?uncap_first}.removeByIds(ids); + return success(true); + } + + <#if superEntityClass?? && superEntityClass=="TreeEntity"> + /** + * 级联查询${tableComment} + * + * @param data 参数 + * @return 查询结果 + */ + @ApiOperation(value = "级联查询${tableComment}", notes = "级联查询${tableComment}") + @GetMapping + @SysLog("级联查询${tableComment}") + public R> list(${entity} data) { + if (data == null) { + data = new ${entity}(); + } + if (data.getParentId() == null) { + data.setParentId(0L); + } + LbqWrapper<${entity}> wrapper = Wraps.lbQ(data).orderByAsc(${entity}::getSortValue); + return success(${entity?uncap_first}Service.list(wrapper)); + } + +} + diff --git a/ceres-generator-master/src/main/resources/templates/dto.java.ftl b/ceres-generator-master/src/main/resources/templates/dto.java.ftl new file mode 100644 index 0000000..50eb021 --- /dev/null +++ b/ceres-generator-master/src/main/resources/templates/dto.java.ftl @@ -0,0 +1,55 @@ +/* +* Copyright (C) 2017-2021 +* All rights reserved, Designed By 深圳中科鑫智科技有限公司 +* Copyright authorization contact 18814114118 +*/ +package ${cfg.DTO}; + +<#list table.importPackages as pkg> +import ${pkg}; + +<#if swagger2> +import io.swagger.annotations.ApiModel; + +import ${package.Entity}.${entity}; +<#if entityLombokModel> +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + + +import java.io.Serializable; + +/** + *

+ * 实体类 + * ${table.comment!?replace("\n","\n * ")} + *

+ * + * @author ${author} + * @since ${date} + */ +<#if entityLombokModel> +@Data +@NoArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) + +<#if swagger2> + @ApiModel(value = "${entity}DTO", description = "${table.comment!?replace("\r\n"," ")?replace("\r"," ")?replace("\n"," ")}") + +public class ${entity}DTO extends ${entity} implements Serializable { + + /** + * 在DTO中新增并自定义字段,需要覆盖验证的字段,请新建DTO。Entity中的验证规则可以自行修改,但下次生成代码时,记得同步代码!! + */ + private static final long serialVersionUID = 1L; + + public static ${entity}DTO build() { + return new ${entity}DTO(); + } + +} diff --git a/ceres-generator-master/src/main/resources/templates/entity.java.ftl b/ceres-generator-master/src/main/resources/templates/entity.java.ftl new file mode 100644 index 0000000..ad0d9e4 --- /dev/null +++ b/ceres-generator-master/src/main/resources/templates/entity.java.ftl @@ -0,0 +1,240 @@ +/* +* Copyright (C) 2017-2021 +* All rights reserved, Designed By 深圳中科鑫智科技有限公司 +* Copyright authorization contact 18814114118 +*/ +package ${package.Entity}; + +<#list table.importPackages as pkg> +import ${pkg}; + +<#if swagger2> +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import org.hibernate.validator.constraints.Length; +import org.hibernate.validator.constraints.Range; +import java.time.LocalDateTime; +<#if entityLombokModel> +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +<#if cfg.filedTypes??> +<#list cfg.filedTypes as fieldType> + <#list table.fields as field> + <#if field.propertyName == fieldType.name && table.name==fieldType.table && field.propertyType=="String"> +import ${fieldType.packagePath}; + <#break> + + + + + +import static com.baomidou.mybatisplus.annotation.SqlCondition.LIKE; + +<#assign tableComment = "${table.comment!''}"/> +<#if table.comment?? && table.comment!?contains('\n')> + <#assign tableComment = "${table.comment!?substring(0,table.comment?index_of('\n'))?trim}"/> + +/** + *

+ * 实体类 + * ${table.comment!?replace("\n","\n * ")} + *

+ * + * @since ${date} + */ +<#if entityLombokModel> +@Data +@NoArgsConstructor +@ToString(callSuper = true) + +<#if table.convert> +@TableName("${table.name}") + +<#if swagger2> +@ApiModel(value = "${entity}", description = "${tableComment}") + +<#if superEntityClass??> +@AllArgsConstructor +<#assign hasCustomAnno="0"/> +<#if superEntityClass?? && superEntityClass=="TreeEntity"> + <#assign hasCustomAnno="1"/> + +public class ${entity} { +<#elseif activeRecord> +@AllArgsConstructor +public class ${entity} extends Model<${entity}> { +<#else> +public class ${entity} implements Serializable { + + + private static final long serialVersionUID = 1L; + +<#setting number_format="0"> +<#-- ---------- BEGIN 字段循环遍历 ----------> +<#list table.fields as field> + <#if field.keyFlag> + <#assign keyPropertyName="${field.propertyName}"/> + + <#assign fieldComment="${field.comment!}"/> + <#if field.comment!?length gt 0> + /** + * ${field.comment!?replace("\n","\n * ")} + */ + <#if field.comment!?contains("\n") > + <#assign fieldComment="${field.comment!?substring(0,field.comment?index_of('\n'))?replace('\r\n','')?replace('\r','')?replace('\n','')?trim}"/> + + + <#if swagger2> + @ApiModelProperty(value = "${fieldComment}") + + <#assign myPropertyType="${field.propertyType}"/> + <#assign isEnumType="1"/> + <#list cfg.filedTypes as fieldType> + <#if fieldType.name == field.propertyName && table.name==fieldType.table && field.propertyType=="String"> + <#assign myPropertyType="${fieldType.type}"/> + <#assign isEnumType="2"/> + + + <#if field.customMap.Null == "NO" > + <#if (field.columnType!"") == "STRING" && isEnumType == "1"> + @NotEmpty(message = "${fieldComment}不能为空") + <#else> + @NotNull(message = "${fieldComment}不能为空") + + + <#if (field.columnType!"") == "STRING" && isEnumType == "1"> + <#assign max = 255/> + <#if field.type?starts_with("varchar") || field.type?starts_with("char")> + <#if field.type?contains("(")> + <#assign max = field.type?substring(field.type?index_of("(") + 1, field.type?index_of(")"))/> + + @Length(max = ${max}, message = "${fieldComment}长度不能超过${max}") + <#elseif field.type?starts_with("text")> + <#assign max = 65535/> + @Length(max = ${max}, message = "${fieldComment}长度不能超过${max}") + <#elseif field.type?starts_with("mediumtext")> + <#assign max = 16777215/> + @Length(max = ${max}, message = "${fieldComment}长度不能超过${max}") + <#elseif field.type?starts_with("longtext")> + + + <#else> + <#if field.propertyType?starts_with("Short")> + @Range(min = Short.MIN_VALUE, max = Short.MAX_VALUE, message = "${fieldComment}长度不能超过"+Short.MAX_VALUE) + + <#if field.propertyType?starts_with("Byte")> + @Range(min = Byte.MIN_VALUE, max = Byte.MAX_VALUE, message = "${fieldComment}长度不能超过"+Byte.MAX_VALUE) + + <#if field.propertyType?starts_with("Short")> + @Range(min = Short.MIN_VALUE, max = Short.MAX_VALUE, message = "${fieldComment}长度不能超过"+Short.MAX_VALUE) + + + <#if field.keyFlag> + <#-- 主键 --> + <#if field.keyIdentityFlag> + @TableId(value = "${field.name}", type = IdType.AUTO) + <#elseif idType??> + @TableId(value = "${field.name}", type = IdType.${idType}) + <#elseif field.convert> + @TableId("${field.name}") + + <#-- 普通字段 --> + <#elseif field.fill??> + <#-- ----- 存在字段填充设置 -----> + <#if field.convert> + @TableField(value = "${field.name}", fill = FieldFill.${field.fill}) + <#else> + @TableField(fill = FieldFill.${field.fill}) + + <#elseif field.convert> + <#if (field.type?starts_with("varchar") || field.type?starts_with("char")) && myPropertyType == "String"> + @TableField(value = "${field.name}", condition = LIKE) + <#else> + @TableField("${field.name}") + + + <#-- 乐观锁注解 --> + <#if (versionFieldName!"") == field.name> + @Version + + <#-- 逻辑删除注解 --> + <#if (logicDeleteFieldName!"") == field.name> + @TableLogic + + <#assign myPropertyName="${field.propertyName}"/> + <#-- 自动注入注解 --> + <#if field.customMap.annotation??> + ${field.customMap.annotation} + @ExcelEntity(name = "") + <#assign myPropertyType="${field.customMap.type}"/> + <#if field.propertyName?ends_with("Id")> + <#assign myPropertyName="${field.propertyName!?substring(0,field.propertyName?index_of('Id'))}"/> + + + private ${myPropertyType} ${myPropertyName}; + + + +<#------------ END 字段循环遍历 ----------> +<#if !entityLombokModel> + + <#list table.fields as field> + <#if field.propertyType == "boolean"> + <#assign getprefix="is"/> + <#else> + <#assign getprefix="get"/> + + public ${field.propertyType} ${getprefix}${field.capitalName}() { + return ${field.propertyName}; + } + + <#if entityBuilderModel> + public ${entity} set${field.capitalName}(${field.propertyType} ${field.propertyName}) { + <#else> + public void set${field.capitalName}(${field.propertyType} ${field.propertyName}) { + + this.${field.propertyName} = ${field.propertyName}; + <#if entityBuilderModel> + return this; + + } + + + +<#if activeRecord> + + @Override + protected Serializable pkVal() { + <#if keyPropertyName??> + return this.${keyPropertyName}; + <#else> + return null; + + } + +<#if !entityLombokModel> + + @Override + public String toString() { + return "${entity}{" + + <#list table.fields as field> + <#if field_index==0> + "${field.propertyName}=" + ${field.propertyName} + + <#else> + ", ${field.propertyName}=" + ${field.propertyName} + + + + "}"; + } + + +} diff --git a/ceres-generator-master/src/main/resources/templates/enum.java.ftl b/ceres-generator-master/src/main/resources/templates/enum.java.ftl new file mode 100644 index 0000000..c01708c --- /dev/null +++ b/ceres-generator-master/src/main/resources/templates/enum.java.ftl @@ -0,0 +1,83 @@ +package ${enumCustom.package.importPackage}; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.zkthink.base.BaseEnum; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; +import lombok.Getter; + +<#assign tableComment="${table.comment!}"/> +<#if table.comment!?length gt 0> + <#if table.comment!?contains("\n") > + <#assign tableComment="${table.comment!?substring(0,table.comment?index_of('\n'))?trim}"/> + + +/** + *

+ * 实体注释中生成的类型枚举 + * ${table.comment!?replace("\n","\n * ")} + *

+ * + * @author ${author} + * @date ${date} + */ +@Getter +@AllArgsConstructor +@NoArgsConstructor +@ApiModel(value = "${enumCustom.enumName}", description = "${enumCustom.comment}-枚举") +@JsonFormat(shape = JsonFormat.Shape.OBJECT) +public enum ${enumCustom.enumName} implements BaseEnum { + + <#list enumCustom.list?keys as key> + /** + * ${key?upper_case}=<#list enumCustom.list[key] as des><#if enumCustom.firstTypeNumber=="false">"${des?trim}"<#else >${des?trim} + */ + ${key?upper_case}(<#list enumCustom.list[key] as des><#if des_index == 0 && enumCustom.firstTypeNumber=="true">${des?trim}<#else>"${des?trim}"<#if des_has_next>,), + + ; + +<#list enumCustom.list?keys as key> +<#list enumCustom.list[key] as des> + <#if des_index == 0> + @ApiModelProperty(value = "描述") + + private <#if des_index == 0 && enumCustom.firstTypeNumber=="true">int<#else >String <#if des_index == 0 && (enumCustom.list[key]?size == 1)>desc<#elseif des_index == 0 && (enumCustom.list[key]?size > 1)>val<#elseif des_index == 1 >desc<#else>other${enumCustom.list?size}; + + +<#break> + + + public static ${enumCustom.enumName} match(String val, ${enumCustom.enumName} def) { + for (${enumCustom.enumName} enm : ${enumCustom.enumName}.values()) { + if (enm.name().equalsIgnoreCase(val)) { + return enm; + } + } + return def; + } + + public static ${enumCustom.enumName} get(String val) { + return match(val, null); + } + + public boolean eq(String val) { + return this.name().equalsIgnoreCase(val); + } + + public boolean eq(${enumCustom.enumName} val) { + if (val == null) { + return false; + } + return eq(val.name()); + } + + @Override + @ApiModelProperty(value = "编码", allowableValues = "<#list enumCustom.list?keys as key>${key?upper_case}<#if key_has_next>,", example = "${enumCustom.list?keys[0]?upper_case}") + public String getCode() { + return this.name(); + } + +} diff --git a/ceres-generator-master/src/main/resources/templates/mapper.java.ftl b/ceres-generator-master/src/main/resources/templates/mapper.java.ftl new file mode 100644 index 0000000..4753539 --- /dev/null +++ b/ceres-generator-master/src/main/resources/templates/mapper.java.ftl @@ -0,0 +1,20 @@ +/* +* Copyright (C) 2017-2021 +* All rights reserved, Designed By 深圳中科鑫智科技有限公司 +* Copyright authorization contact 18814114118 +*/ +package ${package.Mapper}; + +import ${superMapperClassPackage}; +import ${package.Entity}.${entity}; + +import org.apache.ibatis.annotations.Mapper; + +@Mapper +<#if kotlin> +interface ${table.mapperName} : ${superMapperClass}<${entity}> +<#else> +public interface ${entity}DAO extends ${superMapperClass}<${entity}> { + +} + diff --git a/ceres-generator-master/src/main/resources/templates/mapper.xml.ftl b/ceres-generator-master/src/main/resources/templates/mapper.xml.ftl new file mode 100644 index 0000000..5852839 --- /dev/null +++ b/ceres-generator-master/src/main/resources/templates/mapper.xml.ftl @@ -0,0 +1,98 @@ + + + + +<#if enableCache> + + + + +<#if baseResultMap> + + +<#list table.fields as field> +<#if field.keyFlag><#--生成主键排在第一位--> + <#if field.type?starts_with("int")> + + <#elseif field.type?starts_with("datetime")> + + <#elseif field.type?starts_with("text") || field.type?starts_with("longtext")> + + <#else> + <#if field.type?contains("(")> + <#assign fType = field.type?substring(0, field.type?index_of("("))?upper_case/> + + <#else> + + + + + +<#list table.commonFields as field><#--生成公共字段 --> + <#if field.keyFlag> + <#if field.type?starts_with("int")> + + <#elseif field.type?starts_with("datetime")> + + <#elseif field.type?starts_with("text") || field.type?starts_with("longtext")> + + <#else> + <#if field.type?contains("(")> + <#assign fType = field.type?substring(0, field.type?index_of("("))?upper_case/> + + <#else> + + + + <#else> + <#if field.type?starts_with("int")> + + <#elseif field.type?starts_with("datetime")> + + <#elseif field.type?starts_with("text") || field.type?starts_with("longtext") || field.type?starts_with("mediumtext")> + + <#else> + <#if field.type?contains("(")> + <#assign fType = field.type?substring(0, field.type?index_of("("))?upper_case/> + + <#else> + + + + + +<#list table.fields as field> +<#if !field.keyFlag><#--生成普通字段 --> + + <#assign myPropertyName="${field.propertyName}"/> + <#-- 自动注入注解 --> + <#if field.customMap.annotation?? && field.propertyName?ends_with("Id")> + <#assign myPropertyName="${field.propertyName!?substring(0,field.propertyName?index_of('Id'))}"/> + + <#if field.type?starts_with("int")> + + <#elseif field.type?starts_with("datetime")> + + <#elseif field.type?starts_with("text") || field.type?starts_with("longtext") || field.type?starts_with("mediumtext")> + + <#else> + <#if field.type?contains("(")> + <#assign fType = field.type?substring(0, field.type?index_of("("))?upper_case/> + + <#else> + + + + + + + + +<#if baseColumnList> + + + ${table.fieldNames} + + + + diff --git a/ceres-generator-master/src/main/resources/templates/pageDto.java.ftl b/ceres-generator-master/src/main/resources/templates/pageDto.java.ftl new file mode 100644 index 0000000..4467997 --- /dev/null +++ b/ceres-generator-master/src/main/resources/templates/pageDto.java.ftl @@ -0,0 +1,148 @@ +/* +* Copyright (C) 2017-2021 +* All rights reserved, Designed By 深圳中科鑫智科技有限公司 +* Copyright authorization contact 18814114118 +*/ +package ${cfg.PageDTO}; + +import java.time.LocalDateTime; +<#list table.importPackages as pkg> +import ${pkg}; + +<#if swagger2> +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import org.hibernate.validator.constraints.Length; +import org.hibernate.validator.constraints.Range; +<#if entityLombokModel> +import lombok.Data; +import lombok.Builder; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.AllArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +<#list cfg.filedTypes as fieldType> + <#list table.fields as field> + <#if field.propertyName == fieldType.name && table.name==fieldType.table && field.propertyType=="String"> +import ${fieldType.packagePath}; + <#break> + + + +import java.io.Serializable; + +/** + *

+ * 实体类 + * ${table.comment!?replace("\n","\n * ")} + *

+ * + * @author ${author} + * @since ${date} + */ +<#if entityLombokModel> +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder + +<#if swagger2> +@ApiModel(value = "${entity}PageDTO", description = "${table.comment!?replace("\r\n"," ")?replace("\r"," ")?replace("\n"," ")}") + +public class ${entity}PageDTO implements Serializable { + + private static final long serialVersionUID = 1L; + +<#list table.fields as field> +<#-- 如果有父类,排除公共字段 --> +<#if (superEntityClass?? && cfg.superExtend?? && field.propertyName !="id") || (superEntityClass?? && field.propertyName !="id" && field.propertyName !="createTime" && field.propertyName != "updateTime" && field.propertyName !="createUser" && field.propertyName !="updateUser") || !superEntityClass??> + <#if field.keyFlag> + <#assign keyPropertyName="${field.propertyName}"/> + + <#assign fieldComment="${field.comment!}"/> + <#if field.comment!?length gt 0> + /** + * ${field.comment!?replace("\n","\n * ")} + */ + <#if field.comment!?contains("\n") > + <#assign fieldComment="${field.comment!?substring(0,field.comment?index_of('\n'))?replace('\r\n','')?replace('\r','')?replace('\n','')?trim}"/> + + + <#if swagger2> + @ApiModelProperty(value = "${fieldComment}") + + <#assign myPropertyType="${field.propertyType}"/> + <#assign isEnumType="1"/> + <#list cfg.filedTypes as fieldType> + <#if fieldType.name == field.propertyName && table.name==fieldType.table && field.propertyType=="String"> + <#assign myPropertyType="${fieldType.type}"/> + <#assign isEnumType="2"/> + + + <#if field.customMap.Null == "NO" > + <#if (field.columnType!"") == "STRING" && isEnumType == "1"> + @NotEmpty(message = "${fieldComment}不能为空") + <#else> + @NotNull(message = "${fieldComment}不能为空") + + + <#if (field.columnType!"") == "STRING" && isEnumType == "1"> + <#assign max = 255/> + <#if field.type?starts_with("varchar") || field.type?starts_with("char")> + <#if field.type?contains("(")> + <#assign max = field.type?substring(field.type?index_of("(") + 1, field.type?index_of(")"))/> + + @Length(max = ${max}, message = "${fieldComment}长度不能超过${max}") + <#elseif field.type?starts_with("text")> + <#assign max = 65535/> + @Length(max = ${max?string["0"]}, message = "${fieldComment}长度不能超过${max}") + <#elseif field.type?starts_with("mediumtext")> + <#assign max = 16777215/> + @Length(max = ${max?string["0"]}, message = "${fieldComment}长度不能超过${max}") + <#elseif field.type?starts_with("longtext")> + + <#else> + <#if field.propertyType?starts_with("Short")> + @Range(min = Short.MIN_VALUE, max = Short.MAX_VALUE, message = "${fieldComment}长度不能超过"+Short.MAX_VALUE) + + <#if field.propertyType?starts_with("Byte")> + @Range(min = Byte.MIN_VALUE, max = Byte.MAX_VALUE, message = "${fieldComment}长度不能超过"+Byte.MAX_VALUE) + + <#if field.propertyType?starts_with("Short")> + @Range(min = Short.MIN_VALUE, max = Short.MAX_VALUE, message = "${fieldComment}长度不能超过"+Short.MAX_VALUE) + + + <#-- 自动注入注解 --> + <#if field.customMap.annotation??> + ${field.customMap.annotation} + <#assign myPropertyType="${field.customMap.type}"/> + <#if field.propertyName?ends_with("Id")> + <#assign myPropertyName="${field.propertyName!?substring(0,field.propertyName?index_of('Id'))}"/> + + + <#assign myPropertyName="${field.propertyName}"/> + private ${myPropertyType} ${myPropertyName}; + + + +<#if superEntityClass?? && superEntityClass=="TreeEntity"> + @ApiModelProperty(value = "名称") + @NotEmpty(message = "名称不能为空") + @Length(max = 255, message = "名称长度不能超过255") + protected String label; + + @ApiModelProperty(value = "父ID") + protected <#list table.commonFields as field><#if field.keyFlag>${field.propertyType} parentId; + + @ApiModelProperty(value = "排序号") + protected Integer sortValue; + +} diff --git a/ceres-generator-master/src/main/resources/templates/saveDto.java.ftl b/ceres-generator-master/src/main/resources/templates/saveDto.java.ftl new file mode 100644 index 0000000..5ad5bed --- /dev/null +++ b/ceres-generator-master/src/main/resources/templates/saveDto.java.ftl @@ -0,0 +1,147 @@ +/* +* Copyright (C) 2017-2021 +* All rights reserved, Designed By 深圳中科鑫智科技有限公司 +* Copyright authorization contact 18814114118 +*/ +package ${cfg.SaveDTO}; + +<#list table.importPackages as pkg> +import ${pkg}; + +<#if swagger2> +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import org.hibernate.validator.constraints.Length; +import org.hibernate.validator.constraints.Range; +<#if entityLombokModel> +import lombok.Data; +import lombok.Builder; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.AllArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +<#list cfg.filedTypes as fieldType> + <#list table.fields as field> + <#if field.propertyName == fieldType.name && table.name==fieldType.table && field.propertyType=="String"> +import ${fieldType.packagePath}; + <#break> + + + +import java.io.Serializable; + +/** + *

+ * 实体类 + * ${table.comment!?replace("\n","\n * ")} + *

+ * + * @author ${author} + * @since ${date} + */ +<#if entityLombokModel> +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder + +<#if swagger2> +@ApiModel(value = "${entity}SaveDTO", description = "${table.comment!?replace("\r\n"," ")?replace("\r"," ")?replace("\n"," ")}") + +public class ${entity}SaveDTO implements Serializable { + + private static final long serialVersionUID = 1L; + +<#list table.fields as field> +<#-- 如果有父类,排除公共字段 --> +<#if (superEntityClass?? && cfg.superExtend?? && field.propertyName !="id") || (superEntityClass?? && field.propertyName !="id" && field.propertyName !="createTime" && field.propertyName != "updateTime" && field.propertyName !="createUser" && field.propertyName !="updateUser") || !superEntityClass??> + <#if field.keyFlag> + <#assign keyPropertyName="${field.propertyName}"/> + + <#assign fieldComment="${field.comment!}"/> + <#if field.comment!?length gt 0> + /** + * ${field.comment!?replace("\n","\n * ")} + */ + <#if field.comment!?contains("\n") > + <#assign fieldComment="${field.comment!?substring(0,field.comment?index_of('\n'))?replace('\r\n','')?replace('\r','')?replace('\n','')?trim}"/> + + + <#if swagger2> + @ApiModelProperty(value = "${fieldComment}") + + <#assign myPropertyType="${field.propertyType}"/> + <#assign isEnumType="1"/> + <#list cfg.filedTypes as fieldType> + <#if fieldType.name == field.propertyName && table.name==fieldType.table && field.propertyType=="String"> + <#assign myPropertyType="${fieldType.type}"/> + <#assign isEnumType="2"/> + + + <#if field.customMap.Null == "NO" > + <#if (field.columnType!"") == "STRING" && isEnumType == "1"> + @NotEmpty(message = "${fieldComment}不能为空") + <#else> + @NotNull(message = "${fieldComment}不能为空") + + + <#if (field.columnType!"") == "STRING" && isEnumType == "1"> + <#assign max = 255/> + <#if field.type?starts_with("varchar") || field.type?starts_with("char")> + <#if field.type?contains("(")> + <#assign max = field.type?substring(field.type?index_of("(") + 1, field.type?index_of(")"))/> + + @Length(max = ${max}, message = "${fieldComment}长度不能超过${max}") + <#elseif field.type?starts_with("text")> + <#assign max = 65535/> + @Length(max = ${max?string["0"]}, message = "${fieldComment}长度不能超过${max}") + <#elseif field.type?starts_with("mediumtext")> + <#assign max = 16777215/> + @Length(max = ${max?string["0"]}, message = "${fieldComment}长度不能超过${max}") + <#elseif field.type?starts_with("longtext")> + + <#else> + <#if field.propertyType?starts_with("Short")> + @Range(min = Short.MIN_VALUE, max = Short.MAX_VALUE, message = "${fieldComment}长度不能超过"+Short.MAX_VALUE) + + <#if field.propertyType?starts_with("Byte")> + @Range(min = Byte.MIN_VALUE, max = Byte.MAX_VALUE, message = "${fieldComment}长度不能超过"+Byte.MAX_VALUE) + + <#if field.propertyType?starts_with("Short")> + @Range(min = Short.MIN_VALUE, max = Short.MAX_VALUE, message = "${fieldComment}长度不能超过"+Short.MAX_VALUE) + + + <#assign myPropertyName="${field.propertyName}"/> + <#-- 自动注入注解 --> + <#if field.customMap.annotation??> + ${field.customMap.annotation} + <#assign myPropertyType="${field.customMap.type}"/> + <#if field.propertyName?ends_with("Id")> + <#assign myPropertyName="${field.propertyName!?substring(0,field.propertyName?index_of('Id'))}"/> + + + private ${myPropertyType} ${myPropertyName}; + + + +<#if superEntityClass?? && superEntityClass=="TreeEntity"> + @ApiModelProperty(value = "名称") + @NotEmpty(message = "名称不能为空") + @Length(max = 255, message = "名称长度不能超过255") + protected String label; + + @ApiModelProperty(value = "父ID") + protected <#list table.commonFields as field><#if field.keyFlag>${field.propertyType} parentId; + + @ApiModelProperty(value = "排序号") + protected Integer sortValue; + +} diff --git a/ceres-generator-master/src/main/resources/templates/service.java.ftl b/ceres-generator-master/src/main/resources/templates/service.java.ftl new file mode 100644 index 0000000..da35916 --- /dev/null +++ b/ceres-generator-master/src/main/resources/templates/service.java.ftl @@ -0,0 +1,25 @@ +/* +* Copyright (C) 2017-2021 +* All rights reserved, Designed By 深圳中科鑫智科技有限公司 +* Copyright authorization contact 18814114118 +*/ +package ${package.Service}; + +import ${package.Entity}.${entity}; + +/** + *

+ * 业务接口 + * ${table.comment!?replace("\n","\n * ")} + *

+ * + * @author ${author} + * @date ${date} + */ +<#if kotlin> +interface ${table.serviceName} : ${superServiceClass}<${entity}> +<#else> +public interface ${table.serviceName} { + +} + diff --git a/ceres-generator-master/src/main/resources/templates/serviceImpl.java.ftl b/ceres-generator-master/src/main/resources/templates/serviceImpl.java.ftl new file mode 100644 index 0000000..e280c41 --- /dev/null +++ b/ceres-generator-master/src/main/resources/templates/serviceImpl.java.ftl @@ -0,0 +1,58 @@ +/* +* Copyright (C) 2017-2021 +* All rights reserved, Designed By 深圳中科鑫智科技有限公司 +* Copyright authorization contact 18814114118 +*/ +package ${package.ServiceImpl}; + +import ${package.Mapper}.${entity}DAO; +import ${package.Entity}.${entity}; +import ${package.Service}.${table.serviceName}; + +import lombok.extern.slf4j.Slf4j; +<#if superServiceImplClass?? && superServiceImplClass == "SuperCacheServiceImpl"> +import org.springframework.aop.framework.AopContext; +import org.springframework.cache.annotation.CacheConfig; + +import org.springframework.stereotype.Service; + +/** + *

+ * 业务实现类 + * ${table.comment!?replace("\n","\n * ")} + *

+ * + * @author ${author} + * @date ${date} + */ +@Slf4j +@Service +<#if superServiceImplClass?? && superServiceImplClass == "SuperCacheServiceImpl"> +@CacheConfig(cacheNames = ${table.serviceImplName}.${entity?upper_case}) + +<#if kotlin> +open class ${table.serviceImplName} : ${superServiceImplClass}<${table.mapperName}, ${entity}>(), ${table.serviceName} { +} +<#else> +<#if superServiceImplClass??> +public class ${table.serviceImplName} implements ${table.serviceName} { +<#else> +public class ${table.serviceImplName} { + +<#if superServiceImplClass?? && superServiceImplClass == "SuperCacheServiceImpl"> + /** + * 建议将改变量移动到CacheKey工具类中统一管理,并在 caffeine.properties 文件中合理配置有效期 + */ + protected static final String ${entity?upper_case} = "${entity?lower_case}"; + + @Override + protected String getRegion() { + return ${entity?upper_case}; + } + + protected ${table.serviceName} currentProxy() { + return ((${table.serviceName}) AopContext.currentProxy()); + } + +} + diff --git a/ceres-generator-master/src/main/resources/templates/updateDto.java.ftl b/ceres-generator-master/src/main/resources/templates/updateDto.java.ftl new file mode 100644 index 0000000..fc9dd43 --- /dev/null +++ b/ceres-generator-master/src/main/resources/templates/updateDto.java.ftl @@ -0,0 +1,162 @@ +/* +* Copyright (C) 2017-2021 +* All rights reserved, Designed By 深圳中科鑫智科技有限公司 +* Copyright authorization contact 18814114118 +*/ +package ${cfg.SaveDTO}; + +<#list table.importPackages as pkg> +import ${pkg}; + +<#if swagger2> +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import org.hibernate.validator.constraints.Length; +import org.hibernate.validator.constraints.Range; +import com.zkthink.base.entity.SuperEntity; +<#if entityLombokModel> +import lombok.Data; +import lombok.Builder; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.AllArgsConstructor; +import lombok.ToString; +import lombok.experimental.Accessors; + +<#list cfg.filedTypes as fieldType> + <#list table.fields as field> + <#if field.propertyName == fieldType.name && table.name==fieldType.table && field.propertyType=="String"> +import ${fieldType.packagePath}; + <#break> + + + +import java.io.Serializable; + +/** + *

+ * 实体类 + * ${table.comment!?replace("\n","\n * ")} + *

+ * + * @author ${author} + * @since ${date} + */ +<#if entityLombokModel> +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = false) +@Builder + +<#if swagger2> +@ApiModel(value = "${entity}UpdateDTO", description = "${table.comment!?replace("\r\n"," ")?replace("\r"," ")?replace("\n"," ")}") + +public class ${entity}UpdateDTO implements Serializable { + + private static final long serialVersionUID = 1L; + +<#list table.commonFields as field> + <#if field.keyFlag> + @ApiModelProperty(value = "主键") + @NotNull(message = "id不能为空", groups = SuperEntity.Update.class) + private ${field.propertyType} ${field.propertyName}; + + + +<#list table.fields as field> +<#-- 如果有父类,排除公共字段 --> +<#if (superEntityClass?? && cfg.superExtend?? && field.propertyName !="id") || (superEntityClass?? && field.propertyName !="id" && field.propertyName !="createTime" && field.propertyName != "updateTime" && field.propertyName !="createUser" && field.propertyName !="updateUser") || !superEntityClass??> + <#if field.keyFlag> + <#assign keyPropertyName="${field.propertyName}"/> + + <#assign fieldComment="${field.comment!}"/> + <#if field.comment!?length gt 0> + /** + * ${field.comment!?replace("\n","\n * ")} + */ + <#if field.comment!?contains("\n") > + <#assign fieldComment="${field.comment!?substring(0,field.comment?index_of('\n'))?replace('\r\n','')?replace('\r','')?replace('\n','')?trim}"/> + + + <#if swagger2> + @ApiModelProperty(value = "${fieldComment}") + + <#assign myPropertyType="${field.propertyType}"/> + <#assign isEnumType="1"/> + <#list cfg.filedTypes as fieldType> + <#if fieldType.name == field.propertyName && table.name==fieldType.table && field.propertyType=="String"> + <#assign myPropertyType="${fieldType.type}"/> + <#assign isEnumType="2"/> + + + <#if field.customMap.dict??> + <#assign isEnumType="3"/> + + <#if field.customMap.Null == "NO" > + <#if (field.columnType!"") == "STRING" && isEnumType == "1"> + @NotEmpty(message = "${fieldComment}不能为空") + <#else> + @NotNull(message = "${fieldComment}不能为空") + + + <#if (field.columnType!"") == "STRING" && isEnumType == "1"> + <#assign max = 255/> + <#if field.type?starts_with("varchar") || field.type?starts_with("char")> + <#if field.type?contains("(")> + <#assign max = field.type?substring(field.type?index_of("(") + 1, field.type?index_of(")"))/> + + @Length(max = ${max}, message = "${fieldComment}长度不能超过${max}") + <#elseif field.type?starts_with("text")> + <#assign max = 65535/> + @Length(max = ${max?string["0"]}, message = "${fieldComment}长度不能超过${max}") + <#elseif field.type?starts_with("mediumtext")> + <#assign max = 16777215/> + @Length(max = ${max?string["0"]}, message = "${fieldComment}长度不能超过${max}") + <#elseif field.type?starts_with("longtext")> + + <#else> + <#if field.propertyType?starts_with("Short")> + @Range(min = Short.MIN_VALUE, max = Short.MAX_VALUE, message = "${fieldComment}长度不能超过"+Short.MAX_VALUE) + + <#if field.propertyType?starts_with("Byte")> + @Range(min = Byte.MIN_VALUE, max = Byte.MAX_VALUE, message = "${fieldComment}长度不能超过"+Byte.MAX_VALUE) + + <#if field.propertyType?starts_with("Short")> + @Range(min = Short.MIN_VALUE, max = Short.MAX_VALUE, message = "${fieldComment}长度不能超过"+Short.MAX_VALUE) + + + <#if field.customMap.dict??> + @DictionaryType("${field.customMap.dict}") + <#assign myPropertyType="Dictionary"/> + + <#assign myPropertyName="${field.propertyName}"/> +<#-- 自动注入注解 --> + <#if field.customMap.annotation??> + ${field.customMap.annotation} + <#assign myPropertyType="${field.customMap.type}"/> + <#if field.propertyName?ends_with("Id")> + <#assign myPropertyName="${field.propertyName!?substring(0,field.propertyName?index_of('Id'))}"/> + + + private ${myPropertyType} ${myPropertyName}; + + +<#if superEntityClass?? && superEntityClass=="TreeEntity"> + @ApiModelProperty(value = "名称") + @NotEmpty(message = "名称不能为空") + @Length(max = 255, message = "名称长度不能超过255") + protected String label; + + @ApiModelProperty(value = "父ID") + protected <#list table.commonFields as field><#if field.keyFlag>${field.propertyType} parentId; + + @ApiModelProperty(value = "排序号") + protected Integer sortValue; + +} diff --git a/ceres-generator-master/src/test/java/CommonGenerator.java b/ceres-generator-master/src/test/java/CommonGenerator.java new file mode 100644 index 0000000..dcb43c5 --- /dev/null +++ b/ceres-generator-master/src/test/java/CommonGenerator.java @@ -0,0 +1,53 @@ +import com.zkthink.ceres.generator.CodeGenerator; +import com.zkthink.ceres.generator.config.CodeGeneratorConfig; +import com.zkthink.ceres.generator.config.FileCreateConfig; +import com.zkthink.ceres.generator.type.EntityType; +import com.zkthink.ceres.generator.type.GenerateType; + +import java.util.Arrays; +import java.util.List; + +/** + */ +public class CommonGenerator { + + public static void main(String[] args) { + CodeGeneratorConfig build = buildMemberEntity(); + + // 下面是数据库的账号和密码 + build.setUsername("root"); + build.setPassword("123456"); + + System.out.println("输出路径:"); + // 这里需要设置成你的项目所在的路径 + String outputPath = System.getProperty("user.dir") + "/ceres/ceres-product"; + System.out.println(outputPath); + build.setProjectRootPath(outputPath); + + FileCreateConfig fileCreateConfig = new FileCreateConfig(GenerateType.OVERRIDE); + build.setFileCreateConfig(fileCreateConfig); + + build.setProjectPrefix("cereshop"); + for (String module:CodeGeneratorConfig.CERESHOP_MODULAR_LIST) { + build.setCurrentModule(module); + CodeGenerator.run(build); + } + } + + + private static CodeGeneratorConfig buildMemberEntity() { + List tables = Arrays.asList( + "cere_generate_test" + ); + //这一行不用改,第四个参数是表名称的前缀 + CodeGeneratorConfig build = CodeGeneratorConfig. + build("", "", "", "cere", tables); + //填写基础包 + build.setPackageBase("com.shop.cereshop"); + //填写子包名称 + build.setChildPackageName("live"); + //设置数据库url + build.setUrl("jdbc:mysql://127.0.0.1:3306/cereshop1.6?serverTimezone=CTT&characterEncoding=utf8&useUnicode=true&useSSL=false&autoReconnect=true&zeroDateTimeBehavior=convertToNull"); + return build; + } +}