本文目录导读:

- 使用Spring Cloud Config(推荐)
- 使用Apache Commons Configuration
- 手动实现文件监听器
- 使用分布式配置中心
- 使用Spring Event + 定时刷新
- 完整示例:文件系统监听器
- 最佳实践建议
在Java中实现配置热加载,主要目的是在不重启应用的情况下动态更新配置,以下是几种常见的实现方案,从简单到复杂:
使用Spring Cloud Config(推荐)
依赖配置
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
配置类示例
@RefreshScope
@Component
@ConfigurationProperties(prefix = "app.config")
public class AppConfig {
private String name;
private int timeout;
private List<String> allowedUrls;
// getter/setter
}
@RestController
public class ConfigController {
@Autowired
private AppConfig appConfig;
@GetMapping("/config")
public AppConfig getConfig() {
return appConfig;
}
}
触发刷新
# 发送POST请求刷新配置 curl -X POST http://localhost:8080/actuator/refresh
使用Apache Commons Configuration
依赖
<dependency>
<groupId>commons-configuration</groupId>
<artifactId>commons-configuration</artifactId>
<version>1.10</version>
</dependency>
实现代码
import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy;
public class HotReloadConfig {
private static PropertiesConfiguration config;
public static void init() throws Exception {
config = new PropertiesConfiguration("app.properties");
// 设置热加载策略:5秒检查一次文件变化
FileChangedReloadingStrategy strategy = new FileChangedReloadingStrategy();
strategy.setRefreshDelay(5000);
config.setReloadingStrategy(strategy);
}
public static String getProperty(String key) {
return config.getString(key);
}
public static int getIntProperty(String key) {
return config.getInt(key);
}
}
手动实现文件监听器
使用Java NIO WatchService
import java.nio.file.*;
import java.util.concurrent.Executors;
public class ConfigFileWatcher {
private static final String CONFIG_FILE = "app.properties";
private static Properties configProps = new Properties();
public static void startWatching() throws Exception {
Path configPath = Paths.get(CONFIG_FILE);
WatchService watchService = FileSystems.getDefault().newWatchService();
configPath.getParent().register(watchService,
StandardWatchEventKinds.ENTRY_MODIFY);
Executors.newSingleThreadExecutor().submit(() -> {
while (true) {
WatchKey key = watchService.take();
for (WatchEvent<?> event : key.pollEvents()) {
if (event.context().toString().equals(CONFIG_FILE)) {
reloadConfig();
}
}
key.reset();
}
});
}
private static synchronized void reloadConfig() {
try (InputStream input = new FileInputStream(CONFIG_FILE)) {
configProps.load(input);
System.out.println("配置已热加载: " + new Date());
} catch (Exception e) {
e.printStackTrace();
}
}
public static String getConfig(String key) {
return configProps.getProperty(key);
}
}
使用分布式配置中心
Apollo配置中心示例
@Configuration
@EnableApolloConfig
public class AppConfig {
@Value("${app.timeout:1000}")
private int timeout;
// 监听配置变化
@ApolloConfigChangeListener
private void onChange(ConfigChangeEvent changeEvent) {
if (changeEvent.isChanged("app.timeout")) {
timeout = Integer.parseInt(changeEvent.getChange("app.timeout").getNewValue());
System.out.println("timeout已更新为: " + timeout);
}
}
}
使用Spring Event + 定时刷新
@Component
public class DynamicConfigService {
private Map<String, String> configMap = new HashMap<>();
@PostConstruct
public void init() {
loadConfig();
scheduleRefresh();
}
private void loadConfig() {
// 从数据库或文件加载配置
// ...
}
private void scheduleRefresh() {
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
this::loadConfig, 0, 10, TimeUnit.SECONDS);
}
@EventListener
public void handleRefreshEvent(RefreshEvent event) {
loadConfig();
}
}
完整示例:文件系统监听器
import java.io.*;
import java.nio.file.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.function.Consumer;
public class HotConfigLoader {
private final String configPath;
private final Map<String, String> config = new ConcurrentHashMap<>();
private final List<Consumer<Map<String, String>>> listeners = new CopyOnWriteArrayList<>();
public HotConfigLoader(String configPath) {
this.configPath = configPath;
loadConfig();
startWatch();
}
private void loadConfig() {
Properties props = new Properties();
try (InputStream input = new FileInputStream(configPath)) {
props.load(input);
config.clear();
props.forEach((k, v) -> config.put(k.toString(), v.toString()));
// 通知监听器
listeners.forEach(l -> l.accept(Collections.unmodifiableMap(config)));
} catch (IOException e) {
e.printStackTrace();
}
}
private void startWatch() {
Thread watcher = new Thread(() -> {
try {
Path path = Paths.get(configPath);
WatchService watchService = FileSystems.getDefault().newWatchService();
path.getParent().register(watchService, StandardWatchEventKinds.ENTRY_MODIFY);
while (true) {
WatchKey key = watchService.take();
for (WatchEvent<?> event : key.pollEvents()) {
if (event.context().toString().equals(path.getFileName().toString())) {
TimeUnit.SECONDS.sleep(1); // 等待文件写入完成
loadConfig();
System.out.println("配置文件已更新: " + new Date());
}
}
key.reset();
}
} catch (Exception e) {
e.printStackTrace();
}
});
watcher.setDaemon(true);
watcher.start();
}
public String get(String key) {
return config.get(key);
}
public void addListener(Consumer<Map<String, String>> listener) {
listeners.add(listener);
}
}
使用示例
public class Application {
public static void main(String[] args) {
HotConfigLoader config = new HotConfigLoader("app.properties");
// 添加监听器
config.addListener(newProps -> {
System.out.println("配置已更新: " + newProps.get("app.timeout"));
});
// 定时输出配置
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(() -> {
System.out.println("当前timeout: " + config.get("app.timeout"));
}, 0, 2, TimeUnit.SECONDS);
}
}
最佳实践建议
-
选择合适方案:
- 简单应用:手动文件监听器
- Spring项目:Spring Cloud Config + @RefreshScope
- 微服务架构:Apollo/Nacos等配置中心
-
注意事项:
- 确保线程安全
- 添加异常处理
- 考虑配置验证机制
- 做好版本控制
- 添加日志记录
-
性能优化:
- 使用原子操作更新配置
- 避免频繁读取配置
- 合理设置检查间隔
-
容错处理:
- 配置加载失败使用旧配置
- 配置变化通知事务处理
- 提供回退机制
选择哪种方案取决于你的具体场景、项目规模和团队技术栈,对于大多数Spring项目,使用Spring Cloud Config或配置中心是推荐方案。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播