Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(codegen): support feature and test and table generation #862

Merged
merged 1 commit into from
Jul 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 [email protected], [email protected]
* @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", "[email protected]");

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 [email protected], [email protected]
* @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 [email protected], [email protected]
* @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 [email protected], [email protected]
* @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 [email protected], [email protected]
* @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
Loading