Java实现配置管理案例

wen java案例 1

本文目录导读:

Java实现配置管理案例

  1. 基础配置实体类
  2. 核心配置管理器
  3. 配置源接口和实现
  4. 配置缓存实现
  5. 使用示例
  6. 高级应用:注解驱动的配置绑定
  7. 配置文件示例 (application.properties)
  8. Maven依赖 (pom.xml)
  9. 关键特性说明

我来为您提供一个完整的Java配置管理案例,包含多种常见场景和最佳实践。

基础配置实体类

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.Properties;
import java.io.InputStream;
import java.io.IOException;
/**
 * 配置项实体类
 */
public class ConfigItem {
    private String key;
    private String value;
    private String description;
    private String group;
    private boolean isSensitive;
    private String dataType; // string, int, boolean, double, json
    public ConfigItem() {}
    public ConfigItem(String key, String value, String description, 
                     String group, boolean isSensitive, String dataType) {
        this.key = key;
        this.value = value;
        this.description = description;
        this.group = group;
        this.isSensitive = isSensitive;
        this.dataType = dataType;
    }
    // Getters and Setters
    public String getKey() { return key; }
    public void setKey(String key) { this.key = key; }
    public String getValue() { return value; }
    public void setValue(String value) { this.value = value; }
    public String getDescription() { return description; }
    public void setDescription(String description) { this.description = description; }
    public String getGroup() { return group; }
    public void setGroup(String group) { this.group = group; }
    public boolean isSensitive() { return isSensitive; }
    public void setSensitive(boolean sensitive) { isSensitive = sensitive; }
    public String getDataType() { return dataType; }
    public void setDataType(String dataType) { this.dataType = dataType; }
}

核心配置管理器

import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
/**
 * 配置管理器 - 支持热更新、监听、缓存
 */
public class ConfigManager {
    private static volatile ConfigManager instance;
    // 配置存储
    private final Map<String, ConfigItem> configs = new ConcurrentHashMap<>();
    // 配置变更监听器
    private final Map<String, List<Consumer<ConfigItem>>> listeners = new ConcurrentHashMap<>();
    // 全局监听器
    private final List<Consumer<String>> globalListeners = new ArrayList<>();
    // 配置来源
    private ConfigSource source;
    // 缓存管理
    private final ConfigCache cache;
    // 刷新锁
    private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
    // 初始化状态
    private final AtomicBoolean initialized = new AtomicBoolean(false);
    // 定期刷新调度器
    private ScheduledExecutorService scheduler;
    private ScheduledFuture<?> refreshTask;
    private ConfigManager() {
        this.cache = new ConfigCache(1000); // 默认缓存1秒
        initScheduler();
    }
    public static ConfigManager getInstance() {
        if (instance == null) {
            synchronized (ConfigManager.class) {
                if (instance == null) {
                    instance = new ConfigManager();
                }
            }
        }
        return instance;
    }
    /**
     * 初始化配置源
     */
    public void init(ConfigSource source) {
        this.source = source;
        loadAllConfigs();
        initialized.set(true);
    }
    /**
     * 加载所有配置
     */
    private void loadAllConfigs() {
        if (source == null) return;
        lock.writeLock().lock();
        try {
            Map<String, ConfigItem> loadedConfigs = source.loadAllConfigs();
            if (loadedConfigs != null) {
                // 对比旧配置,找出变化
                detectChanges(configs, loadedConfigs);
                configs.clear();
                configs.putAll(loadedConfigs);
            }
        } finally {
            lock.writeLock().unlock();
        }
    }
    /**
     * 检测配置变更并通知
     */
    private void detectChanges(Map<String, ConfigItem> oldConfigs, 
                               Map<String, ConfigItem> newConfigs) {
        if (oldConfigs.isEmpty()) return;
        // 检查更新和删除
        for (Map.Entry<String, ConfigItem> entry : oldConfigs.entrySet()) {
            String key = entry.getKey();
            ConfigItem newItem = newConfigs.get(key);
            if (newItem == null) {
                // 配置被删除
                notifyListeners(key, null);
            } else if (!Objects.equals(entry.getValue().getValue(), newItem.getValue())) {
                // 配置值变更
                notifyListeners(key, newItem);
            }
        }
        // 检查新增
        for (String key : newConfigs.keySet()) {
            if (!oldConfigs.containsKey(key)) {
                notifyListeners(key, newConfigs.get(key));
            }
        }
    }
    /**
     * 获取配置(带缓存)
     */
    public String getConfig(String key) {
        return getConfig(key, null);
    }
    /**
     * 获取配置(带默认值)
     */
    public String getConfig(String key, String defaultValue) {
        lock.readLock().lock();
        try {
            // 尝试从缓存获取
            Object cached = cache.get(key);
            if (cached != null) {
                return (String) cached;
            }
            // 从配置存储获取
            ConfigItem item = configs.get(key);
            String value = item != null ? item.getValue() : defaultValue;
            // 缓存结果
            cache.put(key, value);
            return value;
        } finally {
            lock.readLock().unlock();
        }
    }
    /**
     * 获取带类型的配置
     */
    public int getInt(String key, int defaultValue) {
        String value = getConfig(key);
        if (value == null) return defaultValue;
        try {
            return Integer.parseInt(value);
        } catch (NumberFormatException e) {
            return defaultValue;
        }
    }
    public boolean getBoolean(String key, boolean defaultValue) {
        String value = getConfig(key);
        if (value == null) return defaultValue;
        return Boolean.parseBoolean(value);
    }
    public double getDouble(String key, double defaultValue) {
        String value = getConfig(key);
        if (value == null) return defaultValue;
        try {
            return Double.parseDouble(value);
        } catch (NumberFormatException e) {
            return defaultValue;
        }
    }
    /**
     * 设置配置(并通知变更)
     */
    public void setConfig(String key, String value) {
        setConfig(key, value, true);
    }
    /**
     * 设置配置
     */
    public void setConfig(String key, String value, boolean notifyChange) {
        lock.writeLock().lock();
        try {
            ConfigItem oldItem = configs.get(key);
            if (oldItem == null) {
                // 新增配置
                ConfigItem newItem = new ConfigItem(key, value, "", "default", false, "string");
                configs.put(key, newItem);
                if (notifyChange) {
                    notifyListeners(key, newItem);
                }
            } else {
                // 更新配置
                oldItem.setValue(value);
                oldItem.setDataType(detectDataType(value));
                // 更新到配置源
                if (source != null) {
                    source.updateConfig(key, value);
                }
                if (notifyChange) {
                    notifyListeners(key, oldItem);
                }
            }
            // 更新缓存
            cache.put(key, value);
        } finally {
            lock.writeLock().unlock();
        }
    }
    /**
     * 批量设置配置
     */
    public void setConfigs(Map<String, String> configMap) {
        lock.writeLock().lock();
        try {
            for (Map.Entry<String, String> entry : configMap.entrySet()) {
                setConfig(entry.getKey(), entry.getValue(), false);
            }
            // 触发全局变更通知
            notifyGlobalListeners("batch_update");
        } finally {
            lock.writeLock().unlock();
        }
    }
    /**
     * 注册配置监听器
     */
    public void registerListener(String key, Consumer<ConfigItem> listener) {
        listeners.computeIfAbsent(key, k -> new CopyOnWriteArrayList<>())
                 .add(listener);
    }
    /**
     * 注册全局监听器
     */
    public void registerGlobalListener(Consumer<String> listener) {
        globalListeners.add(listener);
    }
    /**
     * 通知指定配置的监听器
     */
    private void notifyListeners(String key, ConfigItem item) {
        // 通知指定key的监听器
        List<Consumer<ConfigItem>> keyListeners = listeners.get(key);
        if (keyListeners != null) {
            for (Consumer<ConfigItem> listener : keyListeners) {
                try {
                    listener.accept(item);
                } catch (Exception e) {
                    // 异常处理
                }
            }
        }
        // 通知全局监听器
        notifyGlobalListeners(key);
    }
    /**
     * 通知全局监听器
     */
    private void notifyGlobalListeners(String key) {
        for (Consumer<String> listener : globalListeners) {
            try {
                listener.accept(key);
            } catch (Exception e) {
                // 异常处理
            }
        }
    }
    /**
     * 刷新配置
     */
    public void refresh() {
        if (source != null) {
            loadAllConfigs();
        }
    }
    /**
     * 定时刷新
     */
    public void scheduleRefresh(long interval, TimeUnit unit) {
        if (refreshTask != null) {
            refreshTask.cancel(false);
        }
        refreshTask = scheduler.scheduleAtFixedRate(() -> {
            try {
                refresh();
            } catch (Exception e) {
                // 刷新失败日志
            }
        }, interval, interval, unit);
    }
    /**
     * 初始化调度器
     */
    private void initScheduler() {
        scheduler = Executors.newSingleThreadScheduledExecutor(r -> {
            Thread t = new Thread(r, "config-refresh-scheduler");
            t.setDaemon(true);
            return t;
        });
    }
    /**
     * 检测数据类型
     */
    private String detectDataType(String value) {
        if (value == null) return "string";
        try {
            Integer.parseInt(value);
            return "int";
        } catch (NumberFormatException e) {
            // Not an int
        }
        try {
            Double.parseDouble(value);
            return "double";
        } catch (NumberFormatException e) {
            // Not a double
        }
        if (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("false")) {
            return "boolean";
        }
        // JSON检查
        if (value.trim().startsWith("{") || value.trim().startsWith("[")) {
            return "json";
        }
        return "string";
    }
    /**
     * 获取所有配置
     */
    public Map<String, ConfigItem> getAllConfigs() {
        lock.readLock().lock();
        try {
            return new HashMap<>(configs);
        } finally {
            lock.readLock().unlock();
        }
    }
    /**
     * 删除配置
     */
    public void removeConfig(String key) {
        lock.writeLock().lock();
        try {
            configs.remove(key);
            cache.remove(key);
            // 通知监听器
            notifyListeners(key, null);
            // 从配置源删除
            if (source != null) {
                source.deleteConfig(key);
            }
        } finally {
            lock.writeLock().unlock();
        }
    }
    /**
     * 关闭配置管理器
     */
    public void shutdown() {
        if (refreshTask != null) {
            refreshTask.cancel(true);
        }
        scheduler.shutdown();
        if (source != null) {
            source.close();
        }
    }
}

配置源接口和实现

import java.util.Map;
/**
 * 配置源接口
 */
public interface ConfigSource {
    Map<String, ConfigItem> loadAllConfigs();
    void updateConfig(String key, String value);
    void deleteConfig(String key);
    void close();
}
/**
 * 基于Properties文件的配置源
 */
public class PropertiesConfigSource implements ConfigSource {
    private final String filePath;
    private final Properties properties = new Properties();
    public PropertiesConfigSource(String filePath) {
        this.filePath = filePath;
        loadProperties();
    }
    private void loadProperties() {
        try (InputStream input = getClass().getClassLoader()
                .getResourceAsStream(filePath)) {
            if (input != null) {
                properties.load(input);
            }
        } catch (IOException e) {
            throw new RuntimeException("Failed to load properties file: " + filePath, e);
        }
    }
    @Override
    public Map<String, ConfigItem> loadAllConfigs() {
        Map<String, ConfigItem> configMap = new HashMap<>();
        for (String key : properties.stringPropertyNames()) {
            ConfigItem item = new ConfigItem();
            item.setKey(key);
            item.setValue(properties.getProperty(key));
            item.setGroup("properties");
            configMap.put(key, item);
        }
        return configMap;
    }
    @Override
    public void updateConfig(String key, String value) {
        properties.setProperty(key, value);
        saveToFile();
    }
    @Override
    public void deleteConfig(String key) {
        properties.remove(key);
        saveToFile();
    }
    private void saveToFile() {
        // 保存到文件
        try (OutputStream output = new FileOutputStream(filePath)) {
            properties.store(output, "Config Updated at " + new Date());
        } catch (IOException e) {
            // 处理异常
        }
    }
    @Override
    public void close() {
        // 清理资源
    }
}
/**
 * 基于数据库的配置源
 */
public class DatabaseConfigSource implements ConfigSource {
    private final DataSource dataSource;
    public DatabaseConfigSource(DataSource dataSource) {
        this.dataSource = dataSource;
    }
    @Override
    public Map<String, ConfigItem> loadAllConfigs() {
        Map<String, ConfigItem> configMap = new HashMap<>();
        String sql = "SELECT `key`, `value`, `description`, `group_name`, " +
                    "`is_sensitive`, `data_type` FROM configs";
        try (Connection conn = dataSource.getConnection();
             PreparedStatement ps = conn.prepareStatement(sql);
             ResultSet rs = ps.executeQuery()) {
            while (rs.next()) {
                ConfigItem item = new ConfigItem(
                    rs.getString("key"),
                    rs.getString("value"),
                    rs.getString("description"),
                    rs.getString("group_name"),
                    rs.getBoolean("is_sensitive"),
                    rs.getString("data_type")
                );
                configMap.put(item.getKey(), item);
            }
        } catch (SQLException e) {
            throw new RuntimeException("Failed to load configs from database", e);
        }
        return configMap;
    }
    @Override
    public void updateConfig(String key, String value) {
        String sql = "UPDATE configs SET value = ? WHERE `key` = ?";
        try (Connection conn = dataSource.getConnection();
             PreparedStatement ps = conn.prepareStatement(sql)) {
            ps.setString(1, value);
            ps.setString(2, key);
            ps.executeUpdate();
        } catch (SQLException e) {
            throw new RuntimeException("Failed to update config", e);
        }
    }
    @Override
    public void deleteConfig(String key) {
        String sql = "DELETE FROM configs WHERE `key` = ?";
        try (Connection conn = dataSource.getConnection();
             PreparedStatement ps = conn.prepareStatement(sql)) {
            ps.setString(1, key);
            ps.executeUpdate();
        } catch (SQLException e) {
            throw new RuntimeException("Failed to delete config", e);
        }
    }
    @Override
    public void close() {
        // 清理资源
    }
}

配置缓存实现

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
/**
 * 配置缓存
 */
public class ConfigCache {
    private final long defaultTtl;
    private final Map<String, CacheEntry> cacheMap = new ConcurrentHashMap<>();
    private static class CacheEntry {
        private final Object value;
        private final long expireTime;
        CacheEntry(Object value, long expireTime) {
            this.value = value;
            this.expireTime = expireTime;
        }
        boolean isExpired() {
            return System.currentTimeMillis() > expireTime;
        }
    }
    public ConfigCache(long defaultTtlMillis) {
        this.defaultTtl = defaultTtlMillis;
    }
    public void put(String key, Object value) {
        put(key, value, defaultTtl);
    }
    public void put(String key, Object value, long ttlMillis) {
        long expireTime = System.currentTimeMillis() + ttlMillis;
        cacheMap.put(key, new CacheEntry(value, expireTime));
    }
    public Object get(String key) {
        CacheEntry entry = cacheMap.get(key);
        if (entry == null) return null;
        if (entry.isExpired()) {
            cacheMap.remove(key);
            return null;
        }
        return entry.value;
    }
    public void remove(String key) {
        cacheMap.remove(key);
    }
    public void clear() {
        cacheMap.clear();
    }
    public int size() {
        return cacheMap.size();
    }
}

使用示例

/**
 * 配置管理示例代码
 */
public class ConfigExample {
    public static void main(String[] args) throws InterruptedException {
        // 1. 初始化配置管理器
        ConfigManager configManager = ConfigManager.getInstance();
        // 2. 配置数据源(这里使用properties文件)
        PropertiesConfigSource source = new PropertiesConfigSource("application.properties");
        configManager.init(source);
        // 3. 添加配置监听器
        configManager.registerListener("app.name", (configItem) -> {
            System.out.println("App name changed to: " + configItem.getValue());
        });
        configManager.registerGlobalListener((key) -> {
            System.out.println("Config changed: " + key);
        });
        // 4. 读取配置
        String appName = configManager.getConfig("app.name", "MyApp");
        int port = configManager.getInt("server.port", 8080);
        boolean debug = configManager.getBoolean("app.debug", false);
        System.out.println("App Name: " + appName);
        System.out.println("Port: " + port);
        System.out.println("Debug: " + debug);
        // 5. 批量设置配置
        Map<String, String> newConfigs = new HashMap<>();
        newConfigs.put("server.host", "localhost");
        newConfigs.put("server.timeout", "5000");
        newConfigs.put("database.poolSize", "20");
        configManager.setConfigs(newConfigs);
        // 6. 定时刷新配置(每10秒刷新一次)
        configManager.scheduleRefresh(10, TimeUnit.SECONDS);
        // 7. 模拟运行一段时间
        Thread.sleep(30000);
        // 8. 关闭配置管理器
        configManager.shutdown();
    }
}

高级应用:注解驱动的配置绑定

import java.lang.annotation.*;
import java.lang.reflect.Field;
/**
 * 配置注解
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ConfigValue {
    String key();
    String defaultValue() default "";
}
/**
 * 配置绑定器
 */
public class ConfigBinder {
    public static <T> T bind(T target, ConfigManager configManager) {
        Class<?> clazz = target.getClass();
        for (Field field : clazz.getDeclaredFields()) {
            if (field.isAnnotationPresent(ConfigValue.class)) {
                ConfigValue annotation = field.getAnnotation(ConfigValue.class);
                String value = configManager.getConfig(annotation.key(), 
                                                       annotation.defaultValue());
                field.setAccessible(true);
                try {
                    field.set(target, convertValue(value, field.getType()));
                } catch (IllegalAccessException e) {
                    // 处理异常
                }
            }
        }
        return target;
    }
    private static Object convertValue(String value, Class<?> type) {
        if (type == String.class) {
            return value;
        } else if (type == int.class || type == Integer.class) {
            return Integer.parseInt(value);
        } else if (type == boolean.class || type == Boolean.class) {
            return Boolean.parseBoolean(value);
        } else if (type == double.class || type == Double.class) {
            return Double.parseDouble(value);
        } else if (type == long.class || type == Long.class) {
            return Long.parseLong(value);
        }
        return value;
    }
}
/**
 * 配置绑定示例
 */
public class AppConfig {
    @ConfigValue(key = "app.name", defaultValue = "MyApp")
    private String appName;
    @ConfigValue(key = "server.port", defaultValue = "8080")
    private int port;
    @ConfigValue(key = "app.debug", defaultValue = "false")
    private boolean debug;
    // Getters
    public String getAppName() { return appName; }
    public int getPort() { return port; }
    public boolean isDebug() { return debug; }
    public static void main(String[] args) {
        ConfigManager configManager = ConfigManager.getInstance();
        // 设置一些配置
        configManager.setConfig("app.name", "TestApp");
        configManager.setConfig("server.port", "9090");
        configManager.setConfig("app.debug", "true");
        // 绑定配置到对象
        AppConfig appConfig = ConfigBinder.bind(new AppConfig(), configManager);
        System.out.println("App Name: " + appConfig.getAppName());
        System.out.println("Port: " + appConfig.getPort());
        System.out.println("Debug: " + appConfig.isDebug());
    }
}

配置文件示例 (application.properties)

# 应用配置
app.name=MyApplication
app.version=1.0.0
app.debug=false
app.environment=development
app.timezone=Asia/Shanghai
# 服务器配置
server.host=0.0.0.0
server.port=8080
server.maxThreads=200
server.minSpareThreads=50
server.sessionTimeout=30m
server.compression.enabled=true
# 数据库配置
database.url=jdbc:mysql://localhost:3306/mydb
database.username=admin
database.password=secret
database.poolSize=20
database.maxConnection=100
database.connectionTimeout=3000
database.idleTimeout=60000
# 缓存配置
cache.type=redis
cache.host=localhost
cache.port=6379
cache.password=redis123
cache.ttl=3600
cache.maxMemory=256MB
# 日志配置
logging.level.root=INFO
logging.level.com.example=DEBUG
logging.file.name=application.log
logging.file.maxSize=10MB
logging.file.maxHistory=7
# 功能开关
feature.newUI.enabled=true
feature.advancedSearch.enabled=false
feature.cache.enabled=true
feature.rateLimit.enabled=false
# 第三方服务配置
sms.provider=aliyun
sms.accessKeyId=your-access-key
sms.accessKeySecret=your-secret-key
sms.signName=YourCompany
# 邮件服务配置
mail.smtp.host=smtp.example.com
mail.smtp.port=587
mail.smtp.username=user@example.com
mail.smtp.password=password
mail.from=no-reply@example.com

Maven依赖 (pom.xml)

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
         http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>config-management</artifactId>
    <version>1.0.0</version>
    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <dependencies>
        <!-- 数据库连接池 -->
        <dependency>
            <groupId>com.zaxxer</groupId>
            <artifactId>HikariCP</artifactId>
            <version>5.0.1</version>
        </dependency>
        <!-- MySQL驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.33</version>
        </dependency>
        <!-- SLF4J日志 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>2.0.9</version>
        </dependency>
        <!-- JSON处理 -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.15.2</version>
        </dependency>
        <!-- 单元测试 -->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>5.10.0</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

关键特性说明

  1. 单例模式:使用双重检查锁实现线程安全的单例
  2. 读写锁:使用ReentrantReadWriteLock保证并发安全
  3. 缓存机制:支持配置缓存,提高读取性能
  4. 监听器模式:支持配置变更监听和通知
  5. 热更新:支持定时刷新配置,无需重启应用
  6. 多数据源支持:支持Properties文件、数据库等不同配置源
  7. 类型转换:自动检测和转换配置值的类型
  8. 注解驱动:通过注解自动绑定配置到对象

这个配置管理案例提供了完整的实现,您可以按需扩展和调整。

抱歉,评论功能暂时关闭!