package com.ruoyi; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.ListUtil; import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.resource.ResourceUtil; import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.ClassUtil; import cn.hutool.core.util.StrUtil; import com.fasterxml.jackson.databind.ObjectMapper; import com.ruoyi.common.annotation.Info; import lombok.Data; import org.apache.velocity.VelocityContext; import org.apache.velocity.app.VelocityEngine; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.data.annotation.Id; import java.io.File; import java.io.StringWriter; import java.lang.reflect.Field; import java.util.Arrays; import java.util.List; import java.util.Set; import java.util.stream.Collectors; @Info public class MongoGenerator { /** * 输出的类的根包,扫描的实体类为该包下的mongo子包下 */ private String packageName = "com.ruoyi.jobs"; /** * 模块名,类的简单名称会先去掉前面的模块名 */ private String moduleName = "jobs"; @Test @Disabled @DisplayName("mongodb代码生成") public void generate() throws Exception { List entityList = scan(); //所有编写了@Info的实体类 // List entityList = scan("JobsTag1");//编写了@Info的实体类中的某些类 System.out.println(new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(entityList)); generate(entityList); System.out.println("完成"); } public void generate(List entityList) throws Exception { File[] fs = getOutPath(); /** * 工程根 */ File root = fs[0]; /** * java包根目录 */ File javaRoot = fs[1]; for (BaseInfo entity : entityList) { String code = generate("query.vm", entity, entityList); new File(javaRoot, "mongo/query").mkdirs(); FileUtil.writeString(code, new File(javaRoot, "mongo/query/" + entity.toUpperName() + "Query.java"), "UTF-8"); code = generate("api.vm", entity, entityList); new File(javaRoot, "api").mkdirs(); FileUtil.writeString(code, new File(javaRoot, "api/" + entity.toUpperName() + "Api.java"), "UTF-8"); code = generate("api.js.vm", entity, entityList); new File(root, "admin-ui/src/views/" + moduleName + "/api").mkdirs(); FileUtil.writeString(code, new File(root, "admin-ui/src/views/" + moduleName + "/api/" + entity.toSimpleLowerName() + ".js"), "UTF-8"); code = generate("index.vue.vm", entity, entityList); new File(root, "admin-ui/src/views/" + moduleName + "/" + entity.toSimpleLowerName()).mkdirs(); FileUtil.writeString(code, new File(root, "admin-ui/src/views/" + moduleName + "/" + entity.toSimpleLowerName() + "/index.vue"), "UTF-8"); code = generate("WAdd.vue.vm", entity, entityList); new File(root, "admin-ui/src/views/" + moduleName + "/" + entity.toSimpleLowerName() + "/components").mkdirs(); FileUtil.writeString(code, new File(root, "admin-ui/src/views/" + moduleName + "/" + entity.toSimpleLowerName() + "/components/WAdd.vue"), "UTF-8"); code = generate("WEdit.vue.vm", entity, entityList); FileUtil.writeString(code, new File(root, "admin-ui/src/views/" + moduleName + "/" + entity.toSimpleLowerName() + "/components/WEdit.vue"), "UTF-8"); } String code = generate("sql.vm", null, entityList); FileUtil.writeString(code, new File(root, moduleName + "-menu.sql"), "UTF-8"); } /** * 使用模板引擎生成代码 * * @param template * @param entity * @param list * @return * @throws Exception */ public String generate(String template, BaseInfo entity, List list) throws Exception { VelocityEngine ve = new VelocityEngine(); ve.init(); VelocityContext context = new VelocityContext(); context.put("package", packageName); context.put("entity", entity); context.put("list", list); context.put("moduleName", moduleName); StringWriter writer = new StringWriter(); template = ResourceUtil.readUtf8Str("classpath:/generator/" + template); ve.evaluate(context, writer, this.getClass().getName(), template); return writer.toString(); } /** * 获取输出的java包源目录 * * @return */ public File[] getOutPath() { Set paths = ClassUtil.getClassPaths(packageName); if (CollUtil.isEmpty(paths) || paths.size() != 1) { throw new RuntimeException("不能确定java包源目录"); } String path = paths.iterator().next(); File file = new File(path.replace("/target/classes/", "/src/main/java/")); File root = new File(path.substring(0, path.indexOf("/target/classes/"))).getParentFile(); return new File[]{root, file}; } /** * 扫描获取包下需要生成的实体信息 * * @param includes 包含的类名,不填表示扫描所有 * @return */ public List scan(String... includes) { Info defaultInfo = MongoGenerator.class.getAnnotation(Info.class); List entityList = ListUtil.list(true); ClassUtil.scanPackageByAnnotation(packageName + ".mongo", Info.class).stream().filter(c -> { if (ArrayUtil.isEmpty(includes)) { return true; } else { return ArrayUtil.indexOf(includes, c.getSimpleName()) > -1; } }).forEach(entityClazz -> { BaseInfo entityInfo = loadByInfo(entityClazz.getAnnotation(Info.class)); entityList.add(entityInfo); entityInfo.setClazz(entityClazz); entityInfo.setJavaName(entityClazz.getSimpleName()); entityInfo.setModuleName(moduleName); entityInfo.all = Arrays.stream(entityClazz.getDeclaredFields()).map(field -> { BaseInfo info = null; if (field.isAnnotationPresent(Info.class)) { info = loadByInfo(field.getAnnotation(Info.class)); } else { info = loadByInfo(defaultInfo); } info.setClazz(field.getType()); info.setJavaName(field.getName()); info.setIsId(field.isAnnotationPresent(Id.class)); info.setModuleName(moduleName); return info; }).sorted((a, b) -> a.order - b.order).collect(Collectors.toList()); entityInfo.cols = entityInfo.all.stream().filter(a -> !a.isId).collect(Collectors.toList()); entityInfo.id = entityInfo.all.stream().filter(a -> a.isId).findFirst().get(); }); return entityList; } public BaseInfo loadByInfo(Info info) { BaseInfo base = new BaseInfo(); base.setAdd(info.add()); base.setUpdate(info.update()); base.setShow(info.show()); base.setOrder(info.order()); base.setName(info.value()); if (!info.addDefault().equals("")) { base.setAddDefault(info.addDefault()); } if (!info.updateDefault().equals("")) { base.setUpdateDefault(info.updateDefault()); } if (!info.comment().equals("")) { base.setComment(info.comment()); } return base; } @Data public static class BaseInfo { public Class clazz; public Field field; /** * 所有字段 */ public List all; /** * 不含主键 */ public List cols; /** * 主键字段 */ public BaseInfo id; public Boolean isId = false; public String name; public String getName() { if (StrUtil.isBlank(name)) { return javaName; } else { return name; } } public String javaName; public String moduleName; public String toUpperName() { return javaName.substring(0, 1).toUpperCase() + javaName.substring(1); } /** * 去掉模块名后的 * * @return */ public String toSimpleUpperName() { String n = toLowerName(); if (n.startsWith(moduleName)) { return n.substring(moduleName.length()); } else { return toUpperName(); } } public String toSimpleLowerName() { String n = toLowerName(); if (n.startsWith(moduleName)) { n = n.substring(moduleName.length()); return n.substring(0, 1).toLowerCase() + n.substring(1); } else { return toLowerName(); } } public String toLowerName() { return javaName.substring(0, 1).toLowerCase() + javaName.substring(1); } public String comment; /** * @param tabNum * @return */ public String toComment(int tabNum) { if (tabNum < 0) { tabNum = 0; } String tabs = tabNum > 0 ? String.format("%" + (tabNum * 2) + "s", "") + " * " : " * "; if (StrUtil.isNotBlank(comment)) { return tabs + comment.replace("\n", "\n" + tabs); } else { return tabs; } } public boolean show; public boolean add; public String addDefault; public boolean update; public String updateDefault; public int order; } }