java应用中,经常需要向main方法传递参数(String[] args),比如:
java -jar test.jar arg1 arg2 arg3
# 其中test.jar是jar包名,arg1、arg2、arg3是要传递的参数
但是有时候需要向main方法传递命令行参数(比如不同命令行参数实现不同的处理逻辑),比如:
java -jar test.jar -a 6 -s 6 -m 10 -d 8
# 其中test.jar是jar包名,-a是命令行参数(其后的6是参数值),以此类推
这时候就需要对传递的命令行参数进行解析,再针对不同的解析结果设置不同的处理逻辑。
示例:
java应用需要根据传递的命令行参数来实现四则运算(加减乘除,只针对整数):
- 代码中会定义一个int num = 6;
- 命令行参数-a 1:加号,打印num+1;
- 命令行参数-s 1:减号,打印num-1;
- 命令行参数-m 1:乘号,打印num*1;
- 命令行参数-d 1:除号,打印num/1;
实现过程:
apache commons-cli依赖包是一个专门用于解析命令行参数的包,其中几个比较重要的类或者接口包括:
- Option:对应一个命令行参数(包括参数名缩写、参数名全称、参数描述等);
- Options:Option组成的集合,能够完成Option对象的添加、删除等操作;
- CommandLine:对应一个命令行对象,能够获取其中包含的参数名、参数值等;
- CommandLineParser:将Options对象解析成CommandLine对象;
- HelpFormatter:CommandLineParser解析出现异常时,打印帮助信息;
程序执行顺序如下:
- 根据命令行参数定义Option对象;
- 将Option对象添加到Options中;
- CommandLineParser解析传递给main方法的args得到CommandLine对象;
- 根据CommandLine对象包含的命令行参数设定处理逻辑。
详细代码:
<!-- pom.xml中添加commons-cli依赖 -->
<dependency>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
<version>1.4</version>
</dependency>
package com.example.cmdoption;
import org.apache.commons.cli.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TestMain {
public static void main(String[] args){
// 根据命令行参数定义Option对象,第1/2/3/4个参数分别是指命令行参数名缩写、参数名全称、是否有参数值、参数描述
Option opt1 = new Option("a","add",true,"add operation");
opt1.setRequired(false);
Option opt2 = new Option("s","subtract",true,"subbstract operation");
opt2.setRequired(false); // 设置该参数是否是必须的
Option opt3 = new Option("m","multiply",true,"multiply operation");
opt3.setRequired(false);
Option opt4 = new Option("d","divide",true,"divide operation");
opt4.setRequired(false);
Options options = new Options();
options.addOption(opt1);
options.addOption(opt2);
options.addOption(opt3);
options.addOption(opt4);
CommandLine cli = null;
CommandLineParser cliParser = new DefaultParser();
HelpFormatter helpFormatter = new HelpFormatter();
try {
cli = cliParser.parse(options, args);
} catch (ParseException e) {
// 解析失败是用 HelpFormatter 打印 帮助信息
helpFormatter.printHelp(">>>>>> test cli options", options);
e.printStackTrace();
}
//根据不同参数执行不同逻辑
int num = 6;
if (cli.hasOption("a")){
int a = Integer.parseInt(cli.getOptionValue("a","1")); // 获取参数“a”对应的参数值,如果为空则返回1(默认值)
System.out.println(String.format(">>>>>> add operation, %s+%s=%s", num, a, num+a));
}
if(cli.hasOption("s")){
int a = Integer.parseInt(cli.getOptionValue("s","1"));
System.out.println(String.format(">>>>>> subtract operation, %s-%s=%s", num, a, num-a));
}
if(cli.hasOption("m")){
int a = Integer.parseInt(cli.getOptionValue("m","1"));
System.out.println(String.format(">>>>>> multiply operation, %s*%s=%s", num, a, num*a));
}
if(cli.hasOption("d")){
int a = Integer.parseInt(cli.getOptionValue("d","1"));
System.out.println(String.format(">>>>>> divide operation, %s/%s=%s", num, a, num/a));
}
}
}
测试结果:
1. shell中运行jar并添加命令行参数:
java -jar demo-0.0.1-SNAPSHOT.jar -a 6 -s 6 -m 10 -d 8
结果:
10:52:08.684 [main] INFO com.example.cmdoption.TestMain - >>>>>> add operation, 6+6=12
10:52:08.692 [main] INFO com.example.cmdoption.TestMain - >>>>>> subtract operation, 6-6=0
10:52:08.692 [main] INFO com.example.cmdoption.TestMain - >>>>>> multiply operation, 6*10=60
10:52:08.692 [main] INFO com.example.cmdoption.TestMain - >>>>>> divide operation, 6/8=0
2. 命令行参数名可以用全称,比如:
java -jar demo-0.0.1-SNAPSHOT.jar -a 6 --subtract 6 -m 10 -d 8
3. 测试下解析命令行参数异常时,HelpFormatter打印帮助信息:
java -jar demo-0.0.1-SNAPSHOT.jar -a 6 -s -m 10 -d 8
结果:
usage: >>>>>> test cli options
-a,--add <arg> add operation
-d,--divide <arg> divide operation
-m,--multiply <arg> multiply operation
-s,--subtract <arg> subbstract operation
org.apache.commons.cli.MissingArgumentException: Missing argument for option: s
at org.apache.commons.cli.DefaultParser.checkRequiredArgs(DefaultParser.java:211)
......