基于TrantorCli开发本地命令
TrantorCli支持第三方命令的接入,下边介绍如何基于TrantorCli开发本地命令。
本教程提供demo可以一起使用,下文所涉及源码都在demo内。
demo下载地址:https://erda.cloud/terminus/dop/T-Project/trantor-cli-plugin-demo
sdk
提供trantor-cli-client-sdk用于本地的开发
<dependency> <groupId>io.terminus.trantor</groupId> <artifactId>trantor-cli-client-sdk</artifactId> <version>1.0.0.RELEASE</version></dependency>定义命令
TrantorCommand的抽象

定义一个Trantor命令必须要继承自 AbstractTrantorCommand 。
添加类注解
| Annotation | Description | Required | Property |
|---|---|---|---|
| @Name | 定义命令的名称。 | true | value |
| @Summary | 对当前命令做一个简短的说明,可以展示在使用帮助中。 | false | value |
| @Description | 加长版说明,可以写该命令的使用示例,也可以展示在使用帮助中。 | false | value |
添加方法注解
| Annotation | Description | Required | Property |
|---|---|---|---|
| @Argument | 添加在成员变量的set方法上,用于参数的描述。 | true | 略 |
| @Option | 添加在成员变量的set方法上,用于选项的描述 | true | 略 |
定义一个基础命令
基础命令继承 AbstractTrantorSimpleCommand 抽象类。
该类命令是最基础的命令执行逻辑。
示例:
@Name("basic")@Summary("this is a basic command")@Description("EXAMPLES:\n" + "trantor basic [arg]" + "trantor basic -s true hhh")public class BasicCommand extends AbstractTrantorSimpleCommand {
/** * 命令选项 */ private Boolean status;
/** * 命令参数 */ private String arg;
/** * 定义该变量接收命令中的--status / -s选项对应的值 * 更多属性建议查看Option源码 */ @Option(shortName = "s", longName = "status") @DefaultValue("true") @Description("default type is true") public void setStatus(Boolean status) { this.status = status; }
/** * 定义该变量接收命令中的第一个参数 * argName 定义变量名称 * index 定义该变量在命令中参数的下标 * 更多属性建议查看Argument源码 */ @Argument(argName = "arg", index = 0) @Description("arg for basic command") public void setArg(String arg) { this.arg = arg; }
/** * 返回当前命令的版本 自定义 * * @return 当前命令的版本 */ @Override public String getVersion() { return TrantorCliVersion.VERSION; }
/** * 获取当前命令的父命令 当没有父命令时允许返回null * * @return 父命令名 */ @Override public Class<? extends TrantorCommand> getParent() { return null; }
/** * 命令的逻辑部分 * * @return 命令的执行状态 */ @Override public int process() throws Throwable { AnsiLog.info("这是一个基础命令,参数为{},选项为{}", arg, status); if (status) { AnsiLog.info("666"); } return TerminalStatus.EXIT_NORMALITY; }}图例:

定义一个复杂命令
复杂命令需要继承 AbstractTrantorComplexCommand 抽象类。
该类命令主要应用场景在多级命令,生命周期与简单命令一致,process() 方法执行完即结束。
逻辑上来说存在子命令的父命令只会存在选项,所以该抽象类的实现类不可以再有 Argument (命令参数) 的元信息描述。
一般场景下只会有二级命令,所以该抽象类默认实现了TrantorCommand接口的getParent() 方法并返回 null 表示没有父级命令。
如遇特殊情况,需要用到三级命令,请重写 TrantorCommand的getParent() 方法,返回值为二级命令的类信息。
示例:
ParentCommand命令为父级命令,由于有子命令,所以find命令需要继承自AbstractTrantorComplexCommand抽象类,可以拿到子命令以及子命令下的参数。实际最终命令的执行逻辑应该定义在SonCommand的process() 方法中。
@Name("parent")@Summary("this is a complex command,it have a secondary command")public class ParentCommand extends AbstractTrantorComplexCommand {
/** * 没有子命令输入时执行该方法 * * @return * @throws Throwable */ @Override protected int execute() throws Throwable { AnsiLog.info(this.usage()); return TerminalStatus.EXIT_NORMALITY; }
/** * 返回当前命令的版本 自定义 * * @return 当前命令的版本 */ @Override public String getVersion() { return TrantorCliVersion.VERSION; }
/** * 当需要个性化使用帮助时可重写该方法 * * @return 使用帮助内容 */ @Override public String usage() { StringBuilder usageStringBuilder = new StringBuilder(); UsageMessageFormatter usageMessageFormatter = new UsageMessageFormatter(); usageMessageFormatter.setOptionComparator(null); this.getCli().usage(usageStringBuilder, usageMessageFormatter); return usageStringBuilder.toString(); }}子命令SonCommand继承 AbstractTrantorSimpleCommand 抽象类,定义参数/选项,重写方法。
@Name("son")@Summary("this is a secondary command")@Description("EXAMPLES:\n" + "trantor parent son")public class SonCommand extends AbstractTrantorSimpleCommand {
private String arg;
@Argument(argName = "arg", index = 0) @Description("arg for son command") public void setArg(String arg) { this.arg = arg; }
@Override public String getVersion() { return TrantorCliVersion.VERSION; }
@Override public Class<? extends TrantorCommand> getParent() { return ParentCommand.class; }
@Override public int process() throws Throwable { AnsiLog.info("这里是一个子命令 参数是{}", arg); if (!"hahaha".equals(arg)) { throw new TrantorCommandProcessException(TerminalStatus.EXIT_ABNORMALLY, "参数不匹配"); } return TerminalStatus.EXIT_NORMALITY; }}图例:

定义一个会话级别的命令
会话级别的交互式命令需要继承AbstractTrantorSessionCommand抽象类。
该类命令主要用于多次交互的场景 例如 连接服务端进行远程命令操作,或者部署、数据迁移等需要多次交互的场景。 生命周期为进入会话,直到用户通过 exit 命令/CTRL+ D快捷键 主动退出。 该抽象类默认实现了TrantorCommand 的 getParent() 方法并返回 null 表示没有父级命令。
当我们需要定义一个会话级别的命令时可以继承AbstractTrantorLocalSessionCommand抽象类,该类是AbstractTrantorSessionCommand的进一步抽象,实现了process方法,可以帮助我们路由到会话中的命令。
示例:
实现一个会话级别命令
@Name("room")@Summary("this is a session command")@Description("EXAMPLES:\n" + "trantor room")public class RoomCommand extends AbstractTrantorLocalSessionCommand {
/** * 开始会话模式命令前的处理逻辑 * <p> * 返回的Map中,如果有ServiceName的key存在,value会成为命令行的Prompt * * @return 可以展示给用户的信息 Map k->label; v->value; */ @Override protected TrantorSessionCommandPrepareInformation prepareHook() throws Throwable { TrantorSessionCommandPrepareInformation information = new TrantorSessionCommandPrepareInformation(); //定义命令行提示符 information.setPrompt("trantor-cli-test"); LinkedHashMap<String, String> map = new LinkedHashMap<>(); map.put("hello","这是一个会话级别的命令"); //定义进入会话后的展示信息 information.setDisplayMessage(map); return information; }
/** * 结束会话模式命令后的处理逻辑 */ @Override protected void quitHook() throws Throwable { AnsiLog.info("会话结束啦"); }
@Override public String getVersion() { return TrantorCliVersion.VERSION; }}实现一个会话中的命令
@Name("chart")@Summary("this is a session command")@Description("EXAMPLES:\n" + "chart [arg]")public class ChartCommand extends AbstractTrantorSimpleCommand {
/** * 命令参数 */ private String arg;
/** * 定义该变量接收命令中的第一个参数 * argName 定义变量名称 * index 定义该变量在命令中参数的下标 * 更多属性建议查看Argument源码 */ @Argument(argName = "arg", index = 0) @Description("arg for basic command") public void setArg(String arg) { this.arg = arg; }
@Override public String getVersion() { return TrantorCliVersion.VERSION; }
@Override public Class<? extends TrantorCommand> getParent() { return RoomCommand.class; }
@Override public int process() throws Throwable { if ("hello".equals(arg)){ AnsiLog.info("hi"); }else{ AnsiLog.info("你好"); } return TerminalStatus.EXIT_NORMALITY; }
}图例:

命令的返回状态 (TerminalStatus)
| Key | Description | Value |
|---|---|---|
| EXIT_NORMALITY | 命令执行完成,正常退出 | 0 |
| EXIT_ABNORMALLY | 命令执行失败,异常退出 | 1 |
| EXIT_PARSE_EXCEPTION | 命令数据解析失败,异常退出 | 2 |
| EXIT_COMMAND_NOT_EXECUTABLE | 命令不可执行 | 126 |
| EXIT_COMMAND_NOT_FOUND | 没找到命令 | 127 |
命令行日志工具 (AnsiLog)
| Method | Description |
|---|---|
| level | 设置日志级别 |
| system | 设置日志级别 (ALL, TRACE, DEBUG, INFO, WARN, ERROR, OFF) |
| trace | 打印trace级别日志 |
| debug | 打印debug级别日志 |
| info | 打印info级别日志 |
| warn | 打印warn级别日志 |
| error | 打印error级别日志 |
部署
trantor-cli-plugin-client-demo工程下执行mvn命令打成.jar包。
mvn clean package打好的jar包放在 ../trantor-cli/lib/ext 目录下。

执行安装命令后即可使用。
trantor install [jarPath]jarPath 参数表示需要安装的jar包路径。
图例:

单测
Trantor Cli提供了单测工具类TrantorBasicCommandTest,引入依赖后即可使用。
<dependency> <groupId>io.terminus.trantor</groupId> <artifactId>trantor-cli-test</artifactId> <version>1.0.0.RELEASE</version> <scope>test</scope></dependency>示例:
public class CommandTest extends TrantorBasicCommandTest { @Test public void testBasicCommand() throws Throwable { String inputCommand ="test"; int status = runCommand(inputCommand, BasicCommand.class); Assert.assertEquals(TerminalStatus.EXIT_NORMALITY, status); }}