Skip to content

Commit

Permalink
feat(codegen): support feature and test and table generation based on…
Browse files Browse the repository at this point in the history
… template or generator
  • Loading branch information
wangyingjie3 committed Jul 12, 2024
1 parent 3526694 commit 1e0f9f3
Show file tree
Hide file tree
Showing 13 changed files with 538 additions and 0 deletions.
17 changes: 17 additions & 0 deletions jcommon/codegen/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,23 @@
<artifactId>beetl</artifactId>
<version>2.7.14</version>
</dependency>
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-codegen</artifactId>
<version>1.7.8</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.29</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>4.0.3</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
package run.mone.ai.codegen;

import com.mybatisflex.codegen.Generator;
import com.mybatisflex.codegen.config.GlobalConfig;
import com.zaxxer.hikari.HikariDataSource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.jdbc.core.JdbcTemplate;
import run.mone.ai.codegen.bo.FeatureGeneratType;
import run.mone.ai.codegen.bo.FeatureGenerateBo;
import run.mone.ai.codegen.util.TemplateUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
* @author goodjava@qq.com, HawickMason@xiaomi.com
* @date 7/12/24 9:44 AM
*/
@Slf4j
public class FeatureGenerator {

public static void generateWithTemplate(FeatureGenerateBo featureGenerateBo) {

// 类型检查
if (Objects.isNull(featureGenerateBo.getType())) {
log.warn("Empty generation type, will do noting!");
return;
}
FeatureGeneratType featureGenType = featureGenerateBo.getType();
if (FeatureGeneratType.CODE_WITH_TEMPLATE != featureGenType
&& FeatureGeneratType.TABLE != featureGenType) {
log.warn("generate type:{} is not match with current call", featureGenType);
return;
}

//配置数据源
HikariDataSource dataSource = new HikariDataSource();
dataSource.setJdbcUrl(featureGenerateBo.getJdbcUrl());
dataSource.setUsername(featureGenerateBo.getUserName());
dataSource.setPassword(featureGenerateBo.getPassword());

//创建mapper相关代码
if (FeatureGeneratType.CODE_WITH_TEMPLATE == featureGenType) {
GlobalConfig globalConfig = createGlobalConfigUseStyle(featureGenerateBo);
Generator generator = new Generator(dataSource, globalConfig);
generator.generate();
return;
}

//创建table
if (FeatureGeneratType.TABLE == featureGenType) {
JdbcTemplate jt = new JdbcTemplate(dataSource);
jt.update(featureGenerateBo.getSql());
}
}

public static GlobalConfig createGlobalConfigUseStyle(FeatureGenerateBo featureGenerateBo) {
GlobalConfig globalConfig = new GlobalConfig();
//设置根包
String basePackage = featureGenerateBo.getBasePackage();
globalConfig.setBasePackage(basePackage);
//表的名字
globalConfig.setGenerateTable(featureGenerateBo.getTableName());
globalConfig.setTablePrefix("");
//设置生成 entity 并启用 Lombok
globalConfig.setEntityGenerateEnable(true);
globalConfig.setEntityWithLombok(true);
globalConfig.setServiceGenerateEnable(true);
globalConfig.setServiceImplGenerateEnable(true);
globalConfig.enableController();

//生成entity mapper service controller
String dir = featureGenerateBo.getBasePath();
globalConfig.setMapperGenerateEnable(true);
globalConfig.getEntityConfig().setSourceDir(dir);
globalConfig.getMapperConfig().setSourceDir(dir);
globalConfig.getServiceConfig().setSourceDir(dir);
globalConfig.getServiceImplConfig().setSourceDir(dir);
globalConfig.getControllerConfig().setSourceDir(dir);

globalConfig.setEntityPackage(basePackage + ".dao.entity");
globalConfig.setMapperPackage(basePackage + ".dao.mapper");
globalConfig.setServicePackage(basePackage + ".service");
globalConfig.setServiceImplPackage(basePackage + ".service");
globalConfig.setControllerPackage(basePackage + ".controller");

return globalConfig;
}

public static void generateByTemplate(FeatureGenerateBo featureGenerateBo) {
String className = featureGenerateBo.getClassName();
if (StringUtils.isEmpty(className)) {
return;
}
Map<String, Object> data = new HashMap<>();
data.put("className", className);
data.put("author", "goodjava@qq.com");

String basePath = featureGenerateBo.getBasePath();
String basePackage = featureGenerateBo.getBasePackage();
String midPath = replaceDotWithSlash(basePackage);
log.info("generate by template with base path:{}", basePath);
// 调用方法并获取结果
if (featureGenerateBo.isCreatePojo()) {
String pojo = TemplateUtils.renderTemplateFromFile("tlp/pojo.java", data);
TemplateUtils.writeStringToFile(pojo, getFilePath(basePath, featureGenerateBo.getServiceModulePath(), midPath, "/model/po/", className, ".java"));
}

if (featureGenerateBo.isCreateVo()) {
String vo = TemplateUtils.renderTemplateFromFile("tlp/vo.java", data);
TemplateUtils.writeStringToFile(vo, getFilePath(basePath, featureGenerateBo.getApiModulePath(), midPath, "/api/vo/", className, "VO.java"));
}

if (featureGenerateBo.isCreateTransfer()) {
String transfer = TemplateUtils.renderTemplateFromFile("tlp/transfer.java", data);
TemplateUtils.writeStringToFile(transfer, getFilePath(basePath, featureGenerateBo.getServiceModulePath(), midPath, "/model/transfer/", className, "Transfer.java"));
}

if (featureGenerateBo.isCreateService()) {
String service = TemplateUtils.renderTemplateFromFile("tlp/service.java", data);
TemplateUtils.writeStringToFile(service, getFilePath(basePath, featureGenerateBo.getServiceModulePath(), midPath, "/service/", className, "Service.java"));
}

if (featureGenerateBo.isCreateTest()) {
String cn = className + "ServiceTest.java";
String test = TemplateUtils.renderTemplateFromFile("tlp/test.java", data);
TemplateUtils.writeStringToFile(test, basePath + "/" + featureGenerateBo.getServerModulePath() + "/src/test/java/run/mone/test/service/" + cn);
}

if (featureGenerateBo.isCreateController()) {
String controller = TemplateUtils.renderTemplateFromFile("tlp/controller.java", data);
TemplateUtils.writeStringToFile(controller, getFilePath(basePath, featureGenerateBo.getServerModulePath(), midPath, "/controller/", className, "Controller.java"));
}
}

private static String getFilePath(String basePath, String modulePath, String midPath, String subPath, String className, String suffix) {
return basePath + "/" + modulePath + "/src/main/java/" + midPath + subPath + className + suffix;
}

// 将字符串中的"."替换为"/"
public static String replaceDotWithSlash(String input) {
if (input == null) {
return null;
}
return input.replace(".", "/");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package run.mone.ai.codegen;

import lombok.extern.slf4j.Slf4j;

/**
* @author goodjava@qq.com, HawickMason@xiaomi.com
* @date 7/11/24 14:14
*/
@Slf4j
public class UnitTestGenerator {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package run.mone.ai.codegen.bo;

import java.util.Arrays;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
* @author goodjava@qq.com, HawickMason@xiaomi.com
* @date 7/12/24 14:15
*/
public enum FeatureGeneratType {

CODE_WITH_GENERATOR(1, "使用mybatis-flex-generator生成"),

CODE_WITH_TEMPLATE(2, "使用预制模板生成"),

TABLE(3, "创建表");

private final int code;

private final String desc;

private static final Map<Integer, FeatureGeneratType> valMap = Arrays.stream(values()).collect(Collectors.toMap(FeatureGeneratType::getCode, Function.identity()));

FeatureGeneratType(int code, String desc) {
this.code = code;
this.desc = desc;
}

public int getCode() {
return code;
}

public String getDesc() {
return desc;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package run.mone.ai.codegen.bo;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
* @author goodjava@qq.com, HawickMason@xiaomi.com
* @date 7/12/24 14:10
*/
@NoArgsConstructor
@AllArgsConstructor
@Data
@Builder
public class FeatureGenerateBo {

@Builder.Default
private FeatureGeneratType type = FeatureGeneratType.CODE_WITH_GENERATOR;

@Builder.Default
private String tableName = "";

@Builder.Default
private String sql = "";

@Builder.Default
private String jdbcUrl = "";

@Builder.Default
private String userName = "";

@Builder.Default
private String password = "";


@Builder.Default
private String basePackage = "";

@Builder.Default
private String className = "Dummy";

@Builder.Default
private String auth = "";

@Builder.Default
private String basePath = "";

@Builder.Default
private String serverModulePath = "";

@Builder.Default
private String serviceModulePath = "";

@Builder.Default
private String apiModulePath = "";

@Builder.Default
private boolean createPojo = false;

@Builder.Default
private boolean createVo = false;

@Builder.Default
private boolean createTransfer = false;

@Builder.Default
private boolean createService = false;

@Builder.Default
private boolean createTest = true;

@Builder.Default
private boolean createController = false;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package run.mone.ai.codegen.util;

import com.google.common.collect.Lists;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.tuple.Pair;
import org.beetl.core.Configuration;
import org.beetl.core.Function;
import org.beetl.core.GroupTemplate;
import org.beetl.core.Template;
import org.beetl.core.resource.StringTemplateResourceLoader;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;

/**
* @author goodjava@qq.com, HawickMason@xiaomi.com
* @date 7/12/24 11:05 AM
*/
@Slf4j
public class TemplateUtils {

public static String renderTemplate(String template, Map<String, ? extends Object> m) {
return renderTemplate(template, m, Lists.newArrayList());
}

public static String renderTemplate(String template, Map<String, ? extends Object> m, List<Pair<String, Function>> functionList) {
try {
if (template == null || template.isEmpty()) {
return "";
}
StringTemplateResourceLoader resourceLoader = new StringTemplateResourceLoader();
Configuration cfg = Configuration.defaultConfiguration();
GroupTemplate gt = new GroupTemplate(resourceLoader, cfg);
functionList.forEach(it -> gt.registerFunction(it.getKey(), it.getValue()));
Template t = gt.getTemplate(template);
m.forEach((k, v) -> t.binding(k, v));
String str = t.render();
return str;
} catch (Throwable ex) {
log.error("renderTemplate", ex);
}
return "";
}

//读取resources下的模板文件,然后渲染成String(class)
@SneakyThrows
public static String renderTemplateFromFile(String templateFileName, Map<String, ? extends Object> m) {
try {
InputStream is = TemplateUtils.class.getClassLoader().getResourceAsStream(templateFileName);
//读取is成String
String template = new String(is.readAllBytes(), StandardCharsets.UTF_8);
return renderTemplate(template, m);
} catch (IOException ex) {
log.error("Error reading template file", ex);
}
return "";
}

//把String写到指定文件中(class)
public static void writeStringToFile(String content, String filePath) {
try (BufferedWriter writer = new BufferedWriter(new FileWriter(filePath))) {
writer.write(content);
} catch (IOException ex) {
log.error("Error writing to file", ex);
}
}
}
2 changes: 2 additions & 0 deletions jcommon/codegen/src/main/resources/tlp/code_test.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
name:${name}
name:${strutil.toLowerCase(name)}
Loading

0 comments on commit 1e0f9f3

Please sign in to comment.