使用Spring Shell 快速開發(fā)自己的命令交互窗口 - 草稿

Spring Shell

有時候,為了方便開發(fā)和測試服務器蕊爵,并不需要一個漂亮的用戶界面辉哥,使用一個簡單的命令窗口即可。如下所示:


交互式命令窗口

這里介紹一個快速攒射,方便醋旦,易用,簡單的交互式命令窗口開發(fā)組件-Spring Shell
沒錯会放,又是spring 生態(tài)中的浑度。

源碼地址

https://gitee.com/wgslucky/spring-shell-demo

創(chuàng)建項目

本項目是使用Eclipse作為開發(fā)的IDE,同樣鸦概,直接導入到Idea之中也可以使用箩张。使用的JDK需要是1.8或更高的版本甩骏,我測試過在JDK11上也可以使用。
在eclipse中創(chuàng)建maven項目:spring-shell-demo先慷,然后在pom.xml中添加如下依賴:

   <parent>
       <!-- 添加spring boot 父pom依賴饮笛,這個不能少,spring shell官方的文檔中沒有寫 -->
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-parent</artifactId>
       <version>2.2.6.RELEASE</version>
   </parent>
   <dependencies>
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter</artifactId>
       </dependency>
       <dependency>
           <groupId>org.springframework.shell</groupId>
           <artifactId>spring-shell-starter</artifactId>
           <version>2.0.0.RELEASE</version>
       </dependency>
   </dependencies>

添加啟動類

@SpringBootApplication
public class SpringShellDemo {

    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(SpringShellDemo.class);
        app.setBannerMode(Mode.OFF);
        app.setWebApplicationType(WebApplicationType.NONE);
        app.run(args);
    }
}

到此论熙,項目創(chuàng)建完成福青。下面就是見證奇跡的時候了。

快速添加一條命令

創(chuàng)建一個命令類脓诡,類名可以自定義:

@ShellComponent
public class MyCommand {
    @ShellMethod("連接服務器无午,格式:connect ip port")
    public String connect(String ip,int port) {
        return String.format("連接服務成功:%s:%s", ip,port);
    }
}

然后,運行項目的啟動類main方法祝谚,在控制臺就可以輸入命令了:


輸入命令

就是這么簡單O艹佟!交惯!次泽,只需要兩步:

  1. 在命令類上面添加注解:@ShellComponent
  2. 在方法上面添加注解:@ShellMethod

項目打包和運行

在項目的pom.xml所在的目錄上執(zhí)行

mvn clean package

然后在target的目錄下面生成了運行包:spring-shell-demo-0.0.1-SNAPSHOT.jar
使用下面的命令可以直接運行此包:

java -jar spring-shell-demo-0.0.1-SNAPSHOT.jar

這樣就可以在IDE外面隨時使用了。

使用小技巧

現(xiàn)在已經(jīng)可以輕松的添加自己想要的交互命令了席爽,交互命令的最重要的職責就是接收用戶輸入的參數(shù)意荤,剩下如何執(zhí)行命令就是自己的業(yè)務邏輯了。下面介紹一些使用小技巧玖像。

內(nèi)置命令

Spring Shell內(nèi)容了一些常用的命令齐饮,可以直接使用,可以在運行的命令窗口中輸入help沈矿,快速查看這些命令:

shell:>help
AVAILABLE COMMANDS

Built-In Commands
        clear: Clear the shell screen. (清屏)
        exit, quit: Exit the shell.  (退出)
        help: Display help about available commands. (幫忙羹膳,查看支持的所有命令)
        script: Read and execute commands from a file. (從文件中讀取命令并執(zhí)行)
        stacktrace: Display the full stacktrace of the last error. 
        (顯示異常棧陵像,一般遇到錯誤時寇壳,使用它快速查看異常棧)

添加命令描述

可以在@ShellMethod注解中添加對此命令的描述,這樣在使用help命令時泞歉,就可以看到這些描述,明白命令如何使用榛丢,如上面的第一個命令的例子挺庞,在命令窗口中輸入help可以看到:

My Command
       connect: 連接服務器,格式:connect ip port

自定義命令的名字

默認情況下是不需要自定義命令的名字的掖鱼,它會使用執(zhí)行這個命令的方法名轉(zhuǎn)化相應的窗口命令名字援制,如果是多個單詞,使用-分開增拥。比如connect方法寻歧,它的命令名字就是connect,如果方法名是sayHello猾封,那么它的命令名字就是:say-hello
如果想要自定義命令名字晌缘,可以在@ShellMethod注解中添加:

    @ShellMethod(value = "登陸服務器痢站,格式:login-server playerId",key = "login-server")
    public String login(String playerId) {
        return "登陸成功:" + playerId;
    }

修改提示符

在spring shell運行時,默認的命令提示符是:shell:> 有時候岳枷,看著別扭呜叫,如果能修改為自定義的提示符就好盛泡。這個可以修改娱颊,需要添加一個新的類:

@Service
public class CustomPromptProvider implements PromptProvider{

    @Override
    public AttributedString getPrompt() {
        return new AttributedString("xinyues-client:>");
    }

}

這樣重新打包運行,輸入的命令提示符就變成了 xinyues-client:>

帶參數(shù)名輸入命令參數(shù)

在輸入命令時掰吕,如果不使用命令參數(shù)名字,那么參數(shù)的順序必須和方法中定義的參數(shù)順序一致局待。如果想使順序不同菱属,可以添加參數(shù)名稱,如下所示:

xinyues-client:>connect --port 8888  --ip localhost
連接服務成功:localhost:8888
xinyues-client:>

參數(shù)需要兩個橫扛(--)薛耻。

添加默認參數(shù)值

有時候赏陵,一些命令可以簡化一下,如果不輸入?yún)?shù)的話缕溉,就使用參數(shù)的默認值吃型。如下所示:

    @ShellMethod("連接服務器,格式:connect ip port")
    public String connectDefault(@ShellOption(defaultValue = 
"localhost")String ip,@ShellOption(defaultValue = "8080")int port) {
        return String.format("連接服務成功:%s:%s", ip,port);
    }

在參數(shù)上面使用了一個新的注解:@ShellOption
使用命令時可以直接輸入命令名勤晚,而不需要輸入?yún)?shù):

xinyues-client:>connect-default
連接服務成功:localhost:8080
xinyues-client:>

使用數(shù)組參數(shù)

有時候,為了輸入方便鸟蜡,不想定義太多的參數(shù)變量挺邀,或者參數(shù)是一個數(shù)組數(shù)據(jù)時,可以使用下面這種方式:

        @ShellMethod("Add Numbers.")
        public float add(@ShellOption(arity=3) float[] numbers) {
                return numbers[0] + numbers[1] + numbers[2];
        }

輸入的參數(shù)帶空格時

默認情況下,spring shell是以空格區(qū)分多個參數(shù)的沦补,如果一個參數(shù)是多個單詞咪橙,且有空格虚倒,就不能直接輸入了魂奥,可以使用雙引號或單引號易猫,比如下面這個命令:

        @ShellMethod("Prints what has been entered.")
        public String echo(String what) {
                return "You said " + what;
        }

輸入如下所示:

shell:>echo Hello
You said Hello
shell:>echo 'Hello'
You said Hello
shell:>echo 'Hello World'
You said Hello World
shell:>echo "Hello World"
You said Hello World

也可以這樣使用,避免使用轉(zhuǎn)義符:

shell:>echo "I'm here!"
You said I'm here!
shell:>echo 'He said "Hi!"'
You said He said "Hi!"

命令自動補全功能

可以使用tab鍵哈蝇,自動補命令名字攘已,和使用linux命令類似,也可以使用tab自動補全參數(shù)名字吠勘。

命令換行輸入

有時候峡眶,命令參數(shù)太多,一行可能輸入不完诵姜,可以在一行的末尾添加 \ 搏熄,然后另起一行輸入命令:

shell:>register module --type source --name foo  \ 
> --uri file:///tmp/bar
Successfully registered module 'source:foo'

快捷鍵使用

  1. ctrl + r 搜索輸入過歷史執(zhí)行過的命令。減少重復的輸入宵凌,提高操作效率止后。
  2. ctrl + a 跳轉(zhuǎn)到行頭輸入
  3. ctrl + e 跳轉(zhuǎn)到行尾輸入
  4. 上下箭頭 輸入完命令名字之后译株,按上下箭頭可以查閱之前輸入過的參數(shù)命令。

參數(shù)限制

可以使用注解乘寒,對參數(shù)進入限制匪补,防止用戶輸入錯誤烂翰,如下所示:

        @ShellMethod("Change password.")
        public String changePassword(@Size(min = 8, max = 40) String password) {
                return "Password successfully set to " + password;
        }

如果輸入的不符合要求甘耿,會有提示:

shell:>change-password hello
The following constraints were not met:
    --password string : size must be between 8 and 40 (You passed 'hello')

更多可以使用的注解竿滨,請參閱:https://beanvalidation.org/2.0/spec/#builtinconstraints

命令有效性檢測

有時候,多個命令之間可能有某種依賴性殿怜,比如這樣一個場景曙砂,客戶端有一個下載download命令,但是在使用下載命令的時候柱告,必須先connect成功笑陈。可以這樣檢測download命令是否可用:

@ShellComponent
public class MyCommands {

    private boolean connected;

    @ShellMethod("Connect to the server.")
    public void connect(String user, String password) {
        [...]
        connected = true;
    }

    @ShellMethod("Download the nuclear codes.")
    public void download() {
        [...]
    }
   // 注意乖菱,這里方法的命名是命令名 + Availability
    public Availability downloadAvailability() {
        return connected
            ? Availability.available()
            : Availability.unavailable("you are not connected");
    }
}

這樣蓬网,如果用戶沒有使用connect命令,而直接使用download命令吵取,就會提示:

xinyues-client:>download
?[31mCommand 'download' exists but is not currently available because you are not connected?[0m
?[31mDetails of the error have been omitted. You can use the ?[1mstacktrace?[22m command to print the full stacktrace.?[0m
xinyues-client:>

上面這個檢測方法是命名是有規(guī)則的必須是命令名 + Availability皮官;另一種方式是使用注解指定檢測的方法名:

    @ShellMethod("Download the nuclear codes.")
    @ShellMethodAvailability("availabilityCheck") 
    public void download() {
        [...]
    }

    public Availability availabilityCheck() { 
        return connected
            ? Availability.available()
            : Availability.unavailable("you are not connected");
    }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末捺氢,一起剝皮案震驚了整個濱河市剪撬,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌缺狠,老刑警劉巖萍摊,帶你破解...
    沈念sama閱讀 211,348評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件冰木,死亡現(xiàn)場離奇詭異,居然都是意外死亡歇终,警方通過查閱死者的電腦和手機逼龟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,122評論 2 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來奕短,“玉大人匀钧,你說我怎么就攤上這事∪砧荆” “怎么了佑刷?”我有些...
    開封第一講書人閱讀 156,936評論 0 347
  • 文/不壞的土叔 我叫張陵项乒,是天一觀的道長。 經(jīng)常有香客問我檀何,道長,這世上最難降的妖魔是什么栓辜? 我笑而不...
    開封第一講書人閱讀 56,427評論 1 283
  • 正文 為了忘掉前任藕甩,我火速辦了婚禮周荐,結(jié)果婚禮上僵娃,老公的妹妹穿的比我還像新娘腋妙。我一直安慰自己,他們只是感情好匙睹,可當我...
    茶點故事閱讀 65,467評論 6 385
  • 文/花漫 我一把揭開白布痕檬。 她就那樣靜靜地躺著送浊,像睡著了一般。 火紅的嫁衣襯著肌膚如雪袭景。 梳的紋絲不亂的頭發(fā)上改淑,一...
    開封第一講書人閱讀 49,785評論 1 290
  • 那天朵夏,我揣著相機與錄音仰猖,去河邊找鬼奈籽。 笑死,一個胖子當著我的面吹牛衣屏,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播膨疏,決...
    沈念sama閱讀 38,931評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼佃却,長吁一口氣:“原來是場噩夢啊……” “哼窘俺!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,696評論 0 266
  • 序言:老撾萬榮一對情侶失蹤育八,失蹤者是張志新(化名)和其女友劉穎单鹿,沒想到半個月后深纲,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體劲妙,經(jīng)...
    沈念sama閱讀 44,141評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡镣奋,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,483評論 2 327
  • 正文 我和宋清朗相戀三年侨颈,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片哈垢。...
    茶點故事閱讀 38,625評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡耘分,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出求泰,到底是詐尸還是另有隱情,我是刑警寧澤芽丹,帶...
    沈念sama閱讀 34,291評論 4 329
  • 正文 年R本政府宣布拔第,位于F島的核電站,受9級特大地震影響楼肪,放射性物質(zhì)發(fā)生泄漏惹悄。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,892評論 3 312
  • 文/蒙蒙 一暂殖、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧踩窖,春花似錦、人聲如沸洋腮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽伙狐。三九已至瞬欧,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間艘虎,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工美旧, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留榴嗅,地道東北人。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓嗽测,卻偏偏與公主長得像肿孵,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子晤愧,可洞房花燭夜當晚...
    茶點故事閱讀 43,492評論 2 348

推薦閱讀更多精彩內(nèi)容