feat: 新增config指令, 支持热更新配置信息.

This commit is contained in:
2025-01-23 16:13:52 +08:00
parent afa47c3ff3
commit 379f5c7032
8 changed files with 114 additions and 32 deletions

View File

@@ -9,6 +9,7 @@ import com.serliunx.ddns.core.context.MultipleSourceInstanceContext;
import com.serliunx.ddns.support.InstanceContextHolder; import com.serliunx.ddns.support.InstanceContextHolder;
import com.serliunx.ddns.support.SystemInitializer; import com.serliunx.ddns.support.SystemInitializer;
import com.serliunx.ddns.support.command.CommandDispatcher; import com.serliunx.ddns.support.command.CommandDispatcher;
import com.serliunx.ddns.support.command.target.ConfigCommand;
import com.serliunx.ddns.support.command.target.HelpCommand; import com.serliunx.ddns.support.command.target.HelpCommand;
import com.serliunx.ddns.support.command.target.ReloadCommand; import com.serliunx.ddns.support.command.target.ReloadCommand;
import com.serliunx.ddns.support.log.JLineAdaptAppender; import com.serliunx.ddns.support.log.JLineAdaptAppender;
@@ -120,6 +121,8 @@ public final class ManagerLite {
commandDispatcher.register(new HelpCommand()); commandDispatcher.register(new HelpCommand());
// reload // reload
commandDispatcher.register(new ReloadCommand(configuration, systemInitializer)); commandDispatcher.register(new ReloadCommand(configuration, systemInitializer));
// config
commandDispatcher.register(new ConfigCommand(configuration));
} }
/** /**

View File

@@ -21,7 +21,7 @@ public abstract class AbstractConfiguration implements Configuration {
protected final Logger log = LoggerFactory.getLogger(this.getClass()); protected final Logger log = LoggerFactory.getLogger(this.getClass());
protected final Map<String, String> valueMap = new LinkedHashMap<>(16); protected final Map<String, String> valueMap = new LinkedHashMap<>(16);
protected final Lock loadLock = new ReentrantLock(); protected final Lock contextLock = new ReentrantLock();
public AbstractConfiguration() {} public AbstractConfiguration() {}
@@ -111,6 +111,33 @@ public abstract class AbstractConfiguration implements Configuration {
return valueMap; return valueMap;
} }
@Override
public boolean modify(String key, Object value) {
try {
contextLock.lock();
if (!valueMap.containsKey(key))
return false;
valueMap.put(key, String.valueOf(value));
return true;
} finally {
contextLock.unlock();
}
}
@Override
public void modify(String key, Object value, boolean createIfAbsent) {
try {
contextLock.lock();
if (!valueMap.containsKey(key)) {
if (createIfAbsent)
valueMap.put(key, String.valueOf(value));
} else
valueMap.put(key, String.valueOf(value));
} finally {
contextLock.unlock();
}
}
@Override @Override
public int getPriority() { public int getPriority() {
return Integer.MAX_VALUE; return Integer.MAX_VALUE;
@@ -121,12 +148,12 @@ public abstract class AbstractConfiguration implements Configuration {
*/ */
protected void load() { protected void load() {
try { try {
loadLock.lock(); contextLock.lock();
// 清空原有的配置信息 // 清空原有的配置信息
valueMap.clear(); valueMap.clear();
load0(); load0();
}finally { }finally {
loadLock.unlock(); contextLock.unlock();
} }
} }

View File

@@ -100,4 +100,23 @@ public interface Configuration extends Refreshable, Priority {
* @return 配置文件所有成功加载的键值对 * @return 配置文件所有成功加载的键值对
*/ */
Map<String, String> getAllKeyAndValue(); Map<String, String> getAllKeyAndValue();
/**
* 修改配置项(锁)
*
* @param key 配置键
* @param value 新的值
* @return 成功修改返回真, 否则返回假; 指定键不存在时则修改失败
*/
boolean modify(String key, Object value);
/**
* 修改配置项(锁)
* <li> 指定配置键不存在时则会根绝是否需要创建而新增
*
* @param key 配置键
* @param value 新的值
* @param createIfAbsent 是否在不存在指定键时创建
*/
void modify(String key, Object value, boolean createIfAbsent);
} }

View File

@@ -1,5 +1,8 @@
package com.serliunx.ddns.support.command; package com.serliunx.ddns.support.command;
import com.serliunx.ddns.ManagerLite;
import org.slf4j.Logger;
import java.util.List; import java.util.List;
/** /**
@@ -17,6 +20,8 @@ public abstract class AbstractCommand implements Command {
private final String description; private final String description;
private final String usage; private final String usage;
protected final Logger log = ManagerLite.getLogger();
public AbstractCommand(String name, List<Command> subCommands, String description, String usage) { public AbstractCommand(String name, List<Command> subCommands, String description, String usage) {
this.name = name; this.name = name;
this.subCommands = subCommands; this.subCommands = subCommands;
@@ -43,4 +48,8 @@ public abstract class AbstractCommand implements Command {
public String getUsage() { public String getUsage() {
return usage; return usage;
} }
protected boolean hasArgs(String[] args) {
return args.length > 0;
}
} }

View File

@@ -91,16 +91,6 @@ public final class CommandDispatcher {
return newArgs; return newArgs;
} }
/**
* 检查是否存在参数
*
* @param args 参数
* @return 参数长度大于0返回真, 否则返回假
*/
public static boolean hasArgs(String[] args) {
return args.length > 0;
}
/** /**
* 获取实例 * 获取实例
*/ */

View File

@@ -0,0 +1,36 @@
package com.serliunx.ddns.support.command.target;
import com.serliunx.ddns.config.Configuration;
import com.serliunx.ddns.support.command.AbstractCommand;
/**
* 指令: config
*
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
* @version 1.0.4
* @since 2025/1/22
*/
public class ConfigCommand extends AbstractCommand {
/**
* 配置信息
*/
private final Configuration configuration;
public ConfigCommand(Configuration configuration) {
super("config", null, "调整配置信息", "config <配置项> 新的值");
this.configuration = configuration;
}
@Override
public boolean onCommand(String[] args) {
if (!hasArgs(args) ||
args.length < 2) {
log.warn("用法 => {}", getUsage());
return true;
}
final String target = args[0];
final String value = args[1];
return configuration.modify(target, value);
}
}

View File

@@ -1,15 +1,11 @@
package com.serliunx.ddns.support.command.target; package com.serliunx.ddns.support.command.target;
import com.serliunx.ddns.ManagerLite;
import com.serliunx.ddns.support.command.AbstractCommand; import com.serliunx.ddns.support.command.AbstractCommand;
import com.serliunx.ddns.support.command.Command; import com.serliunx.ddns.support.command.Command;
import com.serliunx.ddns.support.command.CommandDispatcher; import com.serliunx.ddns.support.command.CommandDispatcher;
import org.slf4j.Logger;
import java.util.Map; import java.util.Map;
import static com.serliunx.ddns.support.command.CommandDispatcher.hasArgs;
/** /**
* 指令: help * 指令: help
* *
@@ -19,8 +15,6 @@ import static com.serliunx.ddns.support.command.CommandDispatcher.hasArgs;
*/ */
public class HelpCommand extends AbstractCommand { public class HelpCommand extends AbstractCommand {
private static final Logger log = ManagerLite.getLogger();
public HelpCommand() { public HelpCommand() {
super("help", null, "查看帮助信息", "help <指令>"); super("help", null, "查看帮助信息", "help <指令>");
} }

View File

@@ -1,13 +1,9 @@
package com.serliunx.ddns.support.command.target; package com.serliunx.ddns.support.command.target;
import com.serliunx.ddns.ManagerLite;
import com.serliunx.ddns.config.Configuration; import com.serliunx.ddns.config.Configuration;
import com.serliunx.ddns.support.SystemInitializer; import com.serliunx.ddns.support.SystemInitializer;
import com.serliunx.ddns.support.command.AbstractCommand; import com.serliunx.ddns.support.command.AbstractCommand;
import com.serliunx.ddns.support.ipprovider.ScheduledProvider; import com.serliunx.ddns.support.ipprovider.ScheduledProvider;
import org.slf4j.Logger;
import java.util.Objects;
import static com.serliunx.ddns.constant.ConfigurationKeys.KEY_TASK_REFRESH_INTERVAL_IP; import static com.serliunx.ddns.constant.ConfigurationKeys.KEY_TASK_REFRESH_INTERVAL_IP;
@@ -20,8 +16,6 @@ import static com.serliunx.ddns.constant.ConfigurationKeys.KEY_TASK_REFRESH_INTE
*/ */
public class ReloadCommand extends AbstractCommand { public class ReloadCommand extends AbstractCommand {
private static final Logger log = ManagerLite.getLogger();
/** /**
* 配置信息 * 配置信息
*/ */
@@ -47,18 +41,28 @@ public class ReloadCommand extends AbstractCommand {
configuration.refresh(); configuration.refresh();
// 更新定时查询IP任务 // 更新定时查询IP任务
triggerScheduledProvider(oldIpInterval);
log.info("配置文件已重新载入!");
return true;
}
/**
* 获取更新周期
*/
private long getIpInterval() {
return configuration.getLong(KEY_TASK_REFRESH_INTERVAL_IP, 300L);
}
/**
* 更新定时查询IP任务
*/
private void triggerScheduledProvider(long oldIpInterval) {
final ScheduledProvider scheduledProvider = systemInitializer.getScheduledProvider(); final ScheduledProvider scheduledProvider = systemInitializer.getScheduledProvider();
final long newIpInterval = getIpInterval(); final long newIpInterval = getIpInterval();
if (scheduledProvider != null && if (scheduledProvider != null &&
oldIpInterval != newIpInterval) { oldIpInterval != newIpInterval) {
scheduledProvider.changeTimePeriod(newIpInterval); scheduledProvider.changeTimePeriod(newIpInterval);
} }
log.info("配置文件已重新载入!");
return true;
}
private long getIpInterval() {
return configuration.getLong(KEY_TASK_REFRESH_INTERVAL_IP, 300L);
} }
} }