package com.chinaweal.youfool.devops; import com.chinaweal.youfool.devops.config.ErrorLogProperties; import com.chinaweal.youfool.devops.util.ErrorLogUtils; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; 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; @SpringBootApplication(scanBasePackages = {"com.chinaweal"}) @Slf4j @EnableScheduling public class DevOpsApplication extends SpringBootServletInitializer implements ApplicationListener { @Value("${applicationName:devOps}") private String applicationName; @Value("${version:1.0.0}") private String version; @Value("${description:运维管理系统}") private String description; @Autowired private ErrorLogProperties errorLogProperties; @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); } } } 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 } }