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

321 lines
15 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.chinaweal.youfool.devops;
// Temporarily commented out for Spring AI compatibility
// import com.chinaweal.youfool.devops.ai.config.AIRepairIntegrationConfig;
import com.chinaweal.youfool.devops.config.ErrorLogProperties;
import com.chinaweal.youfool.devops.util.ErrorLogUtils;
import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import javax.sql.DataSource;
import java.sql.Connection;
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<ContextRefreshedEvent> {
@Value("${applicationName:devOps}")
private String applicationName;
@Value("${version:1.0.0}")
private String version;
@Value("${description:运维管理系统}")
private String description;
@Autowired
private ErrorLogProperties errorLogProperties;
// Temporarily commented out for Spring AI compatibility
// @Autowired
// private AIRepairIntegrationConfig aiRepairIntegrationConfig;
@Autowired
@Qualifier("devopsDS")
private DataSource devopsDataSource;
@Autowired
@Qualifier("youfoolDS")
private DataSource youfoolDataSource;
@Autowired(required = false)
private CircuitBreakerRegistry circuitBreakerRegistry;
@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("====== Java环境{}", getJavaVersionInfo());
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());
}
// TODO: AI修缮集成配置状态 - Temporarily disabled due to Spring AI compatibility issues
/*
if (aiRepairIntegrationConfig != null) {
log.info("====== AI修缮集成配置启用={}, 自动生成={}, 异步处理={}",
aiRepairIntegrationConfig.isEnabled(),
aiRepairIntegrationConfig.isAutoGenerate(),
aiRepairIntegrationConfig.isAsyncProcessing());
log.info("====== AI质量阈值={}, 最大处理时间={}ms, 线程池大小={}",
aiRepairIntegrationConfig.getQualityThreshold(),
aiRepairIntegrationConfig.getMaxProcessingTime(),
aiRepairIntegrationConfig.getAsyncThreadPoolSize());
log.info("====== AI支持修缮类型{}",
String.join(", ", aiRepairIntegrationConfig.getFilters().getRepairTypes()));
// 记录AI集成配置到启动日志
ErrorLogUtils.logStartupInfo("AI修缮集成配置 - 启用:" + aiRepairIntegrationConfig.isEnabled() +
", 自动生成:" + aiRepairIntegrationConfig.isAutoGenerate() +
", 异步处理:" + aiRepairIntegrationConfig.isAsyncProcessing());
}
*/
// 重置熔断器以确保服务可用
if (circuitBreakerRegistry != null) {
try {
circuitBreakerRegistry.circuitBreaker("qwen-embedding").reset();
log.info("====== AI服务熔断器已重置embedding服务就绪");
} catch (Exception e) {
log.warn("====== 熔断器重置失败: {}", e.getMessage());
}
} else {
log.info("====== AI功能已启用 - embedding服务和向量化功能可用");
}
// 打印数据库连接信息
printDatabaseConnectionInfo();
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, 21.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 true; // JDK 21环境下默认为true
}
/**
* 获取当前Java版本信息
*/
private static String getJavaVersionInfo() {
try {
String version = System.getProperty("java.version");
String vendor = System.getProperty("java.vendor");
String vmName = System.getProperty("java.vm.name");
return String.format("Java %s (%s - %s)", version, vendor, vmName);
} catch (Exception e) {
return "Java version unknown";
}
}
/**
* 打印数据库连接信息
*/
private void printDatabaseConnectionInfo() {
try {
log.info("========== 数据库连接信息 ==========");
// 打印devops数据源信息
try (Connection conn = devopsDataSource.getConnection()) {
String url = conn.getMetaData().getURL();
String username = conn.getMetaData().getUserName();
String databaseName = conn.getCatalog();
log.info("🔗 Devops数据源:");
log.info(" URL: {}", url);
log.info(" 用户: {}", username);
log.info(" 数据库: {}", databaseName);
ErrorLogUtils.logStartupInfo("Devops数据源连接: " + url + ", 用户: " + username + ", 数据库: " + databaseName);
} catch (Exception e) {
log.error("❌ 获取devops数据源信息失败", e);
ErrorLogUtils.saveStartupError("获取devops数据源信息失败", e);
}
// 打印youfool数据源信息
try (Connection conn = youfoolDataSource.getConnection()) {
String url = conn.getMetaData().getURL();
String username = conn.getMetaData().getUserName();
String databaseName = conn.getCatalog();
log.info("🔗 Youfool数据源:");
log.info(" URL: {}", url);
log.info(" 用户: {}", username);
log.info(" 数据库: {}", databaseName);
ErrorLogUtils.logStartupInfo("Youfool数据源连接: " + url + ", 用户: " + username + ", 数据库: " + databaseName);
} catch (Exception e) {
log.error("❌ 获取youfool数据源信息失败", e);
ErrorLogUtils.saveStartupError("获取youfool数据源信息失败", e);
}
// 测试ENGINEER表访问
try (Connection conn = devopsDataSource.getConnection()) {
// 简单测试查询
String testSql = "SELECT COUNT(*) as total FROM engineer";
try (java.sql.PreparedStatement ps = conn.prepareStatement(testSql);
java.sql.ResultSet rs = ps.executeQuery()) {
if (rs.next()) {
int total = rs.getInt("total");
log.info("✅ ENGINEER表测试: 共{}条记录", total);
ErrorLogUtils.logStartupInfo("ENGINEER表访问测试成功共" + total + "条记录");
}
} catch (Exception e) {
log.error("❌ ENGINEER表访问测试失败", e);
ErrorLogUtils.saveStartupError("ENGINEER表访问测试失败", e);
}
} catch (Exception e) {
log.error("❌ 数据库连接测试失败", e);
ErrorLogUtils.saveStartupError("数据库连接测试失败", e);
}
log.info("=====================================");
} catch (Exception e) {
log.error("❌ 打印数据库连接信息时发生异常", e);
ErrorLogUtils.saveStartupError("打印数据库连接信息异常", e);
}
}
}