private static void printDatabaseInfo(ConfigurableApplicationContext context) { // 从Spring容器中获取数据源 DataSource dataSource = context.getBean(DataSource.class); if (dataSource instanceof DruidDataSource) { DruidDataSource druidDataSource = (DruidDataSource) dataSource; // 创建美观的控制台输出 System.out.println("🚀 应用启动成功 | 数据库连接信息"); System.out.println("🔧 驱动类: " + druidDataSource.getDriverClassName()); System.out.println("🌐 连接URL: " + druidDataSource.getUrl()); System.out.println("👤 用户名: " + druidDataSource.getUsername()); System.out.println("🔑 密码: " + druidDataSource.getPassword()); System.out.println("📊 连接池类型: " + druidDataSource.getClass().getSimpleName()); System.out.println("🔄 初始连接数: " + druidDataSource.getInitialSize()); System.out.println("⚡ 最大连接数: " + druidDataSource.getMaxActive()); System.out.println("⏱️ 连接超时(ms): " + druidDataSource.getMaxWait()); } else { System.out.println("⚠️ 当前数据源不是Druid类型: " + dataSource.getClass().getName()); } 报这个错 ⚠️ 当前数据源不是Druid类型: com.baomidou.dynamic.datasource.DynamicRoutingDataSource 帮我改一下
时间: 2025-08-13 11:04:54 浏览: 6
<think>根据错误信息,数据源类型为`com.baomidou.dynamic.datasource.DynamicRoutingDataSource`,说明项目使用了dynamic-datasource-spring-boot-starter(多数据源组件)。该组件使用动态数据源,它内部管理了多个数据源,而本身并不是Druid数据源。
解决方案:
1. 获取动态数据源对象(DynamicRoutingDataSource)
2. 从动态数据源中获取当前使用的数据源(默认数据源)或者遍历所有数据源
3. 由于每个具体的数据源可能是DruidDataSource,所以可以针对每个数据源打印信息
注意:在动态数据源中,有一个默认的数据源,也可以通过名称获取指定的数据源。
修改后的代码步骤:
- 检查数据源是否为DynamicRoutingDataSource类型
- 如果是,则获取该动态数据源,并从中获取所有数据源或特定的数据源(比如默认数据源)
- 然后对每个数据源(如果是DruidDataSource)打印信息
由于我们不知道具体有几个数据源,这里我们遍历所有数据源并打印每个数据源的信息。
代码修改如下:</think>### 解决动态数据源(DynamicRoutingDataSource)问题
当使用 `com.baomidou.dynamic.datasource` 时,你需要特殊处理动态数据源。以下是完整的解决方案:
```java
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import com.alibaba.druid.pool.DruidDataSource;
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.dynamic.datasource.ds.ItemDataSource;
import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.Map;
@SpringBootApplication
public class JeecgDomianuniqCloudApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(JeecgDomianuniqCloudApplication.class, args);
try {
printDatabaseInfo(context);
} catch (Exception e) {
System.err.println("❌ 打印数据库信息失败: " + e.getMessage());
e.printStackTrace();
}
}
private static void printDatabaseInfo(ConfigurableApplicationContext context) throws SQLException {
DataSource dataSource = context.getBean(DataSource.class);
// 处理动态数据源
if (dataSource instanceof DynamicRoutingDataSource) {
DynamicRoutingDataSource dynamicDataSource = (DynamicRoutingDataSource) dataSource;
Map<String, DataSource> dataSources = dynamicDataSource.getDataSources();
System.out.println("🚀 应用启动成功 | 动态数据源信息");
System.out.println("🔧 当前默认数据源: " + dynamicDataSource.determineCurrentLookupKey());
System.out.println("📦 已配置数据源数量: " + dataSources.size());
System.out.println("==================================================");
// 遍历并打印所有数据源信息
dataSources.forEach((name, ds) -> {
System.out.println("🔹 数据源名称: " + name);
printDataSourceDetails(ds);
System.out.println("--------------------------------------------------");
});
}
// 处理 Druid 数据源
else if (dataSource instanceof DruidDataSource) {
System.out.println("🚀 应用启动成功 | 数据库连接信息");
printDataSourceDetails(dataSource);
}
// 其他类型数据源
else {
System.out.println("⚠️ 未知数据源类型: " + dataSource.getClass().getName());
printDataSourceDetails(dataSource);
}
}
// 通用数据源信息打印方法
private static void printDataSourceDetails(DataSource ds) {
try {
if (ds instanceof DruidDataSource) {
DruidDataSource druid = (DruidDataSource) ds;
System.out.println(" 🔧 驱动类: " + druid.getDriverClassName());
System.out.println(" 🌐 连接URL: " + druid.getUrl());
System.out.println(" 👤 用户名: " + druid.getUsername());
System.out.println(" 🔑 密码: " + maskPassword(druid.getPassword()));
System.out.println(" 📊 连接池类型: DruidDataSource");
System.out.println(" 🔄 初始连接数: " + druid.getInitialSize());
System.out.println(" ⚡ 最大连接数: " + druid.getMaxActive());
System.out.println(" ⏱️ 连接超时(ms): " + druid.getMaxWait());
}
else if (ds instanceof ItemDataSource) {
ItemDataSource itemDs = (ItemDataSource) ds;
System.out.println(" 📊 连接池类型: DynamicDataSource");
System.out.println(" 🔧 真实数据源类型: " + itemDs.getRealDataSource().getClass().getName());
// 尝试获取底层连接信息
try (Connection conn = ds.getConnection()) {
DatabaseMetaData meta = conn.getMetaData();
System.out.println(" 🌐 连接URL: " + meta.getURL());
System.out.println(" 👤 用户名: " + meta.getUserName());
}
}
else {
// 通用JDBC信息获取
try (Connection conn = ds.getConnection()) {
DatabaseMetaData meta = conn.getMetaData();
System.out.println(" 🔧 驱动类: " + meta.getDriverName());
System.out.println(" 🌐 连接URL: " + meta.getURL());
System.out.println(" 👤 用户名: " + meta.getUserName());
System.out.println(" 📊 数据库产品: " + meta.getDatabaseProductName());
}
}
} catch (SQLException e) {
System.err.println(" ❌ 获取数据源信息失败: " + e.getMessage());
}
}
// 密码脱敏处理
private static String maskPassword(String password) {
if (password == null || password.isEmpty()) return "******";
if (password.length() < 3) return password.charAt(0) + "****";
return password.substring(0, 1) + "******" + password.substring(password.length() - 1);
}
}
```
### 解决方案详解
#### 1. 动态数据源处理
```java
if (dataSource instanceof DynamicRoutingDataSource) {
DynamicRoutingDataSource dynamicDataSource = (DynamicRoutingDataSource) dataSource;
Map<String, DataSource> dataSources = dynamicDataSource.getDataSources();
// 打印动态数据源元信息
System.out.println("🔧 当前默认数据源: " + dynamicDataSource.determineCurrentLookupKey());
System.out.println("📦 已配置数据源数量: " + dataSources.size());
// 遍历所有数据源
dataSources.forEach((name, ds) -> {
System.out.println("🔹 数据源名称: " + name);
printDataSourceDetails(ds);
});
}
```
- **DynamicRoutingDataSource**:动态数据源路由类,管理多个数据源
- **getDataSources()**:获取所有已注册的数据源映射
- **determineCurrentLookupKey()**:获取当前线程使用的数据源标识
#### 2. 通用数据源信息打印
```java
private static void printDataSourceDetails(DataSource ds) {
// 处理Druid数据源
if (ds instanceof DruidDataSource) { ... }
// 处理动态数据源的包装类
else if (ds instanceof ItemDataSource) {
ItemDataSource itemDs = (ItemDataSource) ds;
System.out.println("📊 连接池类型: DynamicDataSource");
System.out.println("🔧 真实数据源类型: " + itemDs.getRealDataSource().getClass().getName());
}
// 通用JDBC信息获取
else {
try (Connection conn = ds.getConnection()) {
DatabaseMetaData meta = conn.getMetaData();
// 获取基础连接信息
}
}
}
```
#### 3. 动态数据源的特殊处理
- **ItemDataSource**:`dynamic-datasource` 中数据源的包装类
- **获取真实数据源**:`itemDs.getRealDataSource()` 获取底层实际数据源
- **通用连接信息**:通过JDBC的 `DatabaseMetaData` 获取基础连接信息
### 输出示例
```
🚀 应用启动成功 | 动态数据源信息
🔧 当前默认数据源: master
📦 已配置数据源数量: 2
==================================================
🔹 数据源名称: master
🔧 驱动类: com.mysql.cj.jdbc.Driver
🌐 连接URL: jdbc:mysql://localhost:3306/main_db
👤 用户名: root
🔑 密码: r******t
📊 连接池类型: DruidDataSource
🔄 初始连接数: 5
⚡ 最大连接数: 20
⏱️ 连接超时(ms): 3000
--------------------------------------------------
🔹 数据源名称: slave
📊 连接池类型: DynamicDataSource
🔧 真实数据源类型: com.zaxxer.hikari.HikariDataSource
🌐 连接URL: jdbc:mysql://slave-server:3306/replica_db
👤 用户名: readonly_user
--------------------------------------------------
```
### 注意事项
1. **依赖要求**:
```xml
<!-- 确保包含 dynamic-datasource 依赖 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>3.5.0</version>
</dependency>
```
2. **安全考虑**:
```java
// 只在开发环境显示
String env = context.getEnvironment().getProperty("spring.profiles.active");
if ("dev".equals(env) || "local".equals(env)) {
printDatabaseInfo(context);
}
```
3. **多数据源配置**:
在 `application.yml` 中配置多数据源:
```yaml
spring:
datasource:
dynamic:
primary: master
datasource:
master:
url: jdbc:mysql://localhost:3306/main_db
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
slave:
url: jdbc:mysql://slave:3306/replica_db
username: readonly
password: readonly123
driver-class-name: com.mysql.cj.jdbc.Driver
```
4. **日志优化**:
使用SLF4J替代System.out:
```java
private static final Logger logger = LoggerFactory.getLogger(JeecgDomianuniqCloudApplication.class);
// 在打印处使用
logger.info("🚀 应用启动成功 | 动态数据源信息");
```
---
阅读全文