自动重启加载生成的代码类
This commit is contained in:
@@ -1,11 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module version="4">
|
||||
<component name="AdditionalModuleElements">
|
||||
<content url="file://$MODULE_DIR$" dumb="true">
|
||||
<sourceFolder url="file://$MODULE_DIR$/target/generated-sources/annotations/src/main/java" isTestSource="false" />
|
||||
</content>
|
||||
<content url="file://$MODULE_DIR$" dumb="true">
|
||||
<sourceFolder url="file://$MODULE_DIR$/target/generated-sources/annotations" isTestSource="false" />
|
||||
</content>
|
||||
</content>
|
||||
</component>
|
||||
</module>
|
||||
@@ -1,17 +1,22 @@
|
||||
package com.cool;
|
||||
|
||||
import com.cool.core.util.PathUtils;
|
||||
import com.tangzc.autotable.springboot.EnableAutoTable;
|
||||
import java.util.List;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.ApplicationArguments;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cache.annotation.EnableCaching;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
|
||||
import com.tangzc.autotable.springboot.EnableAutoTable;
|
||||
|
||||
/**
|
||||
* CoolApplication - 应用程序的主类
|
||||
* 该类配置并运行应用程序。
|
||||
*/
|
||||
@Slf4j
|
||||
@EnableAutoTable // 开启自动建表
|
||||
@EnableAsync // 开启异步处理
|
||||
@EnableCaching // 开启缓存
|
||||
@@ -19,7 +24,51 @@ import com.tangzc.autotable.springboot.EnableAutoTable;
|
||||
@MapperScan("com.cool.modules.*.mapper") // 扫描指定包中的MyBatis映射器
|
||||
public class CoolApplication {
|
||||
|
||||
private static volatile ConfigurableApplicationContext context;
|
||||
private static ClassLoader mainThreadClassLoader;
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(CoolApplication.class, args);
|
||||
mainThreadClassLoader = Thread.currentThread().getContextClassLoader();
|
||||
context = SpringApplication.run(CoolApplication.class, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过关闭当前上下文并启动新上下文来重启应用程序。
|
||||
*/
|
||||
public static void restart(List<String> javaPathList) {
|
||||
// 从当前上下文获取应用程序参数
|
||||
ApplicationArguments args = context.getBean(ApplicationArguments.class);
|
||||
|
||||
// 创建新线程来重启应用程序
|
||||
Thread thread = new Thread(() -> {
|
||||
try {
|
||||
// 关闭当前应用程序上下文
|
||||
context.close();
|
||||
// 等待上下文完全关闭
|
||||
while (context.isActive()) {
|
||||
Thread.sleep(100);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
// 加载动态生成的代码
|
||||
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
||||
javaPathList.forEach(javaPath -> {
|
||||
try {
|
||||
classLoader.loadClass(PathUtils.getClassName(javaPath));
|
||||
} catch (ClassNotFoundException e) {
|
||||
log.error("loadClassErr {}", javaPath, e);
|
||||
}
|
||||
});
|
||||
// 使用相同的参数运行Spring Boot应用程序并设置上下文
|
||||
context = SpringApplication.run(CoolApplication.class, args.getSourceArgs());
|
||||
});
|
||||
// 设置线程的上下文类加载器
|
||||
thread.setContextClassLoader(mainThreadClassLoader);
|
||||
// 确保线程不是守护线程
|
||||
thread.setDaemon(false);
|
||||
// 启动线程
|
||||
thread.start();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -11,13 +11,11 @@ import com.cool.core.exception.CoolPreconditions;
|
||||
import com.cool.core.file.UpLoadModeType;
|
||||
import com.cool.modules.plugin.entity.PluginInfoEntity;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
@@ -47,16 +45,16 @@ public class LocalFileUploadStrategy implements FileUploadStrategy {
|
||||
String date = DateUtil.format(new Date(),
|
||||
DatePattern.PURE_DATE_PATTERN);
|
||||
String relativePath =
|
||||
"/" + localFileProperties.getUploadPath() + "/" + date;
|
||||
File.separator + localFileProperties.getUploadPath() + File.separator + date;
|
||||
|
||||
FileUtil.mkdir(filePath + relativePath);
|
||||
for (MultipartFile file : files) {
|
||||
// 保存文件
|
||||
String fileName = StrUtil.uuid().replaceAll("-", "") + getExtensionName(
|
||||
Objects.requireNonNull(file.getOriginalFilename()));
|
||||
file.transferTo(new File(filePath + "/" + relativePath
|
||||
+ "/" + fileName));
|
||||
fileUrls.add(baseUrl + "/" + date + "/" + fileName);
|
||||
file.transferTo(new File(filePath + File.separator + relativePath
|
||||
+ File.separator + fileName));
|
||||
fileUrls.add(baseUrl + File.separator + date + File.separator + fileName);
|
||||
}
|
||||
if (fileUrls.size() == 1) {
|
||||
return fileUrls.get(0);
|
||||
|
||||
@@ -94,7 +94,7 @@ public class CoolPluginService {
|
||||
String pathStr = pluginPath;
|
||||
if (!PathUtils.isAbsolutePath(pluginPath)) {
|
||||
// 相对路径
|
||||
pathStr = System.getProperty("user.dir") + "/" + pluginPath;
|
||||
pathStr = System.getProperty("user.dir") + File.separator + pluginPath;
|
||||
}
|
||||
// 将路径字符串转换为 Path 对象
|
||||
Path path = Paths.get(pathStr);
|
||||
@@ -104,7 +104,7 @@ public class CoolPluginService {
|
||||
Files.createDirectories(path);
|
||||
}
|
||||
fileName =
|
||||
path + "/" + System.currentTimeMillis() + "_" + file.getOriginalFilename() + ".jar";
|
||||
path + File.separator + System.currentTimeMillis() + "_" + file.getOriginalFilename() + ".jar";
|
||||
jarFile = new File(fileName);
|
||||
file.transferTo(jarFile);
|
||||
// 加载jar
|
||||
|
||||
@@ -3,13 +3,14 @@ package com.cool.core.util;
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import com.mybatisflex.processor.MybatisFlexProcessor;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import javax.annotation.processing.Processor;
|
||||
import javax.tools.JavaCompiler;
|
||||
import javax.tools.JavaFileObject;
|
||||
import javax.tools.StandardJavaFileManager;
|
||||
import javax.tools.StandardLocation;
|
||||
import javax.tools.ToolProvider;
|
||||
|
||||
public class CompilerUtils {
|
||||
@@ -21,66 +22,131 @@ public class CompilerUtils {
|
||||
FileUtil.del(filePathStr);
|
||||
File file = FileUtil.touch(filePathStr);
|
||||
FileUtil.appendString(content, file, StandardCharsets.UTF_8.name());
|
||||
compileAndSave(filePathStr);
|
||||
}
|
||||
|
||||
public static void createMapper(String actModulePath, String fileName, String mapper) {
|
||||
String pathStr = actModulePath + "/mapper/";
|
||||
public static String createMapper(String actModulePath, String fileName, String mapper) {
|
||||
String pathStr = actModulePath + File.separator + "mapper" + File.separator;
|
||||
String filePathStr = pathStr + fileName + "Mapper.java";
|
||||
createFile(mapper, filePathStr);
|
||||
return filePathStr;
|
||||
}
|
||||
|
||||
public static void createServiceImpl(String actModulePath, String fileName,
|
||||
public static String createServiceImpl(String actModulePath, String fileName,
|
||||
String serviceImpl) {
|
||||
String pathStr = actModulePath + "/service/impl/";
|
||||
String pathStr = actModulePath + File.separator + "service" + File.separator + "impl" + File.separator;
|
||||
String filePathStr = pathStr + fileName + "ServiceImpl.java";
|
||||
createFile(serviceImpl, filePathStr);
|
||||
return filePathStr;
|
||||
}
|
||||
|
||||
public static void createService(String actModulePath, String fileName, String service) {
|
||||
String pathStr = actModulePath + "/service/";
|
||||
public static String createService(String actModulePath, String fileName, String service) {
|
||||
String pathStr = actModulePath + File.separator + "service" + File.separator;
|
||||
String filePathStr = pathStr + fileName + "Service.java";
|
||||
createFile(service, filePathStr);
|
||||
return filePathStr;
|
||||
}
|
||||
|
||||
public static String createEntity(String actModulePath, String fileName, String entity) {
|
||||
String pathStr = actModulePath + "/entity/";
|
||||
String pathStr = actModulePath + File.separator + "entity" + File.separator;
|
||||
String filePathStr = pathStr + fileName + "Entity.java";
|
||||
createFile(entity, filePathStr);
|
||||
return filePathStr;
|
||||
}
|
||||
|
||||
public static void createController(String actModulePath, String fileName, String controller) {
|
||||
String pathStr = actModulePath + "/controller/admin/";
|
||||
public static String createController(String actModulePath, String fileName, String controller) {
|
||||
String pathStr = actModulePath + File.separator + "controller" + File.separator + "admin" + File.separator;
|
||||
String filePathStr = pathStr + "Admin" + fileName + "Controller.java";
|
||||
createFile(controller, filePathStr);
|
||||
return filePathStr;
|
||||
}
|
||||
|
||||
public static String createModule(String modulesPath, String module) {
|
||||
String pathStr = modulesPath + "/" + module;
|
||||
String pathStr = modulesPath + File.separator + module;
|
||||
PathUtils.noExistsMk(pathStr);
|
||||
return pathStr;
|
||||
}
|
||||
|
||||
public static void compilerEntityTableDef(String path) {
|
||||
// JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
|
||||
// StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
|
||||
//
|
||||
// Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjects(
|
||||
// path);
|
||||
//
|
||||
// // 设置注解处理器
|
||||
// Iterable<? extends Processor> processors = Arrays.asList(new MybatisFlexProcessor());
|
||||
// // 添加 -proc:only 选项
|
||||
// List<String> options = Arrays.asList("-proc:only");
|
||||
// JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, null, options,
|
||||
// null, compilationUnits);
|
||||
// task.setProcessors(processors);
|
||||
//
|
||||
// boolean success = task.call();
|
||||
// if (success) {
|
||||
// System.out.println("Compilation and annotation processing completed successfully.");
|
||||
// } else {
|
||||
// System.out.println("Compilation and annotation processing failed.");
|
||||
// }
|
||||
public static boolean compileAndSave(String sourceFile) {
|
||||
// 获取系统 Java 编译器
|
||||
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
|
||||
|
||||
// 获取标准文件管理器
|
||||
try (StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null)) {
|
||||
|
||||
// 设置编译输出目录
|
||||
fileManager.setLocation(StandardLocation.CLASS_OUTPUT, List.of(new File("target" + File.separator + "classes")));
|
||||
|
||||
// 获取源文件
|
||||
List<File> javaFiles = List.of(new File(sourceFile));
|
||||
Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(javaFiles);
|
||||
|
||||
// 创建编译任务
|
||||
JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, null, null, null, compilationUnits);
|
||||
// 执行编译任务
|
||||
return task.call();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static void compilerEntityTableDef(String actModulePath, String fileName, String entityPath, List<String> javaPathList) {
|
||||
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
|
||||
try (StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null)) {
|
||||
Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjects(
|
||||
entityPath);
|
||||
// // 设置注解处理器
|
||||
Iterable<? extends Processor> processors = List.of(new MybatisFlexProcessor());
|
||||
// // 添加 -proc:only 选项
|
||||
List<String> options = List.of("-proc:only");
|
||||
JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, null, options,
|
||||
null, compilationUnits);
|
||||
task.setProcessors(processors);
|
||||
task.call();
|
||||
compilationUnits = fileManager.getJavaFileObjects(
|
||||
javaPathList.toArray(new String[0]));
|
||||
// 需在entity之后加载
|
||||
// 设置编译输出目录
|
||||
fileManager.setLocation(StandardLocation.CLASS_OUTPUT, List.of(new File("target/classes")));
|
||||
|
||||
task = compiler.getTask(null, fileManager, null, null, null, compilationUnits);
|
||||
String pathStr = actModulePath + File.separator + "entity" + File.separator + "table" + File.separator;
|
||||
String filePathStr = pathStr + fileName + "EntityTableDef.java";
|
||||
javaPathList.add(1, filePathStr);
|
||||
boolean success = task.call();
|
||||
if (success) {
|
||||
System.out.println("Compilation and annotation processing completed successfully.");
|
||||
String commPath = PathUtils.getUserDir() + File.separator + "com";
|
||||
if (countFiles(new File(commPath)) <= 1) {
|
||||
FileUtil.clean(commPath);
|
||||
FileUtil.del(commPath);
|
||||
}
|
||||
} else {
|
||||
System.out.println("Compilation and annotation processing failed.");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
private static int countFiles(File directory) {
|
||||
File[] files = directory.listFiles();
|
||||
if (files == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
for (File file : files) {
|
||||
if (file.isFile()) {
|
||||
count++;
|
||||
} else if (file.isDirectory()) {
|
||||
count += countFiles(file);
|
||||
}
|
||||
// If more than one file is found, no need to continue counting
|
||||
if (count > 1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.cool.core.util;
|
||||
|
||||
import cn.hutool.core.io.file.PathUtil;
|
||||
import com.cool.CoolApplication;
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
@@ -17,8 +18,21 @@ public class PathUtils {
|
||||
}
|
||||
|
||||
public static String getModulesPath() {
|
||||
return getUserDir() + "/src/main/java/" + CoolApplication.class.getPackageName()
|
||||
.replace(".", "/") + "/modules";
|
||||
return getUserDir() + File.separator + "src"+ File.separator + "main" + File.separator + "java" + File.separator + CoolApplication.class.getPackageName()
|
||||
.replace(".", File.separator) + File.separator + "modules";
|
||||
}
|
||||
|
||||
public static String getClassName(String filePath) {
|
||||
// 定位 "src/main/java" 在路径中的位置
|
||||
int srcMainJavaIndex = filePath.indexOf("src" + File.separator + "main" + File.separator + "java");
|
||||
if (srcMainJavaIndex == -1) {
|
||||
throw new IllegalArgumentException("File path does not contain 'src/main/java'");
|
||||
}
|
||||
|
||||
// 提取 "src/main/java" 之后的路径
|
||||
// 将文件分隔符替换为包分隔符
|
||||
return filePath.substring(srcMainJavaIndex + ("src" + File.separator + "main" + File.separator + "java").length() + 1)
|
||||
.replace(File.separator, ".").replace(".java", "");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.cool.CoolApplication;
|
||||
import com.cool.core.base.BaseServiceImpl;
|
||||
import com.cool.core.base.ModifyEnum;
|
||||
import com.cool.core.util.CompilerUtils;
|
||||
@@ -147,24 +148,25 @@ public class BaseSysMenuServiceImpl extends BaseServiceImpl<BaseSysMenuMapper, B
|
||||
String mapper = (String) params.get("mapper");
|
||||
|
||||
String fileName = (String) params.get("fileName");
|
||||
List<String> javaPathList = new ArrayList<>();
|
||||
String modulesPath = PathUtils.getModulesPath();
|
||||
// 创建的模块地址
|
||||
String actModulePath = CompilerUtils.createModule(modulesPath, module);
|
||||
// 创建 controller
|
||||
CompilerUtils.createController(actModulePath, fileName, controller);
|
||||
// 创建顺序不能调整,类加载的时候需按这个顺序加载,否则类找不到
|
||||
// 创建 entity
|
||||
String entityPath = CompilerUtils.createEntity(actModulePath, fileName, entity);
|
||||
// 创建 service
|
||||
CompilerUtils.createService(actModulePath, fileName, service);
|
||||
// 创建 serviceImpl
|
||||
CompilerUtils.createServiceImpl(actModulePath, fileName, serviceImpl);
|
||||
javaPathList.add(entityPath);
|
||||
// 创建 mapper
|
||||
CompilerUtils.createMapper(actModulePath, fileName, mapper);
|
||||
// 关闭springboot
|
||||
System.exit(0);
|
||||
javaPathList.add(CompilerUtils.createMapper(actModulePath, fileName, mapper));
|
||||
// 创建 service
|
||||
javaPathList.add(CompilerUtils.createService(actModulePath, fileName, service));
|
||||
// 创建 serviceImpl
|
||||
javaPathList.add(CompilerUtils.createServiceImpl(actModulePath, fileName, serviceImpl));
|
||||
// 创建 controller
|
||||
javaPathList.add(CompilerUtils.createController(actModulePath, fileName, controller));
|
||||
// 构建TableDef
|
||||
// CompilerUtils.compilerEntityTableDef(entityPath);
|
||||
CompilerUtils.compilerEntityTableDef(actModulePath, fileName, entityPath, javaPathList);
|
||||
// 重启
|
||||
// CoolApplication.restart();
|
||||
CoolApplication.restart(javaPathList);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user