优化仓库路径配置
This commit is contained in:
+29
-17
@@ -11,6 +11,8 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.Scanner;
|
||||
@@ -62,27 +64,37 @@ public class MyBatisGeneratorPlugin implements Plugin {
|
||||
return "MyBatis 外部配置中数据库 URL 未设置。\n请通过「系统设置 > MyBatis 数据库」标签页补充。";
|
||||
}
|
||||
|
||||
// 2. 回退检查内置 classpath 配置
|
||||
// 2. 回退检查 data/ 外部配置 → classpath 内置配置
|
||||
Properties props = new Properties();
|
||||
// 2a. 先尝试 classpath 内置值(作为基线)
|
||||
try (InputStream is = getClass().getClassLoader()
|
||||
.getResourceAsStream("mybatis-generator.properties")) {
|
||||
if (is == null) {
|
||||
return "MyBatis 生成器配置文件不存在: mybatis-generator.properties\n"
|
||||
+ "请在 src/main/resources/ 下创建此文件,完成后重新打包。\n"
|
||||
+ "或通过「系统设置 > MyBatis 数据库」标签页配置数据库连接。";
|
||||
}
|
||||
Properties props = new Properties();
|
||||
props.load(is);
|
||||
String dbUrl = props.getProperty("db_url", "");
|
||||
String dbUser = props.getProperty("db_username", "");
|
||||
if (dbUrl.isEmpty() || dbUser.isEmpty()) {
|
||||
return "MyBatis 生成器数据库配置不完整:\n"
|
||||
+ " db_url = " + (dbUrl.isEmpty() ? "(未设置)" : dbUrl) + "\n"
|
||||
+ " db_username = " + (dbUser.isEmpty() ? "(未设置)" : dbUser) + "\n"
|
||||
+ "请编辑 src/main/resources/mybatis-generator.properties 后重新打包,\n"
|
||||
+ "或通过「系统设置 > MyBatis 数据库」标签页配置。";
|
||||
if (is != null) {
|
||||
props.load(is);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return "无法读取 MyBatis 生成器配置文件:\n错误: " + e.getMessage();
|
||||
log.warn("无法读取 classpath 内置配置", e);
|
||||
}
|
||||
// 2b. 用 data/ 外部配置覆盖
|
||||
Path dataFile = properties.getMybatisGeneratorFilePath();
|
||||
if (Files.exists(dataFile)) {
|
||||
try (InputStream is = new java.io.FileInputStream(dataFile.toFile())) {
|
||||
Properties externalProps = new Properties();
|
||||
externalProps.load(is);
|
||||
props.putAll(externalProps);
|
||||
} catch (Exception e) {
|
||||
log.warn("无法读取 data/ MyBatis 配置", e);
|
||||
}
|
||||
}
|
||||
|
||||
String dbUrl = props.getProperty("db_url", "");
|
||||
String dbUser = props.getProperty("db_username", "");
|
||||
if (dbUrl.isEmpty() || dbUser.isEmpty()) {
|
||||
return "MyBatis 生成器数据库配置不完整:\n"
|
||||
+ " db_url = " + (dbUrl.isEmpty() ? "(未设置)" : dbUrl) + "\n"
|
||||
+ " db_username = " + (dbUser.isEmpty() ? "(未设置)" : dbUser) + "\n"
|
||||
+ "请在 data/mybatis-generator.properties 中编辑数据库连接信息,\n"
|
||||
+ "或通过「系统设置 > MyBatis 数据库」标签页配置。";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -448,9 +448,19 @@ public class MyBatisGeneratorWindow {
|
||||
|
||||
private void loadDefaultDirs() {
|
||||
Properties p = new Properties();
|
||||
// 1. classpath 内置默认值
|
||||
try (InputStream is = getClass().getClassLoader().getResourceAsStream("mybatis-generator.properties")) {
|
||||
if (is != null) p.load(is);
|
||||
} catch (Exception ignored) {}
|
||||
// 2. data/ 外部配置覆盖
|
||||
Path dataFile = properties.getMybatisGeneratorFilePath();
|
||||
if (java.nio.file.Files.exists(dataFile)) {
|
||||
try (InputStream is = new java.io.FileInputStream(dataFile.toFile())) {
|
||||
Properties externalProps = new Properties();
|
||||
externalProps.load(is);
|
||||
p.putAll(externalProps);
|
||||
} catch (Exception ignored) {}
|
||||
}
|
||||
|
||||
setDirField(modelDirField, p.getProperty("model_target_project", "./generator"));
|
||||
setDirField(xmlDirField, p.getProperty("sqlmapper_target_project", "./generator"));
|
||||
|
||||
+49
-17
@@ -2,6 +2,7 @@ package com.example.workutils.biz.mybatisgenerator.service.generator;
|
||||
|
||||
import com.example.workutils.system.config.DatasourceConfig;
|
||||
import com.example.workutils.system.config.DatasourceConfigManager;
|
||||
import com.example.workutils.system.config.WorkUtilsProperties;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.mybatis.generator.api.MyBatisGenerator;
|
||||
import org.mybatis.generator.config.Configuration;
|
||||
@@ -11,6 +12,8 @@ import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.sql.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -25,14 +28,16 @@ import java.util.Properties;
|
||||
public class MyBatisGeneratorService {
|
||||
|
||||
private static final String CONFIG_FILE = "mybatis-generator.xml";
|
||||
private static final String PROPERTIES_FILE = "mybatis-generator.properties";
|
||||
private static final String CLASSPATH_PROPERTIES = "mybatis-generator.properties";
|
||||
|
||||
private final DatasourceConfigManager datasourceMgr;
|
||||
/** 当前选中的数据源名称(null = 使用外部配置或内置默认配置) */
|
||||
private final WorkUtilsProperties workUtilsProperties;
|
||||
/** 当前选中的数据源名称(null = 使用 data/ 外部配置或内置默认配置) */
|
||||
private String currentDatasourceName;
|
||||
|
||||
public MyBatisGeneratorService(DatasourceConfigManager datasourceMgr) {
|
||||
public MyBatisGeneratorService(DatasourceConfigManager datasourceMgr, WorkUtilsProperties workUtilsProperties) {
|
||||
this.datasourceMgr = datasourceMgr;
|
||||
this.workUtilsProperties = workUtilsProperties;
|
||||
}
|
||||
|
||||
// ==================== 数据源切换 ====================
|
||||
@@ -142,8 +147,8 @@ public class MyBatisGeneratorService {
|
||||
if (ds != null) {
|
||||
return new DbConnection(ds.getUrl(), ds.getUsername(), ds.getPassword());
|
||||
}
|
||||
// 回退 classpath 配置
|
||||
Properties props = getClasspathProperties();
|
||||
// 回退: data/ 外部配置 → classpath 内置配置
|
||||
Properties props = loadMybatisProperties();
|
||||
return new DbConnection(
|
||||
props.getProperty("db_url", ""),
|
||||
props.getProperty("db_username", ""),
|
||||
@@ -250,6 +255,15 @@ public class MyBatisGeneratorService {
|
||||
content = sb.toString();
|
||||
}
|
||||
|
||||
// 将 classpath 资源引用替换为 data/ 外部文件的 file:// URL
|
||||
Path propsFile = workUtilsProperties.getMybatisGeneratorFilePath();
|
||||
if (Files.exists(propsFile)) {
|
||||
String fileUrl = propsFile.toUri().toString();
|
||||
content = content.replace(
|
||||
"<properties resource=\"" + CLASSPATH_PROPERTIES + "\" />",
|
||||
"<properties url=\"" + fileUrl + "\" />");
|
||||
}
|
||||
|
||||
// 截掉 </generatorConfiguration> 之后的内容(防止尾随垃圾导致 XML 解析失败)
|
||||
int endIdx = content.lastIndexOf("</generatorConfiguration>");
|
||||
if (endIdx >= 0) {
|
||||
@@ -390,10 +404,10 @@ public class MyBatisGeneratorService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取配置属性(优先使用选中的数据源,回退到classpath)
|
||||
* 获取配置属性(优先: 选中数据源 > data/ 外部配置 > classpath 内置配置)
|
||||
*/
|
||||
public Properties getConfigurationProperties() {
|
||||
Properties props = getClasspathProperties();
|
||||
Properties props = loadMybatisProperties();
|
||||
// 如果选中了数据源,覆盖连接信息
|
||||
DatasourceConfig ds = getCurrentDatasource();
|
||||
if (ds != null) {
|
||||
@@ -405,12 +419,30 @@ public class MyBatisGeneratorService {
|
||||
return props;
|
||||
}
|
||||
|
||||
private Properties getClasspathProperties() {
|
||||
/**
|
||||
* 加载 MyBatis 属性:优先从 data/ 目录,回退 classpath
|
||||
*/
|
||||
private Properties loadMybatisProperties() {
|
||||
Properties props = new Properties();
|
||||
try {
|
||||
props.load(getClass().getClassLoader().getResourceAsStream(PROPERTIES_FILE));
|
||||
} catch (Exception e) {
|
||||
log.warn("无法加载配置属性文件", e);
|
||||
// 1. 先从 classpath 加载内置默认值
|
||||
try (InputStream is = getClass().getClassLoader().getResourceAsStream(CLASSPATH_PROPERTIES)) {
|
||||
if (is != null) {
|
||||
props.load(is);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.warn("无法加载 classpath 内置属性文件", e);
|
||||
}
|
||||
// 2. 再用 data/ 目录的外部配置覆盖
|
||||
Path dataFile = workUtilsProperties.getMybatisGeneratorFilePath();
|
||||
if (Files.exists(dataFile)) {
|
||||
try (InputStream is = new FileInputStream(dataFile.toFile())) {
|
||||
Properties externalProps = new Properties();
|
||||
externalProps.load(is);
|
||||
props.putAll(externalProps); // 外部配置覆盖内置值
|
||||
log.debug("已从 data/ 加载 MyBatis 属性: {}", dataFile.toAbsolutePath());
|
||||
} catch (IOException e) {
|
||||
log.warn("无法加载 data/ MyBatis 属性文件: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
return props;
|
||||
}
|
||||
@@ -418,24 +450,24 @@ public class MyBatisGeneratorService {
|
||||
public String getDatabaseUrl() {
|
||||
DatasourceConfig ds = getCurrentDatasource();
|
||||
if (ds != null) return ds.getUrl();
|
||||
return getClasspathProperties().getProperty("db_url", "");
|
||||
return loadMybatisProperties().getProperty("db_url", "");
|
||||
}
|
||||
|
||||
public String getDatabaseUsername() {
|
||||
DatasourceConfig ds = getCurrentDatasource();
|
||||
if (ds != null) return ds.getUsername();
|
||||
return getClasspathProperties().getProperty("db_username", "");
|
||||
return loadMybatisProperties().getProperty("db_username", "");
|
||||
}
|
||||
|
||||
public String getModelPackage() {
|
||||
return getClasspathProperties().getProperty("model_package", "");
|
||||
return loadMybatisProperties().getProperty("model_package", "");
|
||||
}
|
||||
|
||||
public String getMapperPackage() {
|
||||
return getClasspathProperties().getProperty("dao_package", "");
|
||||
return loadMybatisProperties().getProperty("dao_package", "");
|
||||
}
|
||||
|
||||
public String getSqlMapperPackage() {
|
||||
return getClasspathProperties().getProperty("sqlmapper_package", "");
|
||||
return loadMybatisProperties().getProperty("sqlmapper_package", "");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,9 +7,13 @@ import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 配置初始化器 —— Spring 启动完成后检查并合并外部配置
|
||||
* 配置初始化器 —— Spring 启动完成后加载外部配置
|
||||
* <p>
|
||||
* 优先级: workutils.config > application.yml > 默认值
|
||||
* data/ 目录下的配置文件由 WorkUtilsProperties 在 @PostConstruct 阶段统一确保存在
|
||||
* (不存在时自动从 classpath:templates/ 复制)。
|
||||
* 本初始化器负责加载 workutils.config 并合并到运行属性中。
|
||||
* <p>
|
||||
* 优先级: data/workutils.config > application.yml > 默认值
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@@ -22,13 +26,10 @@ public class ConfigInitializer implements ApplicationListener<ApplicationReadyEv
|
||||
@Override
|
||||
public void onApplicationEvent(ApplicationReadyEvent event) {
|
||||
if (configManager.exists()) {
|
||||
log.info("发现外部配置文件: {}", configManager.getConfigFile().toAbsolutePath());
|
||||
log.info("加载外部配置文件: {}", configManager.getConfigFile().toAbsolutePath());
|
||||
properties.mergeExternal(configManager.load());
|
||||
} else {
|
||||
log.info("未找到外部配置文件 workutils.config,正在使用 application.yml 默认值生成...");
|
||||
configManager.saveSectioned(configManager.generateDefaults(properties));
|
||||
properties.mergeExternal(configManager.load());
|
||||
log.info("已生成默认外部配置文件: {}", configManager.getConfigFile().toAbsolutePath());
|
||||
log.info("无外部配置文件,使用 application.yml 默认值");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,60 +9,39 @@ 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/ 目录。
|
||||
* 配置文件的路径和首次复制由 WorkUtilsProperties 统一管理。
|
||||
*/
|
||||
@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 WorkUtilsProperties properties;
|
||||
private final List<DatasourceConfig> datasources = new ArrayList<>();
|
||||
private Path configFile;
|
||||
|
||||
public DatasourceConfigManager(WorkUtilsProperties properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
void init() {
|
||||
configFile = Paths.get(System.getProperty("user.dir"), DATASOURCE_FILE);
|
||||
ensureConfigExists();
|
||||
// data/ 目录下的文件已由 WorkUtilsProperties 统一确保存在
|
||||
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;
|
||||
Path configFile = getConfigFile();
|
||||
if (!Files.exists(configFile)) {
|
||||
log.warn("数据源配置文件不存在: {}", configFile.toAbsolutePath());
|
||||
return;
|
||||
}
|
||||
try {
|
||||
String json = new String(Files.readAllBytes(configFile), StandardCharsets.UTF_8);
|
||||
List<DatasourceConfig> loaded = JSON.parseArray(json, DatasourceConfig.class);
|
||||
@@ -93,6 +72,6 @@ public class DatasourceConfigManager {
|
||||
|
||||
/** 获取配置文件的路径(供设置窗口打开编辑) */
|
||||
public Path getConfigFile() {
|
||||
return configFile;
|
||||
return properties.getDatasourcesFilePath();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ 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.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
@@ -15,9 +14,9 @@ import java.util.Properties;
|
||||
/**
|
||||
* 外部配置文件管理器
|
||||
* <p>
|
||||
* 管理 exe 同级目录下的 workutils.config 文件:
|
||||
* 管理 data/ 目录下的 workutils.config 文件:
|
||||
* <ul>
|
||||
* <li>首次运行自动生成带注释的分段式默认配置</li>
|
||||
* <li>首次运行时由 WorkUtilsProperties 从 templates/ 复制到 data/</li>
|
||||
* <li>运行时读写,优先级高于 application.yml</li>
|
||||
* <li>支持热重载</li>
|
||||
* <li>手动写入避免中文 Unicode 转义</li>
|
||||
@@ -27,7 +26,11 @@ import java.util.Properties;
|
||||
@Component
|
||||
public class ExternalConfigManager {
|
||||
|
||||
static final String CONFIG_FILE_NAME = "data/workutils.config";
|
||||
private final WorkUtilsProperties properties;
|
||||
|
||||
public ExternalConfigManager(WorkUtilsProperties properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
// ---- 系统路径 ----
|
||||
public static final String KEY_BASE_DIR = "base-directory";
|
||||
@@ -78,9 +81,9 @@ public class ExternalConfigManager {
|
||||
});
|
||||
}
|
||||
|
||||
/** 获取配置文件路径(exe 所在目录) */
|
||||
/** 获取配置文件路径 */
|
||||
public Path getConfigFile() {
|
||||
return Paths.get(System.getProperty("user.dir"), CONFIG_FILE_NAME);
|
||||
return properties.getWorkutilsConfigFilePath();
|
||||
}
|
||||
|
||||
public boolean exists() {
|
||||
@@ -155,39 +158,4 @@ public class ExternalConfigManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 application.yml 生成默认配置(数据文件、config文件均为 user.dir 同级目录)
|
||||
*/
|
||||
public Properties generateDefaults(WorkUtilsProperties appProps) {
|
||||
Properties props = new Properties();
|
||||
props.setProperty(KEY_BASE_DIR, nvl(appProps.getBaseDirectory()));
|
||||
props.setProperty(KEY_EXPORT_DIR, nvl(appProps.getExportDirectory()));
|
||||
|
||||
// 数据文件用 user.dir 下的绝对路径
|
||||
props.setProperty(KEY_PROJECT_PATHS, appProps.getProjectPathsFilePath().toAbsolutePath().toString());
|
||||
props.setProperty(KEY_DAMAGED_REPOS, appProps.getDamagedReposFilePath().toAbsolutePath().toString());
|
||||
|
||||
// MyBatis 留空让用户填
|
||||
String[] mybatisKeys = {
|
||||
KEY_MYBATIS_DRIVER, KEY_MYBATIS_URL, KEY_MYBATIS_USERNAME,
|
||||
KEY_MYBATIS_PASSWORD,
|
||||
KEY_MYBATIS_MODEL_PKG, KEY_MYBATIS_DAO_PKG, KEY_MYBATIS_SQLMAPPER_PKG
|
||||
};
|
||||
for (String k : mybatisKeys) {
|
||||
props.setProperty(k, "");
|
||||
}
|
||||
|
||||
// 字体大小默认值
|
||||
props.setProperty(KEY_FONT_SECTION_TITLE, String.valueOf(appProps.getFontSectionTitle()));
|
||||
props.setProperty(KEY_FONT_FIELD_LABEL, String.valueOf(appProps.getFontFieldLabel()));
|
||||
props.setProperty(KEY_FONT_BUTTON, String.valueOf(appProps.getFontButton()));
|
||||
props.setProperty(KEY_FONT_BODY, String.valueOf(appProps.getFontBody()));
|
||||
props.setProperty(KEY_FONT_MONO, String.valueOf(appProps.getFontMono()));
|
||||
|
||||
return props;
|
||||
}
|
||||
|
||||
private static String nvl(String s) {
|
||||
return s == null ? "" : s;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import javafx.stage.Stage;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
@@ -233,7 +234,7 @@ public class SettingsWindow {
|
||||
|
||||
wrapper.getChildren().add(grid);
|
||||
|
||||
Button btnLoadBuiltin = new Button("从内置 mybatis-generator.properties 加载");
|
||||
Button btnLoadBuiltin = new Button("从 data/mybatis-generator.properties 加载");
|
||||
btnLoadBuiltin.setFont(font(fontButton));
|
||||
btnLoadBuiltin.setStyle("-fx-padding: 6 14;");
|
||||
allButtons.add(btnLoadBuiltin);
|
||||
@@ -564,7 +565,8 @@ public class SettingsWindow {
|
||||
private void loadMyBatisFromClasspath() {
|
||||
Properties builtin = loadBuiltinMyBatisProps();
|
||||
if (builtin.isEmpty()) {
|
||||
showAlert(AlertType.WARNING, "未找到内置 mybatis-generator.properties 文件。");
|
||||
showAlert(AlertType.WARNING, "未找到 mybatis-generator.properties 配置文件。"
|
||||
+ "\n请检查 data/mybatis-generator.properties 是否存在。");
|
||||
return;
|
||||
}
|
||||
tfDbDriver.setText(builtin.getProperty("db_driver", ""));
|
||||
@@ -579,6 +581,7 @@ public class SettingsWindow {
|
||||
|
||||
private Properties loadBuiltinMyBatisProps() {
|
||||
Properties props = new Properties();
|
||||
// 1. 先从 classpath 加载内置默认值
|
||||
try (InputStream is = getClass().getClassLoader()
|
||||
.getResourceAsStream("mybatis-generator.properties")) {
|
||||
if (is != null) {
|
||||
@@ -586,6 +589,16 @@ public class SettingsWindow {
|
||||
}
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
// 2. 再用 data/ 外部配置覆盖
|
||||
Path dataFile = properties.getMybatisGeneratorFilePath();
|
||||
if (Files.exists(dataFile)) {
|
||||
try (InputStream is = new FileInputStream(dataFile.toFile())) {
|
||||
Properties externalProps = new Properties();
|
||||
externalProps.load(is);
|
||||
props.putAll(externalProps);
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
return props;
|
||||
}
|
||||
|
||||
|
||||
@@ -50,6 +50,15 @@ public class WorkUtilsProperties {
|
||||
/** 损坏仓库缓存文件(相对路径时相对于 user.dir) */
|
||||
private String damagedReposFile;
|
||||
|
||||
/** 数据源配置文件(相对路径时相对于 user.dir) */
|
||||
private String datasourcesFile;
|
||||
|
||||
/** 外部配置文件(相对路径时相对于 user.dir) */
|
||||
private String workutilsConfigFile;
|
||||
|
||||
/** MyBatis 生成器配置文件(相对路径时相对于 user.dir) */
|
||||
private String mybatisGeneratorFile;
|
||||
|
||||
/** 工具启用/禁用配置 */
|
||||
private ToolsConfig tools;
|
||||
|
||||
@@ -92,8 +101,8 @@ public class WorkUtilsProperties {
|
||||
defaults.put(ExternalConfigManager.KEY_EXPORT_DIR, exportDirectory);
|
||||
defaults.put(ExternalConfigManager.KEY_PROJECT_PATHS, projectPathsFile);
|
||||
defaults.put(ExternalConfigManager.KEY_DAMAGED_REPOS, damagedReposFile);
|
||||
// 首次运行时确保数据文件存在于 user.dir 同级目录
|
||||
ensureDataFilesExist();
|
||||
// 首次运行时确保所有数据文件存在于 user.dir 同级 data/ 目录
|
||||
ensureAllDataFilesExist();
|
||||
}
|
||||
|
||||
/** 确保导出目录存在 */
|
||||
@@ -202,7 +211,7 @@ public class WorkUtilsProperties {
|
||||
* 否则解析到 user.dir 下。
|
||||
*/
|
||||
public Path getDamagedReposFilePath() {
|
||||
Path p = Paths.get(damagedReposFile != null ? damagedReposFile : "damaged_repos.cache");
|
||||
Path p = Paths.get(damagedReposFile != null ? damagedReposFile : "data/damaged_repos.cache");
|
||||
if (p.isAbsolute()) {
|
||||
return p;
|
||||
}
|
||||
@@ -210,16 +219,50 @@ public class WorkUtilsProperties {
|
||||
}
|
||||
|
||||
/**
|
||||
* 确保数据文件存在于 user.dir 同级目录。
|
||||
* 不存在时从 classpath:config/ 下复制模板内容(保留原始内容),
|
||||
* 无法读取模板时则创建空文件。
|
||||
* 数据源配置文件的实际路径
|
||||
*/
|
||||
private void ensureDataFilesExist() {
|
||||
ensureDataFile(getProjectPathsFilePath(), TEMPLATES_PATH + "project_paths.txt", "项目路径文件");
|
||||
ensureDataFile(getDamagedReposFilePath(), TEMPLATES_PATH + "damaged_repos.cache", "损坏缓存文件");
|
||||
public Path getDatasourcesFilePath() {
|
||||
Path p = Paths.get(datasourcesFile != null ? datasourcesFile : "data/datasources.json");
|
||||
if (p.isAbsolute()) {
|
||||
return p;
|
||||
}
|
||||
return Paths.get(System.getProperty("user.dir")).resolve(p);
|
||||
}
|
||||
|
||||
private static final String TEMPLATES_PATH = "templates/";
|
||||
/**
|
||||
* 外部配置文件(workutils.config)的实际路径
|
||||
*/
|
||||
public Path getWorkutilsConfigFilePath() {
|
||||
Path p = Paths.get(workutilsConfigFile != null ? workutilsConfigFile : "data/workutils.config");
|
||||
if (p.isAbsolute()) {
|
||||
return p;
|
||||
}
|
||||
return Paths.get(System.getProperty("user.dir")).resolve(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* MyBatis 生成器配置文件的实际路径
|
||||
*/
|
||||
public Path getMybatisGeneratorFilePath() {
|
||||
Path p = Paths.get(mybatisGeneratorFile != null ? mybatisGeneratorFile : "data/mybatis-generator.properties");
|
||||
if (p.isAbsolute()) {
|
||||
return p;
|
||||
}
|
||||
return Paths.get(System.getProperty("user.dir")).resolve(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* 确保所有数据文件存在于 user.dir 同级 data/ 目录。
|
||||
* 启动时统一检查:不存在则从 classpath:templates/ 下复制模板。
|
||||
* 这是所有运行时数据文件的唯一入口。
|
||||
*/
|
||||
private void ensureAllDataFilesExist() {
|
||||
ensureDataFile(getWorkutilsConfigFilePath(), "templates/workutils.config", "外部配置文件");
|
||||
ensureDataFile(getDatasourcesFilePath(), "templates/datasources.json", "数据源配置");
|
||||
ensureDataFile(getProjectPathsFilePath(), "templates/project_paths.txt", "项目路径文件");
|
||||
ensureDataFile(getDamagedReposFilePath(), "templates/damaged_repos.cache", "损坏缓存文件");
|
||||
ensureDataFile(getMybatisGeneratorFilePath(), "templates/mybatis-generator.properties", "MyBatis生成器配置");
|
||||
}
|
||||
|
||||
private void ensureDataFile(Path target, String classpathResource, String label) {
|
||||
try {
|
||||
|
||||
@@ -10,6 +10,9 @@ workutils:
|
||||
# data file paths (relative -> under user.dir/data/, absolute -> as-is)
|
||||
project-paths-file: "data/project_paths.txt"
|
||||
damaged-repos-file: "data/damaged_repos.cache"
|
||||
datasources-file: "data/datasources.json"
|
||||
workutils-config-file: "data/workutils.config"
|
||||
mybatis-generator-file: "data/mybatis-generator.properties"
|
||||
|
||||
logging:
|
||||
charset:
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
db_driver=com.mysql.jdbc.Driver
|
||||
db_url=jdbc:mysql://localhost:3306/disburse?useUnicode=true&characterEncoding=utf8&useSSL=false
|
||||
db_username=root
|
||||
db_password=1Qaz@4772
|
||||
|
||||
model_package=model
|
||||
model_target_project=./generator
|
||||
sqlmapper_package=mapperxml
|
||||
sqlmapper_target_project=./generator
|
||||
dao_package=mapper
|
||||
dao_target_project=./generator
|
||||
@@ -1,3 +1,70 @@
|
||||
# 项目路径配置文件
|
||||
# 格式: 本地路径=Git仓库URL(每行一个项目)
|
||||
# 示例: D:/workspace/my-project=https://user@code.example.com/org/repo.git
|
||||
D:/bestpay-srdcloud/ft-compensatory-core=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/ft-creative-prod=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/ft-credit-prod=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/ft-customer-core=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/ft-file-core=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/ft-finflux-gw-adapter=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/ft-lending-management-core=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/ft-loancapital-core=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/ft-loan-core=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/ft-organmng-core=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/ft-orgsupport-weixin=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/ft-protocol-core=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/ft-repay-core=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/ft-risk-control-core=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/ft-settlement-core=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/ft-wechatstage-prod=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-agent-admin=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-batch-creditpayment=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-batch-creditpayment-plus=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-blockchain-prod=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-boss=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-clrstl-fee-core=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-clrstl-report-core=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-codeutils=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-collateral-core=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-commodity-core=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-commonservice=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-consumestage-core=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-consumestage-mall=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-credit-bizfront=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-credit-bizfront-plus=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-credit-front=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-credit-prod=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-credit-prod-manage=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-creditstagescore=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-credituse-core=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-ctcorp-core=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-customer-core=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-file-core=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-govent-prod=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-grant-core=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-info-collection=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-instalment-admin=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-instalment-batch=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-invoice-core=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-lending-management-core=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-loancapital-core=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-marketing-manage=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-marketing-manage-plus=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-onlinestage-prod=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-organmng-core=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-precredit-core=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-productcfg-core-plus=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-protocol-core=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-risktool=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-scheduler=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-search=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-settlement-core=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-thirdpartybiz-prod=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-trade-core=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-wechatstage-prod=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/ft-approval-core=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/ft-asset-core=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/ft-blockchain-prod=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/ft-collateral-core=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/ft-commodity-core=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/ft-commonservice=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
@@ -0,0 +1,28 @@
|
||||
# ====== workutils 外部配置文件 ======
|
||||
# 编辑后通过「系统设置 > 重新加载」生效,无需重启
|
||||
|
||||
# ===== 系统路径 =====
|
||||
base-directory=
|
||||
export-directory=
|
||||
|
||||
# ===== 数据文件路径(相对于 user.dir)=====
|
||||
project-paths-file=data/project_paths.txt
|
||||
damaged-repos-file=data/damaged_repos.cache
|
||||
|
||||
# ===== MyBatis 数据库连接(覆盖内置值)=====
|
||||
mybatis.db.driver=
|
||||
mybatis.db.url=
|
||||
mybatis.db.username=
|
||||
mybatis.db.password=
|
||||
|
||||
# ===== MyBatis 代码生成包路径 =====
|
||||
mybatis.model.package=
|
||||
mybatis.dao.package=
|
||||
mybatis.sqlmapper.package=
|
||||
|
||||
# ===== 字体大小(显示设置)=====
|
||||
font.size.section-title=20
|
||||
font.size.field-label=18
|
||||
font.size.button=18
|
||||
font.size.body=18
|
||||
font.size.mono=18
|
||||
Reference in New Issue
Block a user