5. 选项

命令行参数可以分为选项和位置参数。 以下各节介绍了功能、如何定义和使用选项。spring-doc.cn

5.1. 定义

选项可以在目标方法中定义为方法参数中的注释 或以编程方式使用 。CommandRegistrationspring-doc.cn

具有带参数的目标方法会自动注册到匹配的 参数名称。spring-doc.cn

public String example(String arg1) {
	return "Hello " + arg1;
}

@ShellOptionannotation 可用于定义选项名称,如果您 不希望它与 argument name 相同。spring-doc.cn

public String example(@ShellOption(value = { "--argx" }) String arg1) {
	return "Hello " + arg1;
}

如果定义选项名称时不带前缀,则会发现 或 。 从 ShellMethod#前缀---spring-doc.cn

public String example(@ShellOption(value = { "argx" }) String arg1) {
	return "Hello " + arg1;
}

编程方式 with 是使用方法添加一个长名称。CommandRegistrationspring-doc.cn

CommandRegistration.builder()
	.withOption()
		.longNames("arg1")
		.and()
	.build();

5.2. 短格式

短格式 POSIX 选项在大多数情况下只是长格式的同义词,但 添加了其他功能以将这些选项组合在一起。拥有短 选项 ABC 可用作 。-abcspring-doc.cn

编程短选项是使用短名称函数定义的。spring-doc.cn

CommandRegistration.builder()
	.withOption()
		.shortNames('a')
		.and()
	.withOption()
		.shortNames('b')
		.and()
	.withOption()
		.shortNames('c')
		.and()
	.build();

如果将 type 定义为标志,则具有组合格式的 Short 选项非常有用 这意味着 type 是一个布尔值。这样你就可以定义 flag 的前提 as 、 或 .-abc-abc true-abc falsespring-doc.cn

CommandRegistration.builder()
	.withOption()
		.shortNames('a')
		.type(boolean.class)
		.and()
	.withOption()
		.shortNames('b')
		.type(boolean.class)
		.and()
	.withOption()
		.shortNames('c')
		.type(boolean.class)
		.and()
	.build();

使用 annotation model,您可以直接定义短参数。spring-doc.cn

public String example(
	@ShellOption(value = { "-a" }) String arg1,
	@ShellOption(value = { "-b" }) String arg2,
	@ShellOption(value = { "-c" }) String arg3
) {
	return "Hello " + arg1;
}

5.3. Arity

有时,您希望通过选项对参数数量进行更精细的控制 在解析操作发生时进行处理。Arity 定义为最小值和最大值 值,其中 min 必须为零或正整数,max 必须大于或等于 min。spring-doc.cn

CommandRegistration.builder()
	.withOption()
		.longNames("arg1")
		.arity(0, 1)
		.and()
	.build();

Arity 也可以定义为枚举,它们是快捷方式 如下表 OptionArity 所示。OptionArityspring-doc.cn

CommandRegistration.builder()
	.withOption()
		.longNames("arg1")
		.arity(OptionArity.EXACTLY_ONE)
		.and()
	.build();
表 1.OptionArity
最小/最大

spring-doc.cn

0 / 0spring-doc.cn

ZERO_OR_ONEspring-doc.cn

0 / 1spring-doc.cn

EXACTLY_ONEspring-doc.cn

1 / 1spring-doc.cn

ZERO_OR_MOREspring-doc.cn

0 / 整数最大值spring-doc.cn

ONE_OR_MOREspring-doc.cn

1 / 整数 MAXspring-doc.cn

注释模型仅支持定义 arity 的最大值。spring-doc.cn

public String example(@ShellOption(arity = 1) String arg1) {
	return "Hello " + arg1;
}

手动定义 arity 的一个用例是施加限制 many parameters 选项接受。spring-doc.cn

CommandRegistration.builder()
	.command("arity-errors")
	.withOption()
		.longNames("arg1")
		.type(String[].class)
		.required()
		.arity(1, 2)
		.and()
	.withTarget()
		.function(ctx -> {
			String[] arg1 = ctx.getOptionValue("arg1");
			return "Hello " + Arrays.asList(arg1);
		})
		.and()
	.build();

在上面的示例中,我们有选项 arg1,它被定义为类型 String[]。阿尔蒂 定义它至少需要 1 个参数,而不是超过 2 个参数。如下所示 引发特殊异常 TooManyArgumentsOptionExceptionNotEnoughArgumentsOptionException 以指示 arity 不匹配。spring-doc.cn

shell:>e2e reg arity-errors --arg1
Not enough arguments --arg1 requires at least 1.

shell:>e2e reg arity-errors --arg1 one
Hello [one]

shell:>e2e reg arity-errors --arg1 one two
Hello [one, two]

shell:>e2e reg arity-errors --arg1 one two three
Too many arguments --arg1 requires at most 2.

5.4. 位置

位置信息主要与命令目标方法相关:spring-doc.cn

CommandRegistration.builder()
	.withOption()
		.longNames("arg1")
		.position(0)
		.and()
	.build();
小心位置参数,因为它可能很快就会出现 使这些映射到的选项变得混乱。

通常,当参数在 命令行,无论是 long 选项还是 short 选项。一般而言 有 optionsoption argumentsarguments,其中后者 是未映射到任何 spesific 选项的 sit。spring-doc.cn

然后,无法识别的参数可以具有辅助映射逻辑,其中 位置信息很重要。使用期权头寸,您是 本质上是告诉命令解析如何解释普通 RAW 模棱两可的论点。spring-doc.cn

让我们看看当我们不定义位置时会发生什么。spring-doc.cn

CommandRegistration.builder()
	.command("arity-strings-1")
	.withOption()
		.longNames("arg1")
		.required()
		.type(String[].class)
		.arity(0, 2)
		.and()
	.withTarget()
		.function(ctx -> {
			String[] arg1 = ctx.getOptionValue("arg1");
			return "Hello " + Arrays.asList(arg1);
		})
		.and()
	.build();

选项 arg1 是必需的,并且没有信息如何处理参数导致缺少选项的错误。onespring-doc.cn

shell:>arity-strings-1 one
Missing mandatory option --arg1.

现在让我们定义一个位置 。0spring-doc.cn

CommandRegistration.builder()
	.command("arity-strings-2")
	.withOption()
		.longNames("arg1")
		.required()
		.type(String[].class)
		.arity(0, 2)
		.position(0)
		.and()
	.withTarget()
		.function(ctx -> {
			String[] arg1 = ctx.getOptionValue("arg1");
			return "Hello " + Arrays.asList(arg1);
		})
		.and()
	.build();

处理参数,直到我们得到最多 2 个参数。spring-doc.cn

shell:>arity-strings-2 one
Hello [one]

shell:>arity-strings-2 one two
Hello [one, two]

shell:>arity-strings-2 one two three
Hello [one, two]

5.5. 可选值

选项是必需的或不是,一般来说,它的行为方式取决于 命令目标:spring-doc.cn

CommandRegistration.builder()
	.withOption()
		.longNames("arg1")
		.required()
		.and()
	.build();

在 Comments 模型中,没有直接的方法来定义 argument 是否为 自选。相反,它被指示为:NULLspring-doc.cn

public String example(
	@ShellOption(defaultValue = ShellOption.NULL) String arg1
) {
	return "Hello " + arg1;
}

5.6. 默认值

选项的默认值与可选值有些关系,因为在某些情况下,您 可能想知道用户是否定义了选项并更改了行为 基于默认值:spring-doc.cn

CommandRegistration.builder()
	.withOption()
		.longNames("arg1")
		.defaultValue("defaultValue")
		.and()
	.build();

注解模型还支持定义默认值:spring-doc.cn

public String example(
	@ShellOption(defaultValue = "defaultValue") String arg1
) {
	return "Hello " + arg1;
}

5.7. 验证

Spring Shell 与 Bean 验证 API 集成以支持 命令参数的自动和自记录约束。spring-doc.cn

在命令参数上找到的注释和方法级别的注释是 honoured 并在命令执行之前触发验证。请考虑以下命令:spring-doc.cn

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

从前面的示例中,您可以免费获得以下行为:spring-doc.cn

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

5.8. 标签

Option Label 在 shell 本身中没有其他功能行为,除了 默认命令输出什么。在命令文档中 一种类型的 an option 被记录下来,但这并不总是非常有用。因此 您可能希望为选项提供更好的描述性词。helpspring-doc.cn

CommandRegistration.builder()
	.withOption()
		.longNames("arg1")
		.and()
	.withOption()
		.longNames("arg2")
		.label("MYLABEL")
		.and()
	.build();

然后,定义标签如 所示。helpspring-doc.cn

my-shell:>help mycommand
NAME
       mycommand -

SYNOPSIS
       mycommand --arg1 String --arg2 MYLABEL

OPTIONS
       --arg1 String
       [Optional]

       --arg2 MYLABEL
       [Optional]

5.9. 类型

本节讨论如何将特定数据类型用作选项值。spring-doc.cn

5.9.1. 字符串

String是最简单的类型,因为不涉及转换,因为 来自 User 的 inin 始终是一个字符串。spring-doc.cn

String example(@ShellOption(value = "arg1") String arg1) {
	return "Hello " + arg1;
}

虽然并不严格要求将 type 定义为 a,但它始终是 建议这样做。Stringspring-doc.cn

CommandRegistration.builder()
	.command("example")
	.withOption()
		.longNames("arg1")
		.type(String.class)
		.required()
		.and()
	.withTarget()
		.function(ctx -> {
			String arg1 = ctx.getOptionValue("arg1");
			return "Hello " + arg1;
		})
		.and()
	.build();

5.9.2. 布尔值

使用布尔类型稍微复杂一些,因为 there 和 where 后者可以是 null。布尔类型通常用作 表示参数值的标志可能不需要。booleanBooleanspring-doc.cn

String example(
	@ShellOption() boolean arg1,
	@ShellOption(defaultValue = "true") boolean arg2,
	@ShellOption(defaultValue = "false") boolean arg3,
	@ShellOption() Boolean arg4,
	@ShellOption(defaultValue = "true") Boolean arg5,
	@ShellOption(defaultValue = "false") Boolean arg6
) {
	return String.format("arg1=%s arg2=%s arg3=%s arg4=%s arg5=%s arg6=%s",
			arg1, arg2, arg3, arg4, arg5, arg6);
}
shell:>example
arg1=false arg2=true arg3=false arg4=false arg5=true arg6=false

shell:>example --arg4
arg1=false arg2=true arg3=false arg4=true arg5=true arg6=false

shell:>example --arg4 false
arg1=false arg2=true arg3=false arg4=false arg5=true arg6=false
CommandRegistration.builder()
	.command("example")
	.withOption()
		.longNames("arg1").type(boolean.class).and()
	.withOption()
		.longNames("arg2").type(boolean.class).defaultValue("true").and()
	.withOption()
		.longNames("arg3").type(boolean.class).defaultValue("false").and()
	.withOption()
		.longNames("arg4").type(Boolean.class).and()
	.withOption()
		.longNames("arg5").type(Boolean.class).defaultValue("true").and()
	.withOption()
		.longNames("arg6").type(Boolean.class).defaultValue("false").and()
	.withTarget()
		.function(ctx -> {
			boolean arg1 = ctx.hasMappedOption("arg1")
					? ctx.getOptionValue("arg1")
					: false;
			boolean arg2 = ctx.getOptionValue("arg2");
			boolean arg3 = ctx.getOptionValue("arg3");
			Boolean arg4 = ctx.getOptionValue("arg4");
			Boolean arg5 = ctx.getOptionValue("arg5");
			Boolean arg6 = ctx.getOptionValue("arg6");
			return String.format("Hello arg1=%s arg2=%s arg3=%s arg4=%s arg5=%s arg6=%s",
					arg1, arg2, arg3, arg4, arg5, arg6);
		})
		.and()
	.build();
shell:>example
arg1=false arg2=true arg3=false arg4=null arg5=true arg6=false

shell:>example --arg4
arg1=false arg2=true arg3=false arg4=true arg5=true arg6=false

shell:>example --arg4 false
arg1=false arg2=true arg3=false arg4=false arg5=true arg6=false

5.9.3. 数字

数字按原样转换。spring-doc.cn

String example(@ShellOption(value = "arg1") int arg1) {
	return "Hello " + arg1;
}
CommandRegistration.builder()
	.command("example")
	.withOption()
		.longNames("arg1")
		.type(int.class)
		.required()
		.and()
	.withTarget()
		.function(ctx -> {
			boolean arg1 = ctx.getOptionValue("arg1");
			return "Hello " + arg1;
		})
		.and()
	.build();

5.9.4. 枚举

如果给定的值与 enum 本身完全匹配,则可以转换为 enum。 目前,您可以转换不区分大小写的假设。spring-doc.cn

enum OptionTypeEnum {
	ONE,TWO,THREE
}
String example(@ShellOption(value = "arg1") OptionTypeEnum arg1) {
	return "Hello " + arg1;
}
CommandRegistration.builder()
	.command("example")
	.withOption()
		.longNames("arg1")
		.type(OptionTypeEnum.class)
		.required()
		.and()
	.withTarget()
		.function(ctx -> {
			OptionTypeEnum arg1 = ctx.getOptionValue("arg1");
			return "Hello " + arg1;
		})
		.and()
	.build();

5.9.5. 数组

数组可以按原样与字符串和基元类型一起使用。spring-doc.cn

String example(@ShellOption(value = "arg1") String[] arg1) {
	return "Hello " + arg1;
}
CommandRegistration.builder()
	.command("example")
	.withOption()
		.longNames("arg1")
		.type(String[].class)
		.required()
		.and()
	.withTarget()
		.function(ctx -> {
			String[] arg1 = ctx.getOptionValue("arg1");
			return "Hello " + arg1;
		})
		.and()
	.build();

using-shell-options.adoc 中未解决的指令 - include::using-shell-options-naming.adoc[]spring-doc.cn