SpringShell之使用簡介

一、什麼是Spring Shell ?

Spring Shell允許人們輕鬆創建這樣的可運行應用程序,用戶將在其中輸入文本命令,這些命令將被執行直到程序終止。Spring Shell項目提供了創建此類REPL(讀取,評估,打印循環)的基礎結構,從而使開發人員可以使用熟悉的Spring編程模型來專注於命令實現。

諸如解析,TAB完成,輸出着色,精美的ascii-art表顯示,輸入轉換和驗證之類的高級功能都是免費提供的,而開發人員僅需專注於核心命令邏輯即可。

二、使用Spring Shell

2.1. 引入依賴
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.0.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.mly.shell</groupId>
    <artifactId>mly-shell</artifactId>
    <version>1.0.0</version>
    <name>mly-shell</name>
    <description>自定義的Spring Shell</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <!-- Spring Shell 依賴 -->
        <dependency>
            <groupId>org.springframework.shell</groupId>
            <artifactId>spring-shell-starter</artifactId>
            <version>2.0.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>
2.2. 第一個小例子
import org.springframework.shell.standard.ShellComponent;
import org.springframework.shell.standard.ShellMethod;

/**
 * @author 墨龍吟
 * @version 1.0.0
 * @ClassName CommandsOne.java
 * @Email [email protected]
 * @Description 第一條命令
 * @createTime 2019年10月31日 - 13:22
 */
@ShellComponent
public class CommandsOne {

    @ShellMethod("Add two integers together.")
    public int add (int a, int b) {
        return a + b;
    }

}

運行輸出:(輸入exit退出命令行)

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.2.0.RELEASE)
shell:>add 1 3
4
shell:>exit

Process finished with exit code 0

構建jar包運行

E:\owner_app\mly-shell>mvn install -DskipTests
[INFO] Scanning for projects...
[INFO]
[INFO] ----------------------< com.mly.shell:mly-shell >-----------------------
[INFO] Building mly-shell 1.0.0
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:3.1.0:resources (default-resources) @ mly-shell ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ mly-shell ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 2 source files to E:\owner_app\mly-shell\target\classes
[INFO]
[INFO] --- maven-resources-plugin:3.1.0:testResources (default-testResources) @ mly-shell ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory E:\owner_app\mly-shell\src\test\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:testCompile (default-testCompile) @ mly-shell ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to E:\owner_app\mly-shell\target\test-classes
[INFO]
[INFO] --- maven-surefire-plugin:2.22.2:test (default-test) @ mly-shell ---
[INFO] Tests are skipped.
[INFO]
[INFO] --- maven-jar-plugin:3.1.2:jar (default-jar) @ mly-shell ---
[INFO] Building jar: E:\owner_app\mly-shell\target\mly-shell-1.0.0.jar
[INFO]
[INFO] --- spring-boot-maven-plugin:2.2.0.RELEASE:repackage (repackage) @ mly-shell ---
[INFO] Replacing main artifact with repackaged archive
[INFO]
[INFO] --- maven-install-plugin:2.5.2:install (default-install) @ mly-shell ---
[INFO] Installing E:\owner_app\mly-shell\target\mly-shell-1.0.0.jar to D:\DevelopSoftware\apache-maven-3.6.1\repository\com\mly\shell\mly-shell\1.0.0\mly-shell-1.0.0.jar
[INFO] Installing E:\owner_app\mly-shell\pom.xml to D:\DevelopSoftware\apache-maven-3.6.1\repository\com\mly\shell\mly-shell\1.0.0\mly-shell-1.0.0.pom
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  5.268 s
[INFO] Finished at: 2019-10-31T13:35:11+08:00
[INFO] ------------------------------------------------------------------------

E:\owner_app\mly-shell>cd target
E:\owner_app\mly-shell>java -jar mly-shell-1.0.0.jar   # 執行命令
2.3. 自定義命令名稱的方法

2.3.1. 默認爲方法名爲命令名:

@ShellMethod("Add two integers together.")
public int add (int a, int b) {
    return a + b;
}
// shell:>add 1 3      #返回結果 4

這樣子上面的命令名:add 1 2 , 將會返回3

2.3.2 如果方法名是由駝峯單詞組成,命令名將會變以橫槓分割多個單詞:

@ShellMethod(value = "add sum")
public int sumAdd(int a, int b) {
    return a + b;
}
// shell:>sum-add 1 2     #返回結果 3

2.3.3. 如果是命令是以下劃線分割的,將還以原型式作爲命令名

@ShellMethod(value = "add sumasas")
public int sum_add(int a, int b) {
    return a + b;
}
// shell:>sum_adds 1 3   # 返回結果 4

2.3.4 命令也可以有別名

@ShellMethod(value = "add sumasas", key = {"sum0", "sum1", "sum2"})
public int adds(int a, int b) {
    return a + b;
}
// shell:>sum0 1 4     # 返回結果 5
// shell:>sum1 1 3     # 返回結果 4
// shell:>sum2 1 3     # 返回結果 4
2.4. 參數的使用

命令參數使用方法:

@ShellMethod("Display stuff")
public String echo (int a, int b, int c) {
    return String.format("You said a = %d, b = %d, c = %d", a, b, c);
}

參數使用:

shell:>echo 1 2 3                  # 使用位置參數
You said a = 1, b = 2, c = 3     
shell:>echo --a 1 --b 2 --c 3      # 完整的按名稱參數
You said a = 1, b = 2, c = 3
shell:>echo --b 2 --c 3 --c 1      # 也可以需要重新排列名稱參數
You said a = 1, b = 2, c = 3      
shell:>echo --a 1 2 3              # 也可以混合使用
You said a = 1, b = 2, c = 3
shell:>echo 1 --c 3 2              # 非名稱參數按他們出現順序解析
You said a = 1, b = 2, c = 3
2.5. 自定義參數鍵
@ShellMethod(value = "Display stuff", prefix = "-")
public String echo (int a, int b, @ShellOption("--third") int c) {
    return String.format("You said a = %d, b = %d, c = %d", a, b, c);
}

參數使用:

shell:>echo -a 1 -b 2 --third 3
You said a = 1, b = 2, c = 3
shell:>echo 1 2 3
You said a = 1, b = 2, c = 3
shell:>echo 1 2 --third 3
You said a = 1, b = 2, c = 3
2.6. 可選參數和默認參數
@ShellMethod("兩數相加:")
public int add (@ShellOption(defaultValue = "3") int a, int b) {
    return a + b;
}

參數使用

shell:>add 3                                # 這樣使用是不對的哦!
Parameter '--b int' should be specified
Details of the error have been omitted. You can use the stacktrace command to print the full stacktrace.
shell:>add --b 3                            # 默認 a 參數, 需要指定參數 b
6
shell:>add 1 2                              # 正常的使用  
3
2.7. 多個參數可以使用Arity

上面情況每個參數都映射到用戶輸入單個參數,當對應多個參數時需要用到Arity對應一個數組或者是一個集合來承接參數。

@ShellMethod("多個數字相加:")
public float add1 (@ShellOption(arity = 3) float[] numbers) {
    return numbers[0] + numbers[1] + numbers[2];
}

// ====================輸出=======================
shell:>add1 2 3.5 6.7
12.2
2.8 對於布爾參數的特殊處理

當涉及參數Arity時,默認情況下,有一種參數會接受特殊處理:布爾值(即booleanjava.lang.Boolean)參數的行爲類似於默認情況下的arity()of 0,允許用戶使用“標誌”方法設置其值。

參數使用展示:

@ShellMethod("Terminate the system.")
public String shutdown(boolean force) {
    return "You said " + force;
}

// ====================錯誤輸出=======================
shell:>shutdown true
Too many arguments: the following could not be mapped to parameters: 'true'
Details of the error have been omitted. You can use the stacktrace command to print the full stacktrace.
// ====================正確輸出=======================    
shell:>shutdown
You said false
shell:>shutdown --force
You said true    

以上得出結論:布爾參數默認爲false

2.9. 多字符串操作:

Spring Shell接受用戶輸入並將其用 單詞 標記化,並按空格分隔。如果用戶想提供一個包含空格的參數值,則該值必須用引號引起來。單引號(')和雙"引號()都受支持,並且這些引號將不屬於值的一部分。

@ShellMethod("接受多個值:")
public String echo(String what) {
    return "You said " + what;
}
// ====================正確輸出=======================    
shell:>echo "Java python"
You said Java python
shell:>echo 'java Python'
You said java Python
shell:>echo "I'm tom"
You said I'm tom    
2.10. 參數驗證

Spring ShellBean Validation API集成在一起,以支持對命令參數的驗證。

@ShellMethod("修改密碼:")
public String changePassword(@Size(min = 8, max = 16, message = "密碼長度必須在8到16之間") String password) {
    return "密碼修改成功:" + password;
}
// ====================正確輸出=======================    
shell:>change-password 12345
The following constraints were not met:
	--password string : 密碼長度必須在816之間 (You passed '12345')
shell:>change-password 1234567889
密碼修改成功:1234567889
2.11. 內置命令
shell:>help
AVAILABLE COMMANDS

Built-In Commands
        clear: 清除屏幕.
        exit, quit: 退出shell.
        help: 顯示有關可用命令的幫助.
        history: 顯示以前的命令
        script: 讀和執行命令從一個文件.
        stacktrace: 顯示上一個錯誤的完整堆棧跟蹤.
wxz
Commands One
        connect: Connect to the server.
        download: Download the nuclear codes.
2.12. 命令分組
  1. 方法一:在ShellMethod中添加group

    @ShellComponent(value = "自定義的命令")
    public class UserCommands {
    
        @ShellMethod(value = "命令一", group = "分組一")
        public void command1() {}
         @ShellMethod(value = "命令二", group = "分組二")
        public void command2() {}
    
        @ShellMethod(value = "命令三", group = "分組三")
        public void command3() {}
    
    }
    

    當輸入help命令時顯示:

    shell:>help
    AVAILABLE COMMANDS
    
    Built-In Commands
            clear: Clear the shell screen.
            exit, quit: Exit the shell.
            help: Display help about available commands.
            history: Display or save the history of previously run commands
            script: Read and execute commands from a file.
            stacktrace: Display the full stacktrace of the last error.
    
    分組一
            command1: 命令一
    
    分組三
            command3: 命令三
    
    分組二
            command2: 命令二
    
  2. 使用ShellCommandGroup註解

    @ShellComponent(value = "自定義的命令")
    @ShellCommandGroup(value = "分組666")
    public class UserCommands {
    
        @ShellMethod(value = "命令一")
        public void command1() {}
    
    
        @ShellMethod(value = "命令二")
        public void command2() {}
    
        @ShellMethod(value = "命令三")
        public void command3() {}
    
    }
    

    當輸入help命令時顯示:

    shell:>help
    AVAILABLE COMMANDS
    
    Built-In Commands
            clear: Clear the shell screen.
            exit, quit: Exit the shell.
            help: Display help about available commands.
            history: Display or save the history of previously run commands
            script: Read and execute commands from a file.
            stacktrace: Display the full stacktrace of the last error.
    
    分組666
            command1: 命令一
            command2: 命令二
            command3: 命令三
    
    
    shell:>
    
2.13. 覆蓋和禁止內置命令

禁止所有內置命令:在依賴中剔除

<dependency>
    <groupId>org.springframework.shell</groupId>
    <artifactId>spring-shell-starter</artifactId>
    <version>2.0.1.RELEASE</version>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.shell</groupId>
            <artifactId>spring-shell-standard-commands</artifactId>
        </exclusion>
    </exclusion>
</dependency>

禁止某一個特定命令:例如禁止help命令

public static void main(String[] args) throws Exception {
    String[] disabledCommands = {"--spring.shell.command.help.enabled=false"}; 
    String[] fullArgs = StringUtils.concatenateStringArrays(args, disabledCommands);
    SpringApplication.run(MyApp.class, fullArgs);
}

覆蓋內置命令:

public class MyClear implements Clear.Command {

    @ShellMethod("Clear the screen, only better.")
    public void clear() {
        // ...
    }
}
2.14. 自定義命令提示,默認的是shell:>
@Component
public class MyCommandShell implements PromptProvider {
    @Override
    public AttributedString getPrompt() {
        return new AttributedString("long : >",
                AttributedStyle.DEFAULT.foreground(AttributedStyle.RED));
    }
}

這樣將會把shell:>替換爲long:>

歡迎關注一波微型公衆號

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章