youfool-devops-gd-jdk21/src/main/java/com/chinaweal/youfool/devops/DevOpsApplication.java

176 lines
8.2 KiB
Java
Raw Normal View History

2024-10-22 10:46:33 +08:00
package com.chinaweal.youfool.devops;
import com.chinaweal.youfool.devops.config.ErrorLogProperties;
import com.chinaweal.youfool.devops.util.ErrorLogUtils;
2024-10-22 10:46:33 +08:00
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
2024-10-22 10:46:33 +08:00
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.scheduling.annotation.EnableScheduling;
import java.util.Arrays;
2024-10-22 10:46:33 +08:00
@SpringBootApplication(scanBasePackages = {"com.chinaweal"})
@Slf4j
@EnableScheduling
public class DevOpsApplication extends SpringBootServletInitializer implements ApplicationListener<ContextRefreshedEvent> {
@Value("${applicationName:devOps}")
2024-10-22 10:46:33 +08:00
private String applicationName;
@Value("${version:1.0.0}")
2024-10-22 10:46:33 +08:00
private String version;
@Value("${description:运维管理系统}")
2024-10-22 10:46:33 +08:00
private String description;
@Autowired
private ErrorLogProperties errorLogProperties;
2024-10-22 10:46:33 +08:00
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder applicationBuilder) {
return applicationBuilder.sources(DevOpsApplication.class);
}
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
if (event.getApplicationContext().getParent() == null) {
try {
log.info("========================== 程序启动成功! ==========================");
log.info("====== 程 序:{} ", applicationName);
log.info("====== 版本号:{} ", version);
log.info("====== 描 述:{} ", description);
log.info("====== 接口文档路径:/doc.html账号admin、密码123456。注如果乱码请指定VM -Dfile.encoding=UTF-8");
log.info("====== Druid Monitor路径/druid账号admin、密码123456");
// 显示错误日志配置状态
if (errorLogProperties != null) {
log.info("====== 错误日志配置:启用={}, 目录={}",
errorLogProperties.isEnabled(), errorLogProperties.getLogDirectory());
log.info("====== 错误日志类型:启动={}, 运行时={}, 数据库={}, 业务={}",
errorLogProperties.isStartupEnabled(),
errorLogProperties.isRuntimeEnabled(),
errorLogProperties.isDatabaseEnabled(),
errorLogProperties.isBusinessEnabled());
}
log.info("====================================================================");
// 记录启动成功信息
ErrorLogUtils.logStartupInfo("应用启动成功 - " + applicationName + " v" + version);
} catch (Exception e) {
log.error("启动成功回调处理异常", e);
ErrorLogUtils.saveStartupError("启动成功回调异常", e);
}
2024-10-22 10:46:33 +08:00
}
}
public static void main(String[] args) {
try {
// 记录启动开始
ErrorLogUtils.logStartupInfo("开始启动应用,参数: " + Arrays.toString(args));
// 设置默认的JVM参数以解决Java模块系统兼容性问题
setJavaModuleOptions();
// 启动Spring Boot应用
SpringApplication app = new SpringApplication(DevOpsApplication.class);
// 添加启动失败监听器
app.addListeners(event -> {
if (event instanceof org.springframework.boot.context.event.ApplicationFailedEvent) {
org.springframework.boot.context.event.ApplicationFailedEvent failedEvent =
(org.springframework.boot.context.event.ApplicationFailedEvent) event;
Throwable exception = failedEvent.getException();
log.error("应用启动失败", exception);
ErrorLogUtils.saveStartupError("应用启动失败", exception);
// 输出友好的错误信息
System.err.println("\n==================== 应用启动失败 ====================");
System.err.println("错误信息已保存到: logs/errors/startup-error-*.log");
System.err.println("详细错误信息: " + ErrorLogUtils.formatErrorInfo("启动失败", exception));
System.err.println("=================================================\n");
}
});
app.run(args);
// 添加JVM关闭钩子以确保异步日志写入器正确关闭
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
log.info("应用正在关闭,清理错误日志资源...");
ErrorLogUtils.shutdown();
}));
} catch (Exception e) {
log.error("应用启动异常", e);
ErrorLogUtils.saveStartupError("主方法启动异常", e);
// 输出友好的错误信息到控制台
System.err.println("\n==================== 应用启动异常 ====================");
System.err.println("错误信息已保存到: logs/errors/startup-error-*.log");
System.err.println("详细错误信息: " + ErrorLogUtils.formatErrorInfo("启动异常", e));
System.err.println("=================================================\n");
// 重新抛出异常以确保程序正确退出
throw new RuntimeException("应用启动失败", e);
}
}
/**
* 设置Java版本兼容性参数
*/
private static void setJavaModuleOptions() {
try {
String javaVersion = System.getProperty("java.version");
ErrorLogUtils.logStartupInfo("当前Java版本: " + javaVersion);
// 只在Java 9+版本设置模块参数
if (isJava9OrHigher()) {
String javaToolOptions = System.getProperty("JAVA_TOOL_OPTIONS", "");
// 检查是否已经设置了必要的模块参数
if (!javaToolOptions.contains("--add-opens java.base/java.util=ALL-UNNAMED")) {
String newOptions = javaToolOptions +
" --add-opens java.base/java.util=ALL-UNNAMED" +
" --add-opens java.base/java.lang=ALL-UNNAMED" +
" --add-opens java.base/java.lang.reflect=ALL-UNNAMED" +
" --add-opens java.base/java.time=ALL-UNNAMED";
System.setProperty("JAVA_TOOL_OPTIONS", newOptions.trim());
ErrorLogUtils.logStartupInfo("已设置Java模块兼容性参数: " + newOptions.trim());
}
} else {
ErrorLogUtils.logStartupInfo("检测到Java 8跳过模块系统参数设置");
}
} catch (Exception e) {
log.warn("检查Java版本失败", e);
ErrorLogUtils.saveStartupError("Java版本检查失败", e);
}
}
/**
* 检查是否为Java 9或更高版本
*/
private static boolean isJava9OrHigher() {
try {
String version = System.getProperty("java.version");
// Java 8: 1.8.x, Java 9+: 9.x, 10.x, 11.x, etc.
if (version.startsWith("1.8")) {
return false;
}
// 尝试解析主版本号
String[] parts = version.split("\\.");
if (parts.length > 0) {
int majorVersion = Integer.parseInt(parts[0]);
return majorVersion >= 9;
}
} catch (Exception e) {
log.warn("解析Java版本失败: " + System.getProperty("java.version"), e);
}
return false; // 默认认为是Java 8
2024-10-22 10:46:33 +08:00
}
}