springshell实践
springshell是spring提供的一个组件,版本也已对springboot环境提供集成,便于整合其他组件,通过启动服务提供命令行式服务.
1.pom引入,搭建基础springboot(maven)工程
<!-- springshell包及基础依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <version>2.6.7</version> </dependency> <dependency> <groupId>org.springframework.shell</groupId> <artifactId>spring-shell-starter</artifactId> <version>2.0.0.RELEASE</version> </dependency> <!-- lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> <version>1.18.24</version> </dependency>
2.编写启动类
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class SpringShellDemoApplication { public static void main(String[] args) { SpringApplication.run(SpringShellDemoApplication.class, args); } }
在idea中启动工程,可在控制台输入命令, 或者maven打包命令行运行(在对应目录下):
mvn clean install -DskipTests java -jar target/***.jar
3.命令操作
package com.example.springshelldemo.command; import org.springframework.shell.standard.ShellCommandGroup; import org.springframework.shell.standard.ShellComponent; import org.springframework.shell.standard.ShellMethod; import org.springframework.shell.standard.ShellOption; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.servlet.ModelAndView; // @ShellComponent 扫描命令的类集 @ShellComponent @ShellCommandGroup(value = "SpringShellDemo Commands") // 不添加则默认为@ShellCommandGroup(value="驼峰类名以空格分隔") public class MyCommands { // @ShellMethod 扫描命令,Value值英文一般首字母大写,以"."结尾. 如使用中文方法注解,注意变更Linux环境的字符集,value为方法描述,key为命令行方法名称 @ShellMethod(value = "Add two nums together.", key = "sum") public int add(int a, int b){ return a+b; } }
注解
@ShellComponent 扫描命令的类集
@ShellCommandGroup(value = "") 不添加则默认为@ShellCommandGroup(value="驼峰类名以空格分隔"),用于命令分组;
@ShellMethod(value = "", key = "") 扫描动作命令,value值英文一般首字母大写,以"."结尾. 如使用中文方法注解,注意变更Linux环境的字符集,value为方法描述,key为命令行方法名称;
命令行参数可以按位置或者按照名称匹配;其中按位置如: echo 1 2 3 ;按名称默认为 --arg 如: echo --a --b --c ,亦可混合使用;
// 命令行参数可以按位置或者按照名称匹配;其中按位置如: echo 1 2 3 ;按名称默认为 --arg 如: echo --a --b --c ,亦可混合使用; @ShellMethod(value = "Dispaly stuff.") public String echo(String a, String b, String c){ return String.format("Param is a=%d ,b=%d, c=%d", a, b, c); }
操作:
shell:>echo a b paramC You said a=a, b=b, c=paramC shell:>echo --a a --b b --c paramC You said a=a, b=b, c=paramC shell:>echo a --b b paramC You said a=a, b=b, c=paramC
4.自定义参数命名键
更改整个方法的默认前缀, use the prefix() attribute of the @ShellMethod annotation
以每个参数的方式覆盖整个key , annotate the parameter with the @ShellOption annotation.
// @ShellMethod prefix 设置整个方法的默认前缀 @ShellMethod(value = "Display stuff.", prefix = "-", key = "echoc") // @ShellOption 设置具体某个参数的名称导入方式.如: -c 或者 --third 名称匹配参数c; public String echoCustomizing(String a, String b, @ShellOption(value = {"-c", "--third"}) String c) { return String.format("You said a=%s, b=%s, c=%s", a, b, c); }
操作:
shell:>echoc a b -c paramC You said a=a, b=b, c=paramC shell:>echoc -a a -b b --third paramC You said a=a, b=b, c=paramC
5.默认值
@ShellOption对参数进行设置,defaultValue 默认值, help设置help提示(如 help query)
@ShellMethod("query appName.") // @ShellOption对参数进行设置,defaultValue 默认值, help设置help提示(如 help query) public String query(@ShellOption(defaultValue = "defaultAppName", help = "应用名称") String appName){ return appName; }
操作:
shell:>query defaultAppName shell:>help query NAME query - query appName. SYNOPSYS query [[--app-name] string] OPTIONS --app-name string 应用名称 [Optional, default = defaultAppName]
6.参数相关性arity
@ShellOption arity 参数相关性,参数类型为数组或集合,并指定预期的值;
@ShellMethod(value = "add Array nums.", key = {"add-array", "addarray"})
// @ShellOption arity 参数相关性,参数类型为数组或集合,并指定预期的值;
public int addArray(@ShellOption(arity = 3) int[] nums) {
return nums[0] + nums[1] + nums[2];
}
操作:
shell:>add-array 1 2 3 6
7.布尔类型参数的处理
boolean 默认为@ShellOption arity = 0,即默认为false, --arg 则为true;
@ShellMethod(value = "Terminate the system.") // boolean 默认为@ShellOption arity = 0,即默认为false, --arg 则为true; public String shutdown(boolean force) { return "The system terminate " + force; }
操作:
shell:>shutdown The system terminate false shell:>shutdown --force The system terminate true
boolean 亦可设置为@ShellOption arity = 1,defaultValu为false;
@ShellMethod(value = "Terminate the system.", key = {"shutdown-system", "shutdownsystem"}) // boolean 亦可设置为@ShellOption arity = 1,defaultValu为false; public String shutdownSystem(@ShellOption(arity = 1, defaultValue = "false") boolean force) { return "The system terminate " + force; }
操作:
shell:>shutdownsystem The system terminate false shell:>shutdownsystem true The system terminate true
8.引用处理(quotes handling)
默认使用空格分隔参数,包含特殊字符的参数,可使用单引号('')或者双引号("")来确定参数,转义使用反斜杠(\);
使用上面的query方法示例操作:
shell:>query hello hello shell:>query 'hello world' hello world shell:>query "hello world" hello world shell:>query 'I\'m here!' I'm here! shell:>query "He said \"Hi!\"" He said "Hi!"
springshell支持TAB快捷操作,参数太长,可使用反斜杠("\")换行输入;
9.参数校验(Validating Command Arguments)
@ShellMethod("checklength.") // javax.validation.constraints.Size public String checklength(@Size(min = 2, max = 10) String username){ return "the username is " + username; }
操作:
shell:>checklength a The following constraints were not met: --username string : 个数必须在2和10之间 (You passed 'a') shell:>checklength yaoming the username is yaoming shell:>checklength yaoming123456789 The following constraints were not met: --username string : 个数必须在2和10之间 (You passed 'yaoming123456789')
10.动态命令可用性(Dynamic Command Availability)
springshell允许判断命令是否可用,并优雅提示;
@ShellMethodAvailability(value = "") 扫描动作命令;
@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() { [...] }
@ShellMethodAvailability({"download", "disconnect"}) public Availability downloadAvailability() { return connected ? Availability.available() : Availability.unavailable("you are not connected"); } }
操作:
shell:>download Command 'download' exists but is not currently available because you are not connected Details of the error have been omitted. You can use the stacktrace command to print the full stacktrace. shell:>disconnect No command found for 'disconnect' Details of the error have been omitted. You can use the stacktrace command to print the full stacktrace. shell:>connect admin admin shell:>download
11.命令分组(Organizing Commands)
使用@ShellMethod group 进行分组展示;
内置命令(Built-In Commands)
命令行键入 help + ENTER 即可输出所有命令,其中内置命令如下:
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.
clear: 清空屏幕
exit/quit: 退出
help: 显示可用命令的帮助信息
script: 从文件中读取并执行命令
stackstrace: 显示最后一个错误的完整堆栈跟踪
如不需要,可禁用内置命令,禁用全部内置命令:
<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> </exclusion> </dependency>
禁用某一条:
public static void main(String[] args) {
String[] disabledCommands = {
"--spring.shell.command.exit.enabled=false",
"--spring.shell.command.quit.enabled=false"}; String[] fullArgs = StringUtils.concatenateStringArrays(args, disabledCommands); SpringApplication.run(SpringShellDemoApplication.class, fullArgs); }
并可在禁用后提供自定义实现:
package com.example.springshelldemo.command; import org.springframework.shell.ExitRequest; import org.springframework.shell.standard.ShellComponent; import org.springframework.shell.standard.ShellMethod; import org.springframework.shell.standard.commands.Quit; @ShellComponent public class ExitCommand implements Quit.Command { public ExitCommand() { } @ShellMethod( value = "Exit the shell.", key = {"quit", "exit"}, group = "SpringShellDemo Commands" ) public void quit() { throw new ExitRequest(); } public interface Command { } }
12.自定义内置命令提示符(ResultHandlers)
import lombok.extern.slf4j.Slf4j; import org.jline.utils.AttributedString; import org.jline.utils.AttributedStyle; import org.springframework.shell.jline.PromptProvider; import org.springframework.stereotype.Component; import java.net.InetAddress; import java.net.UnknownHostException; @Slf4j @Component public class CustomPromptProvider implements PromptProvider { @Override public AttributedString getPrompt() { // 获取主机名称 String hostName = getHostName(); // 设置命令提示符文字 String promot = "SpringShellDemo@" + hostName + "> "; // 设置命令提示符字体样式 AttributedStyle promotStyle = AttributedStyle.BOLD.foreground(AttributedStyle.GREEN); // 返回命令提示符 return new AttributedString(promot, promotStyle); } /** * @Description: 获取主机名称 * @return: String 主机名称 * @author: zongf * @time: 2019-01-26 08:58:45 */ private String getHostName(){ String hostName = ""; try { InetAddress inetAddress = InetAddress.getLocalHost(); hostName = inetAddress.getHostName(); } catch (UnknownHostException e) { log.info("获取主机名称 UnknownHostException: {}", e.getMessage()); e.printStackTrace(); return "unknowHost"; } return hostName; } }
操作:
SpringShellDemo@LAPTOP-JSP5MRO1>
启动banner图案可参考springboot banner生成banner文件即可;
13.启动日志屏蔽,可在配置文件中添加:
#设置整个项目日志级别
logging.lever.root=warn
#设置操作包目录com.example.springshelldemo.command日志级别
logging.lever.com.example.springshelldemo.command=info
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性