From 1bcdabc595f07bab44305bf797f7e96d7ead2076 Mon Sep 17 00:00:00 2001
From: SerLiunx-ctrl <17689543@qq.com>
Date: Wed, 15 Jan 2025 21:49:11 +0800
Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E6=8C=87=E4=BB=A4?=
=?UTF-8?q?=E8=B0=83=E5=BA=A6=E5=99=A8.?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../java/com/serliunx/ddns/ManagerLite.java | 50 ++++++++---
.../ddns/support/command/AbstractCommand.java | 46 ++++++++++
.../ddns/support/command/Command.java | 44 +++++++++
.../support/command/CommandDispatcher.java | 89 +++++++++++++++++++
.../support/command/target/HelpCommand.java | 29 ++++++
5 files changed, 247 insertions(+), 11 deletions(-)
create mode 100644 src/main/java/com/serliunx/ddns/support/command/AbstractCommand.java
create mode 100644 src/main/java/com/serliunx/ddns/support/command/Command.java
create mode 100644 src/main/java/com/serliunx/ddns/support/command/CommandDispatcher.java
create mode 100644 src/main/java/com/serliunx/ddns/support/command/target/HelpCommand.java
diff --git a/src/main/java/com/serliunx/ddns/ManagerLite.java b/src/main/java/com/serliunx/ddns/ManagerLite.java
index 5bee971..572c457 100644
--- a/src/main/java/com/serliunx/ddns/ManagerLite.java
+++ b/src/main/java/com/serliunx/ddns/ManagerLite.java
@@ -6,13 +6,18 @@ import com.serliunx.ddns.config.PropertiesConfiguration;
import com.serliunx.ddns.constant.SystemConstants;
import com.serliunx.ddns.core.context.FileInstanceContext;
import com.serliunx.ddns.core.context.MultipleSourceInstanceContext;
+import com.serliunx.ddns.support.InstanceContextHolder;
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 org.jline.reader.LineReader;
import org.jline.reader.LineReaderBuilder;
import org.jline.reader.impl.history.DefaultHistory;
import org.jline.terminal.Terminal;
import org.jline.terminal.TerminalBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.io.IOException;
@@ -25,6 +30,11 @@ import java.io.IOException;
*/
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 CommandDispatcher commandDispatcher;
+
+ /**
+ * 获取默认的日志输出
+ */
+ public static Logger getLogger() {
+ return DEFAULT_LOGGER;
+ }
public static void main(String[] args) {
-
// 配置初始化
initConfiguration(args);
@@ -49,6 +69,9 @@ public final class ManagerLite {
// 系统初始化
initSystem();
+ // 指令初始化
+ initCommands();
+
Terminal terminal;
try {
terminal = TerminalBuilder.builder()
@@ -67,30 +90,35 @@ public final class ManagerLite {
JLineAdaptAppender.setLineReader(lineReader);
- String prompt = "client> ";
+ final String prompt = "client> ";
+ InstanceContextHolder.setAdditional("command-process");
while (true) {
// 该方法会阻塞,直到用户敲回车
try {
String cmd = lineReader.readLine(prompt);
- // 当用户输入 exit 或 quit,就退出循环
+ // 当用户输入 exit,就退出循环
if ("exit".equalsIgnoreCase(cmd)) {
break;
}
- // 在这里可以对用户输入做进一步处理
+ commandDispatcher.onCommand(cmd);
terminal.flush();
} catch (Exception e) {
- System.exit(0);
+ break;
}
}
- try {
- System.exit(0);
- terminal.close();
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
+ System.exit(0);
+ }
+
+ /**
+ * 指令初始化
+ */
+ private static void initCommands() {
+ commandDispatcher = CommandDispatcher.getInstance();
+ // help
+ commandDispatcher.register(new HelpCommand());
}
/**
diff --git a/src/main/java/com/serliunx/ddns/support/command/AbstractCommand.java b/src/main/java/com/serliunx/ddns/support/command/AbstractCommand.java
new file mode 100644
index 0000000..d8d1263
--- /dev/null
+++ b/src/main/java/com/serliunx/ddns/support/command/AbstractCommand.java
@@ -0,0 +1,46 @@
+package com.serliunx.ddns.support.command;
+
+import java.util.List;
+
+/**
+ * 指令的抽象实现
+ *
实现公共逻辑及定义具体逻辑
+ *
+ * @author SerLiunx
+ * @version 1.0.4
+ * @since 2025/1/15
+ */
+public abstract class AbstractCommand implements Command {
+
+ private final String name;
+ private final List subCommands;
+ private final String description;
+ private final String usage;
+
+ public AbstractCommand(String name, List 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 getSubCommands() {
+ return subCommands;
+ }
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+ @Override
+ public String getUsage() {
+ return usage;
+ }
+}
diff --git a/src/main/java/com/serliunx/ddns/support/command/Command.java b/src/main/java/com/serliunx/ddns/support/command/Command.java
new file mode 100644
index 0000000..ff23d00
--- /dev/null
+++ b/src/main/java/com/serliunx/ddns/support/command/Command.java
@@ -0,0 +1,44 @@
+package com.serliunx.ddns.support.command;
+
+import java.util.List;
+
+/**
+ * 指令接口定义
+ *
+ * @author SerLiunx
+ * @version 1.0.4
+ * @since 2025/1/15
+ */
+public interface Command {
+
+ /**
+ * 指令执行逻辑
+ *
+ * @param args 当前指令参数
+ * @return 成功执行返回真, 否则返回假. (目前没影响)
+ */
+ boolean onCommand(String[] args);
+
+ /**
+ * 获取指令名称
+ */
+ String getName();
+
+ /**
+ * 获取子命令
+ * 例: cmd c1 c2, 此时 c1为cmd的子命令
+ *
+ * @return 子命令
+ */
+ List getSubCommands();
+
+ /**
+ * 获取该指令的描述
+ */
+ String getDescription();
+
+ /**
+ * 获取该指令的用法
+ */
+ String getUsage();
+}
diff --git a/src/main/java/com/serliunx/ddns/support/command/CommandDispatcher.java b/src/main/java/com/serliunx/ddns/support/command/CommandDispatcher.java
new file mode 100644
index 0000000..eed6dcc
--- /dev/null
+++ b/src/main/java/com/serliunx/ddns/support/command/CommandDispatcher.java
@@ -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 SerLiunx
+ * @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 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));
+ }
+ }
+
+ /**
+ * 分割指令参数
+ * 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;
+ }
+}
diff --git a/src/main/java/com/serliunx/ddns/support/command/target/HelpCommand.java b/src/main/java/com/serliunx/ddns/support/command/target/HelpCommand.java
new file mode 100644
index 0000000..cafc776
--- /dev/null
+++ b/src/main/java/com/serliunx/ddns/support/command/target/HelpCommand.java
@@ -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 SerLiunx
+ * @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;
+ }
+}
\ No newline at end of file