Java使用JCommander實現(xiàn)解析命令行參數(shù)
前言
如果你想構(gòu)建一個支持命令行參數(shù)的程序,那么 jcommander 非常適合你,jcommander 是一個只有幾十 kb 的 Java 命令行參數(shù)解析工具,可以通過注解的方式快速實現(xiàn)命令行參數(shù)解析。
這篇教程會通過介紹 jcommadner ,快速的創(chuàng)建一個命令行程序,最后支持的命令參數(shù)功能如下圖。
這個命令行工具仿照 git 操作命令,主要提供了如下功能命令:
- 1.
git-app.jar -help
查看命令幫助信息。 - 2.
git-app.jar -version
查看當前版本號。 - 3.
git-app.jar clone http://xxxx
通過 URL 克隆一個倉庫。 - 4.
git-app.jar add file1 file2
暫存 file1 文件 file2 文件。 - 5.
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
注解進行參數(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?=?"克隆遠程倉庫數(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?=?"顯示當前版本號") private?boolean?version?=?false;
參數(shù)限制
clone
參數(shù)可以接受一個要克隆的 URL 鏈接,但是正常情況下只需要一個 URL 鏈接??梢酝ㄟ^ arity = 1
進行限制。
@Parameter(names?=?{"clone"}, ????description?=?"克隆遠程倉庫數(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
克隆遠程倉庫數(shù)據(jù)
help, -help, -h
查看幫助信息
version, -version, -v
顯示當前版本號
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?=?"顯示當前版本號", ????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?=?"克隆遠程倉庫數(shù)據(jù)", ????????order?=?3, ????????arity?=?1) ????private?String?cloneUrl; ????@Parameter(names?=?{"version",?"-version",?"-v"}, ????????description?=?"顯示當前版本號", ????????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,那么我們就要進行參數(shù)驗證,jcommander 也提供了特有的參數(shù)驗證方式。
1. 編寫參數(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?格式"); ????????} ????} }
2. clone
參數(shù)指定驗證類。
@Parameter(names?=?{"clone"}, ????description?=?"克隆遠程倉庫數(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)常會使用下面兩個命令。
1. git add file1 file2
暫存 file1 文件 file2 文件。
2. 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
總體測試
以上就是Java使用JCommander實現(xiàn)解析命令行參數(shù)的詳細內(nèi)容,更多關(guān)于Java JCommander解析命令行參數(shù)的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
關(guān)于Spring Cloud 本地屬性覆蓋的問題
這篇文章主要介紹了關(guān)于Spring Cloud 本地屬性覆蓋的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-03-03Hibernate validator使用以及自定義校驗器注解
這篇文章主要介紹了Hibernate validator使用以及自定義校驗器注解,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-01-01Hibernate傳入Java對象創(chuàng)建動態(tài)表并錄入數(shù)據(jù)
這篇文章主要介紹了Hibernate傳入Java對象創(chuàng)建動態(tài)表并錄入數(shù)據(jù),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-10-10Java中關(guān)鍵字final finally finalize的區(qū)別介紹
這篇文章主要給大家分享的是 Java中final,finally,finalize 到底有什么區(qū)別,文章圍繞final,finally,finalize的相關(guān)資料展開詳細內(nèi)容,具有一定的參考的價值,需要的朋友可以參考一下2022-04-04java按鈕控件數(shù)組實現(xiàn)計算器界面示例分享
本文主要介紹了JAVA通過按鈕數(shù)組來管理界面中的所有按鈕控件,從而使用最少的代碼實現(xiàn)模擬的計算器界面2014-02-02關(guān)于java數(shù)組與字符串相互轉(zhuǎn)換的問題
這篇文章主要介紹了java數(shù)組與字符串相互轉(zhuǎn)換的問題,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-10-10