JCommander解析命令行參數(shù)使用詳解
前言
如果你想構(gòu)建一個支持命令行參數(shù)的程序,那么 jcommander 非常適合你,jcommander 是一個只有幾十 kb 的 Java 命令行參數(shù)解析工具,可以通過注解的方式快速實現(xiàn)命令行參數(shù)解析。
這篇教程會通過介紹 jcommadner ,快速的創(chuàng)建一個命令行程序,最后支持的命令參數(shù)功能如下圖。

這個命令行工具仿照 git 操作命令,主要提供了如下功能命令:
git-app.jar -help查看命令幫助信息。git-app.jar -version查看當(dāng)前版本號。git-app.jar clone http://xxxx通過 URL 克隆一個倉庫。git-app.jar add file1 file2暫存 file1 文件 file2 文件。git-app.jar commit -m "注釋"提交并添加注釋。
jcommander 引入
截止文章編寫時間,最新版本如下:
<!-- https://mvnrepository.com/artifact/com.beust/jcommander -->
<dependency>
<groupId>com.beust</groupId>
<artifactId>jcommander</artifactId>
<version>1.82</version>
</dependency>jcommander 參數(shù)綁定
命令行解析中,參數(shù)解析與綁定是最實用的一個場景,jcommander 使用 Parameter 注解進(jìn)行參數(shù)綁定。我們定義一個 GitCommandOptions.java 類來測試參數(shù)綁定。
package com.wdbyte.jcommander.v1;
import com.beust.jcommander.Parameter;
/**
* @author https://www.wdbyte.com
*/
public class GitCommandOptions {
@Parameter(names = {"clone"},
description = "克隆遠(yuǎn)程倉庫數(shù)據(jù)")
private String cloneUrl;
public String getCloneUrl() {
return cloneUrl;
}
}使用 jcommander 結(jié)合 GitCommandOptions 來解析參數(shù)。
package com.wdbyte.jcommander.v1;
import com.beust.jcommander.JCommander;
/**
* @author https://www.wdbyte.com
*/
public class GitApp {
public static void main(String[] args) {
// args = new String[]{"clone","http://www.wdbyte.com/test.git"};
GitCommandOptions gitCommandOptions = new GitCommandOptions();
JCommander commander = JCommander.newBuilder()
.addObject(gitCommandOptions)
.build();
commander.parse(args);
System.out.println("clone " + gitCommandOptions.getCloneUrl());
}
}打包后可以執(zhí)行命令參數(shù):
$ java -jar git-app.jar clone http://www.wdbyte.com/test.git clone http://www.wdbyte.com/test.git
這里是一個字符串參數(shù),需要在命令中輸出參數(shù)值,對于 boolean 類型的參數(shù),不需要傳值,有命令即為 true 值。
參數(shù)名稱
@Parameter 注解中的 names 屬性可以定義參數(shù)的名稱。且可以指定多個參數(shù)名稱,讓我再添加 version 參數(shù)和 help 參數(shù),同時設(shè)置參數(shù)別名。這兩個參數(shù)是 boolean 類型。
@Parameter(names = {"help", "-help", "-h"},
description = "查看幫助信息",
help = true)
private boolean help;
@Parameter(names = {"version", "-version", "-v"},
description = "顯示當(dāng)前版本號")
private boolean version = false;參數(shù)限制
clone 參數(shù)可以接受一個要克隆的 URL 鏈接,但是正常情況下只需要一個 URL 鏈接。可以通過 arity = 1 進(jìn)行限制。
@Parameter(names = {"clone"},
description = "克隆遠(yuǎn)程倉庫數(shù)據(jù)",
arity = 1)
private String cloneUrl;幫助信息
使用 usage() 參數(shù)可以打印命令幫助信息。
GitCommandOptions gitCommandOptions = new GitCommandOptions();
JCommander commander = JCommander.newBuilder()
.addObject(gitCommandOptions)
.build();
commander.parse(args);
// 打印幫助信息
commander.usage();運行輸出幫助信息:
$ java -jar git-app.jar
Usage: <main class> [options]
Options:
clone
克隆遠(yuǎn)程倉庫數(shù)據(jù)
help, -help, -h
查看幫助信息
version, -version, -v
顯示當(dāng)前版本號
Default: false雖然正確的輸出了幫助信息,但是其中有 main class 這段,是因為我們沒有指定項目名稱,我們指定項目名稱為 git-app。
JCommander commander = JCommander.newBuilder()
.programName("git-app")
.addObject(gitCommandOptions)
.build();參數(shù)排序
在幫助信息中,如果想要自定義參數(shù)順序,可以通過 order = 來排序,數(shù)字越小越靠前。
@Parameter(names = {"version", "-version", "-v"},
description = "顯示當(dāng)前版本號",
order = 2)
private boolean version = false;參數(shù)綁定完整測試
package com.wdbyte.jcommander.v2;
import com.beust.jcommander.Parameter;
/**
* @author https://www.wdbyte.com
*/
public class GitCommandOptions {
@Parameter(names = {"help", "-help", "-h"},
description = "查看幫助信息",
order = 1,
help = true)
private boolean help;
@Parameter(names = {"clone"},
description = "克隆遠(yuǎn)程倉庫數(shù)據(jù)",
order = 3,
arity = 1)
private String cloneUrl;
@Parameter(names = {"version", "-version", "-v"},
description = "顯示當(dāng)前版本號",
order = 2)
private boolean version = false;
//...get method
}GitApp.java
package com.wdbyte.jcommander.v2;
import com.beust.jcommander.JCommander;
public class GitApp {
public static void main(String[] args) {
GitCommandOptions gitCommandOptions = new GitCommandOptions();
JCommander commander = JCommander.newBuilder()
.programName("git-app")
.addObject(gitCommandOptions)
.build();
commander.parse(args);
// 打印幫助信息
if (gitCommandOptions.isHelp()) {
commander.usage();
return;
}
if (gitCommandOptions.isVersion()) {
System.out.println("git version 2.24.3 (Apple Git-128)");
return;
}
if (gitCommandOptions.getCloneUrl() != null) {
System.out.println("clone " + gitCommandOptions.getCloneUrl());
}
}
}運行測試:

jcommander 參數(shù)驗證
在上面的例子中, 假設(shè) clone 命令傳入的參數(shù)必須是一個 URL,那么我們就要進(jìn)行參數(shù)驗證,jcommander 也提供了特有的參數(shù)驗證方式。
編寫參數(shù)驗證類,需要實現(xiàn) IParameterValidator 接口。
package com.wdbyte.jcommander.v3;
import java.net.MalformedURLException;
import java.net.URL;
import com.beust.jcommander.IParameterValidator;
import com.beust.jcommander.ParameterException;
/**
* @author https://www.wdbyte.com
*/
public class UrlParameterValidator implements IParameterValidator {
@Override
public void validate(String key, String value) throws ParameterException {
try {
new URL(value);
} catch (MalformedURLException e) {
throw new ParameterException("參數(shù) " + key + " 的值必須是 URL 格式");
}
}
}clone 參數(shù)指定驗證類。
@Parameter(names = {"clone"},
description = "克隆遠(yuǎn)程倉庫數(shù)據(jù)",
validateWith = UrlParameterValidator.class,
order = 3,
arity = 1)
private String cloneUrl;運行測試:
$ java -jar git-app.jar clone https://www.wdbyte.com/test.git clone https://www.wdbyte.com/test.git $ java -jar git-app.jar clone test.git Exception in thread "main" com.beust.jcommander.ParameterException: 參數(shù) clone 的值必須是 URL 格式 at com.wdbyte.jcommander.v3.UrlParameterValidator.validate(UrlParameterValidator.java:19) at com.beust.jcommander.ParameterDescription.validateParameter(ParameterDescription.java:377) at com.beust.jcommander.ParameterDescription.validateParameter(ParameterDescription.java:344)
jcommander 子命令
在使用 git 時,我們經(jīng)常會使用下面兩個命令。
git add file1 file2暫存 file1 文件 file2 文件。git commit -m "注釋"提交并添加注釋。
什么是子命令
這是一種很常見的操作,git commit 除了可以跟 -m 子參數(shù)外,還可以跟各種參數(shù),通過 git 幫助文檔可以看到。
git commit [-a | --interactive | --patch] [-s] [-v] [-u<mode>] [--amend]
[--dry-run] [(-c | -C | --fixup | --squash) <commit>]
[-F <file> | -m <msg>] [--reset-author] [--allow-empty]
[--allow-empty-message] [--no-verify] [-e] [--author=<author>]
[--date=<date>] [--cleanup=<mode>] [--[no-]status]
[-i | -o] [-S[<keyid>]] [--] [<file>...]這種有子參數(shù)的情況,我們可以稱 commit 為 git 的一個子命令,使用 jcommander 如何配置子命令呢?
jcommander 子命令實現(xiàn)
我們新增子命令對應(yīng)的參數(shù)類 GitCommandCommit.java.
package com.wdbyte.jcommander;
import com.beust.jcommander.Parameter;
import com.beust.jcommander.Parameters;
/**
* git commit -m "desc"
* @author https://www.wdbyte.com
*/
@Parameters(commandDescription = "提交文件", commandNames = "commit")
public class GitCommandCommit {
public static final String COMMAND = "commit";
@Parameter(names = {"-comment", "-m"},
description = "請輸入注釋",
arity = 1,
required = true)
private String comment;
public String getComment() {
return comment;
}
}代碼中使用 @Parameters 注解指定了子命令為 commit,同時使用 @Paramete 注解指定子參數(shù) -m,同時 -m 參數(shù)是必須的,使用屬性 required = true 來指定。
使用 GitCommandCommit:
使用 addCommand 添加 Commit 命令參數(shù)類。
GitCommandOptions gitCommandOptions = new GitCommandOptions();
GitCommandCommit commandCommit = new GitCommandCommit();
JCommander commander = JCommander.newBuilder()
.programName("git-app")
.addObject(gitCommandOptions)
.addCommand(commandCommit)
.build();
commander.parse(args);
String parsedCommand = commander.getParsedCommand();
if ("commit".equals(parsedCommand)) {
System.out.println(commandCommit.getComment());
}運行測試:
$ java -jar git-app.jar commit -m '注釋一下' 注釋一下
同上,我們可以添加 add 命令對應(yīng)的參數(shù)類:GitCommandAdd.java. 這次我們定義一個 List 類型參數(shù),但是不在屬性上指定子參數(shù)名稱。
package com.wdbyte.jcommander.v5;
import java.util.List;
import com.beust.jcommander.Parameter;
import com.beust.jcommander.Parameters;
/**
* git add file1 file2
*
* @author https://www.wdbyte.com
*/
@Parameters(commandDescription = "暫存文件", commandNames = "add", separators = " ")
public class GitCommandAdd {
public static final String COMMAND = "add";
@Parameter(description = "暫存文件列表")
private List<String> files;
public List<String> getFiles() {
return files;
}
}同樣添加到子命令:
JCommander commander = JCommander.newBuilder()
.programName("git-app")
.addObject(gitCommandOptions)
.addCommand(commandCommit)
.addCommand(commandAdd)
.build();
commander.parse(args);
if ("add".equals(parsedCommand)) {
for (String file : commandAdd.getFiles()) {
System.out.println("暫存文件:" + file);
}
}運行測試:
$ java -jar git-app.jar add file1.txt file2.txt 暫存文件:file1.txt 暫存文件:file2.txt
jcommander 參數(shù)轉(zhuǎn)換
在上面的 GitCommandAdd 代碼中,add 命令傳入的都是文件路徑,現(xiàn)在是使用 List<String> 來接收入?yún)?,通常情況想我們可能需要直接轉(zhuǎn)換成方便操作的類型,如 File 或者 Path,這該如何方面的轉(zhuǎn)換呢,jcommander 也提供了方便轉(zhuǎn)換類。
首先編寫一個轉(zhuǎn)換類 FilePathConverter 用于把入?yún)⑥D(zhuǎn)換成 Path 類,同時校驗文件是否存在
package com.wdbyte.jcommander;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import com.beust.jcommander.IStringConverter;
import com.beust.jcommander.ParameterException;
/**
*
* @author https://www.wdbyte.com
*/
public class FilePathConverter implements IStringConverter<Path> {
@Override
public Path convert(String filePath) {
Path path = Paths.get(filePath);
if (Files.exists(path)) {
return path;
}
throw new ParameterException(String.format("文件不存在,path:%s", filePath));
}
}通過注解指定轉(zhuǎn)換類:
@Parameter(description = "暫存文件列表", converter = FilePathConverter.class) private List<Path> files;
打包測試:
$ java -jar git-app.jar add file1 file2 文件不存在,path:file1 $ ls -l total 12448 drwxr-xr-x 2 darcy staff 64B 6 15 21:10 archive-tmp drwxr-xr-x 3 darcy staff 96B 6 15 21:10 classes drwxr-xr-x 3 darcy staff 96B 6 15 21:10 generated-sources -rw-r--r-- 1 darcy staff 5.6M 6 16 20:44 git-app.jar $ git-app.jar git-app.jar 暫存文件:git-app.jar
總體測試

一如既往,文章代碼都存放在 Github.com/niumoo/javaNotes.
相關(guān)文章
Java Builder Pattern建造者模式詳解及實例
這篇文章主要介紹了Java Builder Pattern建造者模式詳解及實例的相關(guān)資料,需要的朋友可以參考下2017-01-01
@Bean注解和@Configuration、@Component注解組合使用的區(qū)別
這篇文章主要介紹了@Bean注解和@Configuration、@Component注解組合使用的區(qū)別,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-11-11
IDEA啟動tomcat項目報錯53820 socket closed問題及解決
IDEA啟動Tomcat項目時報錯,原因是IDEA關(guān)閉時Tomcat未正常關(guān)閉,導(dǎo)致端口被占用,解決方法是通過任務(wù)管理器關(guān)閉占用高內(nèi)存的Java進(jìn)程,通常是IDEA進(jìn)程下面的,或者使用命令行找到PID并強制終止進(jìn)程2024-12-12
Java模擬HTTP Get Post請求實現(xiàn)論壇自動回帖功能
這篇文章主要介紹了Java模擬HTTP Get Post請求實現(xiàn)論壇自動回帖功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-09-09

