①逆向工程插件支持多数据源
②打包体积缩小
This commit is contained in:
@@ -32,12 +32,6 @@
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.mybatis</groupId>
|
||||
<artifactId>mybatis</artifactId>
|
||||
<version>3.5.7</version>
|
||||
</dependency>
|
||||
|
||||
<!-- MyBatis Generator Core -->
|
||||
<dependency>
|
||||
<groupId>org.mybatis.generator</groupId>
|
||||
@@ -64,12 +58,6 @@
|
||||
<version>4.5</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>xerces</groupId>
|
||||
<artifactId>xercesImpl</artifactId>
|
||||
<version>2.12.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
@@ -100,53 +88,10 @@
|
||||
<version>2.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo</artifactId>
|
||||
<version>2.7.12</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Apache Commons CSV for generating CSV files -->
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-csv</artifactId>
|
||||
<version>1.9.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- JGit dependency -->
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jgit</groupId>
|
||||
<artifactId>org.eclipse.jgit</artifactId>
|
||||
<version>6.8.0.202311291450-r</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>33.0.0-jre</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.dom4j</groupId>
|
||||
<artifactId>dom4j</artifactId>
|
||||
<version>2.1.3</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>jaxen</groupId>
|
||||
<artifactId>jaxen</artifactId>
|
||||
<version>1.2.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
<version>1.2.83</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -166,18 +111,6 @@
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>easyexcel</artifactId>
|
||||
<version>3.1.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>redis.clients</groupId>
|
||||
<artifactId>jedis</artifactId>
|
||||
<version>3.7.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
<artifactId>poi-ooxml</artifactId>
|
||||
<version>5.2.3</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
@@ -217,6 +150,15 @@
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<mainClass>com.example.workutils.WorkUtilsApplication</mainClass>
|
||||
<excludes>
|
||||
<exclude>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
|
||||
@@ -19,29 +19,29 @@ echo ========== WorkUtils 生产构建 ==========
|
||||
echo.
|
||||
|
||||
:: 1. 杀掉可能占用 target 的进程
|
||||
echo [1/4] 清理残留进程...
|
||||
echo [1/4] Clean stale processes...
|
||||
taskkill /f /im java.exe 2>nul
|
||||
taskkill /f /im workutils.exe 2>nul
|
||||
|
||||
:: 2. Maven 打包
|
||||
echo.
|
||||
echo [2/4] Maven 编译打包...
|
||||
call "%PROJECT_DIR%mvnw.cmd" clean package -DskipTests -q
|
||||
echo [2/4] Maven build...
|
||||
call "%PROJECT_DIR%\mvnw.cmd" clean package -DskipTests -q
|
||||
if %errorlevel% neq 0 (
|
||||
echo [ERROR] Maven 打包失败!
|
||||
echo [ERROR] Maven build failed!
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
:: 3. 提取版本号
|
||||
for /f "tokens=2 delims=>" %%i in ('findstr /c:"<version>" "%PROJECT_DIR%pom.xml" ^| findstr /v "xml" ^| findstr /n "1" ^| findstr "1:"') do (
|
||||
for /f "tokens=2 delims=>" %%i in ('findstr /c:"<version>" "%PROJECT_DIR%\pom.xml" ^| findstr /v "xml" ^| findstr /n "1" ^| findstr "1:"') do (
|
||||
for /f "tokens=1 delims=<" %%v in ("%%i") do set VERSION=%%v
|
||||
)
|
||||
if "%VERSION%"=="" set VERSION=0.0.1-SNAPSHOT
|
||||
|
||||
:: 4. 准备发布目录
|
||||
echo.
|
||||
echo [3/4] 组装发布包...
|
||||
echo [3/4] Assemble distribution...
|
||||
if exist "%DIST%" rd /s /q "%DIST%"
|
||||
mkdir "%DIST%\workutils" 2>nul
|
||||
|
||||
@@ -63,9 +63,9 @@ powershell -Command "Compress-Archive -Path '%DIST%\workutils' -DestinationPath
|
||||
|
||||
:: 5. 完成
|
||||
echo.
|
||||
echo [4/4] 构建完成!
|
||||
echo [4/4] Build complete!
|
||||
echo ============================================
|
||||
echo 产物位置:
|
||||
echo Output:
|
||||
echo exe : target\workutils.exe
|
||||
echo jar : target\workutils-%VERSION%.jar
|
||||
echo zip : target\dist\%ZIPNAME%.zip
|
||||
|
||||
@@ -132,6 +132,18 @@ public class MyBatisGeneratorPlugin implements Plugin {
|
||||
public String generate(List<String> tables, String modelDir, String xmlDir, String mapperDir) throws Exception {
|
||||
return generatorService.generateByTableNames(tables, true, modelDir, xmlDir, mapperDir);
|
||||
}
|
||||
@Override
|
||||
public List<String> getDatasourceNames() {
|
||||
return generatorService.getDatasourceNames();
|
||||
}
|
||||
@Override
|
||||
public void switchDatasource(String name) {
|
||||
generatorService.switchDatasource(name);
|
||||
}
|
||||
@Override
|
||||
public String getCurrentDatasourceName() {
|
||||
return generatorService.getCurrentDatasourceName();
|
||||
}
|
||||
};
|
||||
|
||||
javafx.application.Platform.runLater(() -> {
|
||||
|
||||
+65
-6
@@ -53,6 +53,9 @@ public class MyBatisGeneratorWindow {
|
||||
private TextField mapperDirField;
|
||||
private TreeView<String> projectTree;
|
||||
private ToggleGroup fillTargetGroup;
|
||||
private ComboBox<String> datasourceCmb;
|
||||
private Label dbUrlLabel;
|
||||
private Label dbUserLabel;
|
||||
|
||||
/** 表项(含复选框) */
|
||||
public static class TableItem {
|
||||
@@ -79,6 +82,12 @@ public class MyBatisGeneratorWindow {
|
||||
String getDbUrl();
|
||||
String getDbUsername();
|
||||
String generate(List<String> tables, String modelDir, String xmlDir, String mapperDir) throws Exception;
|
||||
/** 可用的数据源名称列表 */
|
||||
List<String> getDatasourceNames();
|
||||
/** 切换数据源 */
|
||||
void switchDatasource(String name);
|
||||
/** 当前选中的数据源名称 */
|
||||
String getCurrentDatasourceName();
|
||||
}
|
||||
|
||||
public MyBatisGeneratorWindow(GeneratorCallback callback, FileOperationHelper fileOperationHelper,
|
||||
@@ -177,19 +186,69 @@ public class MyBatisGeneratorWindow {
|
||||
}
|
||||
|
||||
private HBox createDbInfoSection() {
|
||||
HBox box = new HBox(20);
|
||||
HBox box = new HBox(15);
|
||||
box.setPadding(new Insets(8, 12, 8, 12));
|
||||
box.setStyle("-fx-background-color: #e8f0fe; -fx-background-radius: 4;");
|
||||
box.setAlignment(Pos.CENTER_LEFT);
|
||||
|
||||
Label urlLabel = new Label("数据库: " + callback.getDbUrl());
|
||||
urlLabel.setFont(Font.font("Consolas", fsBody()));
|
||||
Label userLabel = new Label("用户: " + callback.getDbUsername());
|
||||
userLabel.setFont(Font.font("Microsoft YaHei", fsBody()));
|
||||
Label dsLabel = new Label("数据源:");
|
||||
dsLabel.setFont(Font.font("Microsoft YaHei", fsBody()));
|
||||
|
||||
box.getChildren().addAll(urlLabel, userLabel);
|
||||
datasourceCmb = new ComboBox<>();
|
||||
datasourceCmb.setPrefWidth(160);
|
||||
datasourceCmb.setStyle("-fx-font-size: " + fsBody() + "px;");
|
||||
|
||||
// 加载数据源列表
|
||||
refreshDatasourceList();
|
||||
datasourceCmb.setOnAction(e -> {
|
||||
String selected = datasourceCmb.getValue();
|
||||
if (selected != null) {
|
||||
callback.switchDatasource("默认配置".equals(selected) ? null : selected);
|
||||
updateDbInfo();
|
||||
}
|
||||
});
|
||||
|
||||
dbUrlLabel = new Label();
|
||||
dbUrlLabel.setFont(Font.font("Consolas", fsBody() - 1));
|
||||
dbUserLabel = new Label();
|
||||
dbUserLabel.setFont(Font.font("Microsoft YaHei", fsBody() - 1));
|
||||
updateDbInfo();
|
||||
|
||||
Button refreshDsBtn = new Button("刷新");
|
||||
refreshDsBtn.setStyle("-fx-font-size: " + (fsBody() - 1) + "px; -fx-padding: 2 8;");
|
||||
refreshDsBtn.setOnAction(e -> {
|
||||
refreshDatasourceList();
|
||||
updateDbInfo();
|
||||
});
|
||||
|
||||
VBox infoBox = new VBox(3, dbUrlLabel, dbUserLabel);
|
||||
|
||||
box.getChildren().addAll(dsLabel, datasourceCmb, refreshDsBtn, infoBox);
|
||||
return box;
|
||||
}
|
||||
|
||||
private void refreshDatasourceList() {
|
||||
String current = datasourceCmb.getValue();
|
||||
datasourceCmb.getItems().clear();
|
||||
datasourceCmb.getItems().add("默认配置");
|
||||
datasourceCmb.getItems().addAll(callback.getDatasourceNames());
|
||||
if (current != null && datasourceCmb.getItems().contains(current)) {
|
||||
datasourceCmb.setValue(current);
|
||||
} else {
|
||||
String dsName = callback.getCurrentDatasourceName();
|
||||
if (dsName != null && datasourceCmb.getItems().contains(dsName)) {
|
||||
datasourceCmb.setValue(dsName);
|
||||
} else {
|
||||
datasourceCmb.setValue("默认配置");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateDbInfo() {
|
||||
dbUrlLabel.setText("数据库: " + callback.getDbUrl());
|
||||
dbUserLabel.setText("用户: " + callback.getDbUsername());
|
||||
}
|
||||
|
||||
// ==================== 左侧:项目路径树 ====================
|
||||
|
||||
private VBox createProjectTreePanel() {
|
||||
|
||||
+97
-57
@@ -1,5 +1,7 @@
|
||||
package com.example.workutils.biz.mybatisgenerator.service.generator;
|
||||
|
||||
import com.example.workutils.system.config.DatasourceConfig;
|
||||
import com.example.workutils.system.config.DatasourceConfigManager;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.mybatis.generator.api.MyBatisGenerator;
|
||||
import org.mybatis.generator.config.Configuration;
|
||||
@@ -25,12 +27,40 @@ public class MyBatisGeneratorService {
|
||||
private static final String CONFIG_FILE = "mybatis-generator.xml";
|
||||
private static final String PROPERTIES_FILE = "mybatis-generator.properties";
|
||||
|
||||
private final DatasourceConfigManager datasourceMgr;
|
||||
/** 当前选中的数据源名称(null = 使用外部配置或内置默认配置) */
|
||||
private String currentDatasourceName;
|
||||
|
||||
public MyBatisGeneratorService(DatasourceConfigManager datasourceMgr) {
|
||||
this.datasourceMgr = datasourceMgr;
|
||||
}
|
||||
|
||||
// ==================== 数据源切换 ====================
|
||||
|
||||
public List<String> getDatasourceNames() {
|
||||
return datasourceMgr.getDatasourceNames();
|
||||
}
|
||||
|
||||
public DatasourceConfig getCurrentDatasource() {
|
||||
if (currentDatasourceName != null) {
|
||||
return datasourceMgr.findByName(currentDatasourceName);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getCurrentDatasourceName() {
|
||||
return currentDatasourceName;
|
||||
}
|
||||
|
||||
public void switchDatasource(String name) {
|
||||
this.currentDatasourceName = name;
|
||||
log.info("已切换数据源: {}", name != null ? name : "默认配置");
|
||||
}
|
||||
|
||||
// ==================== 生成入口 ====================
|
||||
|
||||
/**
|
||||
* 根据表名列表生成Mapper文件
|
||||
*
|
||||
* @param tableNames 表名列表
|
||||
* @param overwrite 是否覆盖已有文件
|
||||
* @return 生成结果信息
|
||||
*/
|
||||
public String generateByTableNames(List<String> tableNames, boolean overwrite) throws Exception {
|
||||
return generateInternal(tableNames, overwrite, null, null, null);
|
||||
@@ -46,40 +76,27 @@ public class MyBatisGeneratorService {
|
||||
|
||||
/**
|
||||
* 根据表名通配符生成Mapper文件
|
||||
* 先查询数据库中匹配的表,再进行逆向工程
|
||||
*
|
||||
* @param pattern 表名通配符(如 user_%)
|
||||
* @param overwrite 是否覆盖已有文件
|
||||
* @return 生成结果信息
|
||||
*/
|
||||
public String generateByPattern(String pattern, boolean overwrite) throws Exception {
|
||||
List<String> matchedTables = queryTablesByPattern(pattern);
|
||||
|
||||
if (matchedTables.isEmpty()) {
|
||||
return "未找到匹配通配符 [" + pattern + "] 的表";
|
||||
}
|
||||
|
||||
log.info("通配符 [{}] 匹配到 {} 张表: {}", pattern, matchedTables.size(), matchedTables);
|
||||
return generateInternal(matchedTables, overwrite, null, null, null);
|
||||
}
|
||||
|
||||
// ==================== 数据库查询 ====================
|
||||
|
||||
/**
|
||||
* 根据通配符查询数据库中的表
|
||||
*
|
||||
* @param pattern 表名通配符(支持 % 和 _ 通配符)
|
||||
* @return 匹配的表名列表
|
||||
*/
|
||||
public List<String> queryTablesByPattern(String pattern) throws Exception {
|
||||
List<String> tables = new ArrayList<>();
|
||||
Properties props = getConfigurationProperties();
|
||||
|
||||
String url = props.getProperty("db_url");
|
||||
String username = props.getProperty("db_username");
|
||||
String password = props.getProperty("db_password");
|
||||
|
||||
String dbName = extractDatabaseName(url);
|
||||
|
||||
try (Connection conn = DriverManager.getConnection(url, username, password)) {
|
||||
DbConnection db = getDbConnection();
|
||||
String dbName = extractDatabaseName(db.url);
|
||||
|
||||
try (Connection conn = DriverManager.getConnection(db.url, db.username, db.password)) {
|
||||
String sql = "SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = ? AND TABLE_NAME LIKE ?";
|
||||
try (PreparedStatement ps = conn.prepareStatement(sql)) {
|
||||
ps.setString(1, dbName);
|
||||
@@ -91,26 +108,18 @@ public class MyBatisGeneratorService {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tables;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询数据库中所有表
|
||||
*
|
||||
* @return 所有表名列表
|
||||
*/
|
||||
public List<String> queryAllTables() throws Exception {
|
||||
List<String> tables = new ArrayList<>();
|
||||
Properties props = getConfigurationProperties();
|
||||
|
||||
String url = props.getProperty("db_url");
|
||||
String username = props.getProperty("db_username");
|
||||
String password = props.getProperty("db_password");
|
||||
|
||||
String dbName = extractDatabaseName(url);
|
||||
|
||||
try (Connection conn = DriverManager.getConnection(url, username, password)) {
|
||||
DbConnection db = getDbConnection();
|
||||
String dbName = extractDatabaseName(db.url);
|
||||
|
||||
try (Connection conn = DriverManager.getConnection(db.url, db.username, db.password)) {
|
||||
String sql = "SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = ? ORDER BY TABLE_NAME";
|
||||
try (PreparedStatement ps = conn.prepareStatement(sql)) {
|
||||
ps.setString(1, dbName);
|
||||
@@ -121,10 +130,39 @@ public class MyBatisGeneratorService {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tables;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前生效的数据库连接信息
|
||||
* 优先级: 选中的数据源 > 外部配置(workutils.config) > 内置classpath属性
|
||||
*/
|
||||
private DbConnection getDbConnection() {
|
||||
DatasourceConfig ds = getCurrentDatasource();
|
||||
if (ds != null) {
|
||||
return new DbConnection(ds.getUrl(), ds.getUsername(), ds.getPassword());
|
||||
}
|
||||
// 回退 classpath 配置
|
||||
Properties props = getClasspathProperties();
|
||||
return new DbConnection(
|
||||
props.getProperty("db_url", ""),
|
||||
props.getProperty("db_username", ""),
|
||||
props.getProperty("db_password", "")
|
||||
);
|
||||
}
|
||||
|
||||
/** 内部数据类:数据库连接信息 */
|
||||
private static class DbConnection {
|
||||
final String url;
|
||||
final String username;
|
||||
final String password;
|
||||
DbConnection(String url, String username, String password) {
|
||||
this.url = url;
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从JDBC URL中提取数据库名
|
||||
*/
|
||||
@@ -352,9 +390,22 @@ public class MyBatisGeneratorService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取配置属性
|
||||
* 获取配置属性(优先使用选中的数据源,回退到classpath)
|
||||
*/
|
||||
public Properties getConfigurationProperties() {
|
||||
Properties props = getClasspathProperties();
|
||||
// 如果选中了数据源,覆盖连接信息
|
||||
DatasourceConfig ds = getCurrentDatasource();
|
||||
if (ds != null) {
|
||||
if (ds.getDriver() != null) props.setProperty("db_driver", ds.getDriver());
|
||||
if (ds.getUrl() != null) props.setProperty("db_url", ds.getUrl());
|
||||
if (ds.getUsername() != null) props.setProperty("db_username", ds.getUsername());
|
||||
if (ds.getPassword() != null) props.setProperty("db_password", ds.getPassword());
|
||||
}
|
||||
return props;
|
||||
}
|
||||
|
||||
private Properties getClasspathProperties() {
|
||||
Properties props = new Properties();
|
||||
try {
|
||||
props.load(getClass().getClassLoader().getResourceAsStream(PROPERTIES_FILE));
|
||||
@@ -364,38 +415,27 @@ public class MyBatisGeneratorService {
|
||||
return props;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取数据库URL
|
||||
*/
|
||||
public String getDatabaseUrl() {
|
||||
return getConfigurationProperties().getProperty("db_url", "");
|
||||
DatasourceConfig ds = getCurrentDatasource();
|
||||
if (ds != null) return ds.getUrl();
|
||||
return getClasspathProperties().getProperty("db_url", "");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取数据库用户名
|
||||
*/
|
||||
public String getDatabaseUsername() {
|
||||
return getConfigurationProperties().getProperty("db_username", "");
|
||||
DatasourceConfig ds = getCurrentDatasource();
|
||||
if (ds != null) return ds.getUsername();
|
||||
return getClasspathProperties().getProperty("db_username", "");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Model包路径
|
||||
*/
|
||||
public String getModelPackage() {
|
||||
return getConfigurationProperties().getProperty("model_package", "");
|
||||
return getClasspathProperties().getProperty("model_package", "");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Mapper包路径
|
||||
*/
|
||||
public String getMapperPackage() {
|
||||
return getConfigurationProperties().getProperty("dao_package", "");
|
||||
return getClasspathProperties().getProperty("dao_package", "");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取SQL Mapper包路径
|
||||
*/
|
||||
public String getSqlMapperPackage() {
|
||||
return getConfigurationProperties().getProperty("sqlmapper_package", "");
|
||||
return getClasspathProperties().getProperty("sqlmapper_package", "");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.example.workutils.system.config;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 单条数据源配置
|
||||
*/
|
||||
@Data
|
||||
public class DatasourceConfig {
|
||||
|
||||
/** 显示名称(如"开发环境"、"SIT环境") */
|
||||
private String name;
|
||||
|
||||
/** JDBC 驱动类 */
|
||||
private String driver = "com.mysql.jdbc.Driver";
|
||||
|
||||
/** JDBC URL */
|
||||
private String url;
|
||||
|
||||
/** 用户名 */
|
||||
private String username;
|
||||
|
||||
/** 密码 */
|
||||
private String password;
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package com.example.workutils.system.config;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 多数据源配置管理器
|
||||
* <p>
|
||||
* 从 data/datasources.json 加载数据源列表,供 MyBatis 逆向工程插件选择使用。
|
||||
* 首次运行时自动从 classpath 模板复制到 data/ 目录。
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class DatasourceConfigManager {
|
||||
|
||||
private static final String DATASOURCE_FILE = "data/datasources.json";
|
||||
private static final String TEMPLATE_PATH = "templates/datasources.json";
|
||||
|
||||
private final List<DatasourceConfig> datasources = new ArrayList<>();
|
||||
private Path configFile;
|
||||
|
||||
@PostConstruct
|
||||
void init() {
|
||||
configFile = Paths.get(System.getProperty("user.dir"), DATASOURCE_FILE);
|
||||
ensureConfigExists();
|
||||
reload();
|
||||
}
|
||||
|
||||
/** 确保数据源配置文件存在 */
|
||||
private void ensureConfigExists() {
|
||||
if (Files.exists(configFile)) return;
|
||||
try {
|
||||
Files.createDirectories(configFile.getParent());
|
||||
try (InputStream is = getClass().getClassLoader().getResourceAsStream(TEMPLATE_PATH)) {
|
||||
if (is != null) {
|
||||
Files.copy(is, configFile);
|
||||
log.info("已从模板复制数据源配置: {}", configFile.toAbsolutePath());
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.warn("复制数据源模板失败: {}", e.getMessage());
|
||||
}
|
||||
// 兜底:创建空数组
|
||||
try {
|
||||
Files.write(configFile, "[]".getBytes(StandardCharsets.UTF_8));
|
||||
log.info("已创建空数据源配置: {}", configFile.toAbsolutePath());
|
||||
} catch (IOException e) {
|
||||
log.error("创建数据源配置文件失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/** 重新加载数据源配置 */
|
||||
public synchronized void reload() {
|
||||
datasources.clear();
|
||||
if (!Files.exists(configFile)) return;
|
||||
try {
|
||||
String json = new String(Files.readAllBytes(configFile), StandardCharsets.UTF_8);
|
||||
List<DatasourceConfig> loaded = JSON.parseArray(json, DatasourceConfig.class);
|
||||
if (loaded != null) {
|
||||
datasources.addAll(loaded);
|
||||
}
|
||||
log.info("已加载 {} 套数据源配置", datasources.size());
|
||||
} catch (IOException e) {
|
||||
log.error("解析数据源配置失败: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/** 获取所有数据源名称列表 */
|
||||
public List<String> getDatasourceNames() {
|
||||
List<String> names = new ArrayList<>();
|
||||
for (DatasourceConfig ds : datasources) {
|
||||
names.add(ds.getName());
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
/** 根据名称查找数据源配置 */
|
||||
public DatasourceConfig findByName(String name) {
|
||||
return datasources.stream()
|
||||
.filter(ds -> ds.getName().equals(name))
|
||||
.findFirst().orElse(null);
|
||||
}
|
||||
|
||||
/** 获取配置文件的路径(供设置窗口打开编辑) */
|
||||
public Path getConfigFile() {
|
||||
return configFile;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
[
|
||||
{
|
||||
"name": "开发环境",
|
||||
"driver": "com.mysql.jdbc.Driver",
|
||||
"url": "jdbc:mysql://localhost:3306/disburse?useUnicode=true&characterEncoding=utf8&useSSL=false",
|
||||
"username": "root",
|
||||
"password": "1Qaz@4772"
|
||||
},
|
||||
{
|
||||
"name": "SIT环境",
|
||||
"driver": "com.mysql.jdbc.Driver",
|
||||
"url": "jdbc:mysql://sit-server:3306/disburse?useUnicode=true&characterEncoding=utf8&useSSL=false",
|
||||
"username": "sit_user",
|
||||
"password": ""
|
||||
},
|
||||
{
|
||||
"name": "生产环境(只读)",
|
||||
"driver": "com.mysql.jdbc.Driver",
|
||||
"url": "jdbc:mysql://prod-server:3306/disburse?useUnicode=true&characterEncoding=utf8&useSSL=false",
|
||||
"username": "readonly",
|
||||
"password": ""
|
||||
}
|
||||
]
|
||||
Reference in New Issue
Block a user