自定義Spring Shell

目錄

  • 概述
  • 自定義內置命令
    • 禁用內置命令
    • 覆蓋內置命令
  • 自定義命令提示符
  • 自定義命令行選項行為
  • 自定義參數轉換器

概述

官網:https://projects.spring.io/spring-shell/。

Spring Shell除了提供一些常用的內置命令之外,還允許開發者對一些默認功能進行定製。

自定義內置命令

禁用內置命令

禁用Spring Shell的內置命令非常簡單,只需要在pom.xml文件中進行簡單配置即可,如下所示:

<!-- Spring Shell -->
<dependency>
    <groupId>org.springframework.shell</groupId>
    <artifactId>spring-shell-starter</artifactId>
    <version>2.0.0.RELEASE</version>
    <exclusions>
        <!-- 禁用內置命令 -->
        <exclusion>
            <groupId>org.springframework.shell</groupId>
            <artifactId>spring-shell-standard-commands</artifactId>
        </exclusion>
    </exclusions>
</dependency>
shell:>help
No command found for 'help'
shell:>exit
No command found for 'exit'
shell:>

完全禁用了所有內置命令之後,將無法通過help命令查詢其他命令信息,也不能再使用exit命令退出應用。
因此,如果有需要的情況下,應該只是禁用某些內置命令。

如果需要禁用指定內置命令,需要在代碼中設置對應的命令屬性為false,格式為:spring.shell.command.<command>.enabled=true
例如,需要禁用help命令:

@SpringBootApplication
public class TestSpringshellApplication {
    public static void main(String[] args) {
        String[] disabledCommands = new String[]{"--spring.shell.command.help.enabled=false"};
        String[] fullArgs = StringUtils.concatenateStringArrays(args, disabledCommands);
        SpringApplication.run(TestSpringshellApplication.class, fullArgs);
    }
}
# help命令將不再能使用
shell:>help
No command found for 'help'
Details of the error have been omitted. You can use the stacktrace command to print the full stacktrace.
shell:>exit

如果禁用的是其他命令,如:clear,在Spring Shell應用啟動之後通過help命令不再能看被禁用的命令了。

@SpringBootApplication
public class TestSpringshellApplication {
    public static void main(String[] args) {
        // 禁用了內置的clear命令
        String[] disabledCommands = new String[]{"--spring.shell.command.clear.enabled=false"};
        String[] fullArgs = StringUtils.concatenateStringArrays(args, disabledCommands);
        SpringApplication.run(TestSpringshellApplication.class, fullArgs);
    }
}
shell:>help
AVAILABLE COMMANDS

Built-In Commands
        exit, quit: Exit the shell.
        help: Display help about available commands.
        script: Read and execute commands from a file.
        stacktrace: Display the full stacktrace of the last error.

顯然,在禁用了指定的內置命令之後,通過help命令將不能看到該命令了。

覆蓋內置命令

如果希望重寫內置命令的實現,可以通過實現接口org.springframework.shell.standard.commands.<Command>.Command來完成(如:需要重寫clear命令的實現,實現接口org.springframework.shell.standard.commands.Clear.Command)。
如下為重寫內置命令script的實現:

import org.springframework.shell.standard.ShellComponent;
import org.springframework.shell.standard.ShellMethod;
import org.springframework.shell.standard.commands.Script;
// 實現接口org.springframework.shell.standard.commands.Script.Command
@ShellComponent
public class MyScript implements Script.Command {
    // 注意:命令名稱與內置命令保持一致
    @ShellMethod("Read and execute commands from a file.")
    public void script() {
      / // 實現自定義邏輯
        System.out.println("override default script command");
    }
}

有意思的是,此時在內置命令“Built-In Commands”分組中將不能看到script命令了,而是在自定義的分組中,

shell:>help
AVAILABLE COMMANDS

Built-In Commands  # 在內置命令分組中看不到重寫的命令了
        clear: Clear the shell screen.
        exit, quit: Exit the shell.
        help: Display help about available commands.
        stacktrace: Display the full stacktrace of the last error.

My Script          # 重寫的命令此時在自定義分組中
        scriptdo: Read and execute commands from a file.

如果希望被覆蓋的內置命令依然能夠在“Built-In Commands”分組中看到,可以通過註解@ShellMethod的group屬性指定。

// 指定被覆蓋的內置命令分組為“Built-In Commands”
@ShellMethod(value = "Read and execute commands from a file.", group = "Built-In Commands")
public void script() {
    System.out.println("override default script command");
}
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.
        stacktrace: Display the full stacktrace of the last error.

shell:>script
override default script command

自定義命令提示符

默認情況下,Spring Shell啟動之後显示的是一個黃色的命令提示符(shell:>)等待用戶輸入。
可以通過Spring Shell提供的接口org.springframework.shell.jline.PromptProvider對該命令提示符進行定製。

// 通過實現接口org.springframework.shell.jline.PromptProvider定製命令提示符
import org.jline.utils.AttributedString;
import org.jline.utils.AttributedStyle;
import org.springframework.shell.jline.PromptProvider;
import org.springframework.stereotype.Component;
@Component
public class MyPromptProvider implements PromptProvider {
    @Override
    public AttributedString getPrompt() {
        // 定製命令提示符為紅色的“#”
        return new AttributedString("#", AttributedStyle.DEFAULT.foreground(AttributedStyle.RED));
    }
}

如下為定製的命令提示符:

自定義命令行選項行為

Spring Shell提供了2個默認的ApplicationRunner,用於實現命令行選項的行為。

1.InteractiveShellApplicationRunner用於啟動交互式界面,接收用戶輸入命令。
2.ScriptShellApplicationRunner用於在應用啟動時從程序參數中讀取指定文件中的命令並執行,具體來講:將多個命令寫在文件中,並通過參數的形式將包含了批量命令的文件路徑傳遞給程序,傳遞的文件路徑參數必須以“@”開始,如下示例:

$ java -jar /home/test/sun/workspace/test-springshell/target/test-springshell-0.0.1-SNAPSHOT.jar @/home/test/cmd

文件/home/test/cmd中的內容為:

$ cat /home/test/cmd 
help

這樣,在啟動程序時,將會自動執行/home/test/cmd文件中的命令(如果文件不存在,啟動應用時報錯)。
值得注意的是: 當在程序參數中存在“@local_file_path”這樣的參數時,應用啟動后執行完文件“local_file_path”內命令之後就退出了,不會進入交互式命令行界面(上述示例中,應用啟動后執行help命令之後就退出了)。

如果Spring Shell默認提供的上述2個ApplicationRunner無法滿足需求,可以自定義其他的命令行選項行為,直接實現接口org.springframework.boot.ApplicationRunner即可。

自定義參數轉換器

默認情況下,Spring Shell使用標準的Spring類型轉換機制將命令行的文本參數轉換為指定的類型。
實際上,Spring Shell是通過DefaultConversionService註冊Converter<S, T>GenericConverter或者ConverterFactory<S, R>類型的Bean對象來實現對命令行參數進行類型轉換的。

換句話說,如果我們需要自定義類型轉換器,只需要簡單實現接口org.springframework.core.convert.converter.Converter<S, T>就可以了。

// 自定義類型
public class Food {
    private String value = null;
    public Food(String value) {
        this.value = value;
    }

    @Override
    public String toString() {
        return new StringBuilder()
                .append("Food{").append("value='").append(value).append("'}")
                .toString();
    }
}

// 自定義類型轉換器
@Component
public class MyConverter implements Converter<String, Food> {
    @Override
    public Food convert(String s) {
        // 將輸入參數轉換為Food類型實例
        return new Food(s);
    }
}

// 使用自定義轉換類型
@ShellComponent
public class ConvertionCmd {
    // 在命令方法中直接可以獲取Food對象,這是通過前面的自定義類型轉換器MyConverter實現的
    @ShellMethod("Conversion food")
    public String food(Food food) {
        return food.toString();
    }
}

在命令行指定命令food

#food apple
Food{value='apple'}

顯然,通過自定義類型轉換器可以實現對命令參數的特殊處理,非常實用。

【參考】
https://blog.csdn.net/zknxx/article/details/52196427 SpringBoot之CommandLineRunner接口和ApplicationRunner接口
https://www.jianshu.com/p/5d4ffe267596 CommandLineRunner或者ApplicationRunner接口

【精選推薦文章】

智慧手機時代的來臨,RWD網頁設計已成為網頁設計推薦首選

想知道網站建置、網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計及後台網頁設計

帶您來看台北網站建置台北網頁設計,各種案例分享

廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

您可能也會喜歡…