feat: 新增指令调度器.
This commit is contained in:
@@ -6,13 +6,18 @@ import com.serliunx.ddns.config.PropertiesConfiguration;
|
|||||||
import com.serliunx.ddns.constant.SystemConstants;
|
import com.serliunx.ddns.constant.SystemConstants;
|
||||||
import com.serliunx.ddns.core.context.FileInstanceContext;
|
import com.serliunx.ddns.core.context.FileInstanceContext;
|
||||||
import com.serliunx.ddns.core.context.MultipleSourceInstanceContext;
|
import com.serliunx.ddns.core.context.MultipleSourceInstanceContext;
|
||||||
|
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.target.HelpCommand;
|
||||||
import com.serliunx.ddns.support.log.JLineAdaptAppender;
|
import com.serliunx.ddns.support.log.JLineAdaptAppender;
|
||||||
import org.jline.reader.LineReader;
|
import org.jline.reader.LineReader;
|
||||||
import org.jline.reader.LineReaderBuilder;
|
import org.jline.reader.LineReaderBuilder;
|
||||||
import org.jline.reader.impl.history.DefaultHistory;
|
import org.jline.reader.impl.history.DefaultHistory;
|
||||||
import org.jline.terminal.Terminal;
|
import org.jline.terminal.Terminal;
|
||||||
import org.jline.terminal.TerminalBuilder;
|
import org.jline.terminal.TerminalBuilder;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
@@ -25,6 +30,11 @@ import java.io.IOException;
|
|||||||
*/
|
*/
|
||||||
public final class ManagerLite {
|
public final class ManagerLite {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认的日志输出
|
||||||
|
*/
|
||||||
|
private static final Logger DEFAULT_LOGGER = LoggerFactory.getLogger(ManagerLite.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 配置信息
|
* 配置信息
|
||||||
*/
|
*/
|
||||||
@@ -37,9 +47,19 @@ public final class ManagerLite {
|
|||||||
* 系统初始化器
|
* 系统初始化器
|
||||||
*/
|
*/
|
||||||
private static SystemInitializer systemInitializer;
|
private static SystemInitializer systemInitializer;
|
||||||
|
/**
|
||||||
|
* 指令调度
|
||||||
|
*/
|
||||||
|
private static CommandDispatcher commandDispatcher;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取默认的日志输出
|
||||||
|
*/
|
||||||
|
public static Logger getLogger() {
|
||||||
|
return DEFAULT_LOGGER;
|
||||||
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
|
|
||||||
// 配置初始化
|
// 配置初始化
|
||||||
initConfiguration(args);
|
initConfiguration(args);
|
||||||
|
|
||||||
@@ -49,6 +69,9 @@ public final class ManagerLite {
|
|||||||
// 系统初始化
|
// 系统初始化
|
||||||
initSystem();
|
initSystem();
|
||||||
|
|
||||||
|
// 指令初始化
|
||||||
|
initCommands();
|
||||||
|
|
||||||
Terminal terminal;
|
Terminal terminal;
|
||||||
try {
|
try {
|
||||||
terminal = TerminalBuilder.builder()
|
terminal = TerminalBuilder.builder()
|
||||||
@@ -67,30 +90,35 @@ public final class ManagerLite {
|
|||||||
|
|
||||||
JLineAdaptAppender.setLineReader(lineReader);
|
JLineAdaptAppender.setLineReader(lineReader);
|
||||||
|
|
||||||
String prompt = "client> ";
|
final String prompt = "client> ";
|
||||||
|
|
||||||
|
InstanceContextHolder.setAdditional("command-process");
|
||||||
while (true) {
|
while (true) {
|
||||||
// 该方法会阻塞,直到用户敲回车
|
// 该方法会阻塞,直到用户敲回车
|
||||||
try {
|
try {
|
||||||
String cmd = lineReader.readLine(prompt);
|
String cmd = lineReader.readLine(prompt);
|
||||||
|
|
||||||
// 当用户输入 exit 或 quit,就退出循环
|
// 当用户输入 exit,就退出循环
|
||||||
if ("exit".equalsIgnoreCase(cmd)) {
|
if ("exit".equalsIgnoreCase(cmd)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// 在这里可以对用户输入做进一步处理
|
commandDispatcher.onCommand(cmd);
|
||||||
terminal.flush();
|
terminal.flush();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
System.exit(0);
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
|
||||||
System.exit(0);
|
System.exit(0);
|
||||||
terminal.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 指令初始化
|
||||||
|
*/
|
||||||
|
private static void initCommands() {
|
||||||
|
commandDispatcher = CommandDispatcher.getInstance();
|
||||||
|
// help
|
||||||
|
commandDispatcher.register(new HelpCommand());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package com.serliunx.ddns.support.command;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 指令的抽象实现
|
||||||
|
* <li> 实现公共逻辑及定义具体逻辑
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
|
||||||
|
* @version 1.0.4
|
||||||
|
* @since 2025/1/15
|
||||||
|
*/
|
||||||
|
public abstract class AbstractCommand implements Command {
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
private final List<Command> subCommands;
|
||||||
|
private final String description;
|
||||||
|
private final String usage;
|
||||||
|
|
||||||
|
public AbstractCommand(String name, List<Command> subCommands, String description, String usage) {
|
||||||
|
this.name = name;
|
||||||
|
this.subCommands = subCommands;
|
||||||
|
this.description = description;
|
||||||
|
this.usage = usage;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Command> getSubCommands() {
|
||||||
|
return subCommands;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUsage() {
|
||||||
|
return usage;
|
||||||
|
}
|
||||||
|
}
|
||||||
44
src/main/java/com/serliunx/ddns/support/command/Command.java
Normal file
44
src/main/java/com/serliunx/ddns/support/command/Command.java
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
package com.serliunx.ddns.support.command;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 指令接口定义
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
|
||||||
|
* @version 1.0.4
|
||||||
|
* @since 2025/1/15
|
||||||
|
*/
|
||||||
|
public interface Command {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 指令执行逻辑
|
||||||
|
*
|
||||||
|
* @param args 当前指令参数
|
||||||
|
* @return 成功执行返回真, 否则返回假. (目前没影响)
|
||||||
|
*/
|
||||||
|
boolean onCommand(String[] args);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取指令名称
|
||||||
|
*/
|
||||||
|
String getName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取子命令
|
||||||
|
* <li> 例: cmd c1 c2, 此时 c1为cmd的子命令
|
||||||
|
*
|
||||||
|
* @return 子命令
|
||||||
|
*/
|
||||||
|
List<Command> getSubCommands();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取该指令的描述
|
||||||
|
*/
|
||||||
|
String getDescription();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取该指令的用法
|
||||||
|
*/
|
||||||
|
String getUsage();
|
||||||
|
}
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
package com.serliunx.ddns.support.command;
|
||||||
|
|
||||||
|
import com.serliunx.ddns.ManagerLite;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 指令调度器
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
|
||||||
|
* @version 1.0.4
|
||||||
|
* @since 2025/1/15
|
||||||
|
*/
|
||||||
|
public final class CommandDispatcher {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(CommandDispatcher.class);
|
||||||
|
private static final CommandDispatcher INSTANCE = new CommandDispatcher();
|
||||||
|
|
||||||
|
// private-ctor
|
||||||
|
private CommandDispatcher() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最顶层指令缓存
|
||||||
|
*/
|
||||||
|
private final Map<String, Command> commands = new ConcurrentHashMap<>(128);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 指令注册
|
||||||
|
* @param command 指令
|
||||||
|
*/
|
||||||
|
public void register(Command command) {
|
||||||
|
commands.put(command.getName(), command);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 指令反注册
|
||||||
|
* @param command 指令
|
||||||
|
*/
|
||||||
|
public void unregister(Command command) {
|
||||||
|
commands.remove(command.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理输入的指令
|
||||||
|
* @param input 指令
|
||||||
|
*/
|
||||||
|
public void onCommand(String input) {
|
||||||
|
if (input == null ||
|
||||||
|
input.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] args = input.split(" ");
|
||||||
|
String cmd = args[0];
|
||||||
|
|
||||||
|
Command command = commands.get(cmd);
|
||||||
|
if (command == null) {
|
||||||
|
logger.warn("未知指令: {}, 请输入 help 查看帮助!", cmd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!command.onCommand(splitArgs(args))) {
|
||||||
|
logger.error("指令执行出现了错误: {}", Arrays.toString(args));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分割指令参数
|
||||||
|
* <li> cmd x1 x2 => x1 x2
|
||||||
|
*
|
||||||
|
* @param args 参数
|
||||||
|
* @return 去除指令本身的参数部分
|
||||||
|
*/
|
||||||
|
public static String[] splitArgs(String[] args) {
|
||||||
|
String[] newArgs = new String[args.length - 1];
|
||||||
|
System.arraycopy(args, 1, newArgs, 0, args.length - 1);
|
||||||
|
return newArgs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取实例
|
||||||
|
*/
|
||||||
|
public static CommandDispatcher getInstance() {
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package com.serliunx.ddns.support.command.target;
|
||||||
|
|
||||||
|
import com.serliunx.ddns.ManagerLite;
|
||||||
|
import com.serliunx.ddns.support.command.AbstractCommand;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 指令: help
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2025/1/15
|
||||||
|
*/
|
||||||
|
public class HelpCommand extends AbstractCommand {
|
||||||
|
|
||||||
|
private static final Logger log = ManagerLite.getLogger();
|
||||||
|
|
||||||
|
public HelpCommand() {
|
||||||
|
super("help", null, "查看帮助信息", "help cmd");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCommand(String[] args) {
|
||||||
|
System.out.println(Arrays.toString(args));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user