Analýza parametrov príkazového riadku s JCommander

1. Prehľad

V tomto návode Naučíme sa, ako používať JCommander na analýzu parametrov príkazového riadku. Pri vytváraní jednoduchej aplikácie príkazového riadku preskúmame niekoľko jej funkcií.

2. Prečo JCommander?

"Pretože život je príliš krátky na to, aby sa dali analyzovať parametre príkazového riadku" - Cédric Beust

JCommander, ktorý vytvoril Cédric Beust, je knižnica založená na anotáciách presyntaktická analýza parametrov príkazového riadku. Môže to znížiť úsilie pri vytváraní aplikácií príkazového riadku a pomôcť nám im zaistiť dobrý užívateľský dojem.

S JCommanderom môžeme odložiť zložité úlohy, ako je syntaktická analýza, overenie a typové konverzie, aby sme sa mohli sústrediť na našu aplikačnú logiku.

3. Nastavenie JCommanderu

3.1. Konfigurácia Maven

Začnime pridaním jcommander závislosť v našom pom.xml:

 com.beust jcommander 1.78 

3.2. Ahoj svet

Vytvorme jednoduchý HelloWorldApp , ktorý má jediný vstup s názvom názov a vytlačí pozdrav, "Ahoj ".

Odkedy JCommander viaže argumenty príkazového riadku na polia v triede Java, najskôr definujeme a HelloWorldArgs trieda s poľom názov s poznámkou @Parameter:

trieda HelloWorldArgs {@Parameter (names = "--name", description = "User name", required = true) private String name; }

Teraz použijeme JCommander triedy na analýzu argumentov príkazového riadku a na priradenie polí k nášmu HelloWorldArgs objekt:

HelloWorldArgs jArgs = nový HelloWorldArgs (); JCommander helloCmd = JCommander.newBuilder () .addObject (jArgs) .build (); helloCmd.parse (args); System.out.println ("Dobrý deň" + jArgs.getName ());

Nakoniec vyvolajme hlavnú triedu rovnakými argumentmi z konzoly:

$ java HelloWorldApp - názov JavaWorld Dobrý deň, JavaWorld

4. Vytvorenie skutočnej aplikácie v JCommander

Teraz, keď už sme v prevádzke, zvážme zložitejší prípad použitia - klienta API príkazového riadku, ktorý interaguje s fakturačnou aplikáciou, ako je Stripe, najmä s scenárom fakturácie Metered (alebo na základe použitia). Táto fakturačná služba tretej strany spravuje naše predplatné a fakturáciu.

Predstavme si, že prevádzkujeme firmu SaaS, v rámci ktorej si naši zákazníci kupujú predplatné našich služieb a účtuje sa im počet volaní API do našich služieb mesačne. U klienta vykonáme dve operácie:

  • Predložiť: Zadajte množstvo a jednotkovú cenu použitia pre zákazníka oproti danému predplatnému
  • aportovať: Načítanie poplatkov pre zákazníka na základe spotreby niektorých alebo všetkých ich predplatných v aktuálnom mesiaci - tieto poplatky môžeme získať agregované za všetky predplatné alebo rozčlenené podľa jednotlivých predplatných.

Budeme stavať klienta API, keď prechádzame funkciami knižnice.

Poďme začať!

5. Definovanie parametra

Začnime definovaním parametrov, ktoré môže naša aplikácia používať.

5.1. The @Parameter Anotácia

Anotácia poľa s @Parameter povie JCommander, aby na ňu naviazal zodpovedajúci argument príkazového riadku. @Parameter má atribúty popisujúce hlavný parameter, ako napríklad:

  • mená - jeden alebo viac mien možnosti, napríklad „–name“ alebo „-n“
  • popis - význam tejto možnosti, ktorý má pomôcť koncovému používateľovi
  • požadovaný - či je možnosť povinná, predvolené je - nepravdivé
  • arity - počet ďalších parametrov, ktoré možnosť spotrebúva

Poďme nakonfigurovať parameter customerId v našom scenári merania fakturácie:

@Parameter (names = {"--customer", "-C"}, description = "ID zákazníka využívajúceho služby", arity = 1, required = true) String customerId; 

Teraz vykonajme náš príkaz s novým parametrom „–zákazník“:

$ java aplikácia - zákazník cust0000001A Prečítajte si ID zákazníka: cust0000001A. 

Rovnako môžeme na dosiahnutie rovnakého efektu použiť kratší parameter „-C“:

$ java aplikácia -C cust0000001A Prečítajte si ID zákazníka: cust0000001A. 

5.2. Požadované parametre

Ak je parameter povinný, aplikácia ukončí vrhanie a Výnimka parametra ak to užívateľ neurčí:

$ java Výnimka aplikácie vo vlákne "main" com.beust.jcommander.ParameterException: Vyžaduje sa nasledujúca možnosť: [--customer | -C]

Mali by sme poznamenať, že vo všeobecnosti akákoľvek chyba pri analýze parametrov má za následok a Výnimka parametra v JCommander.

6. Vstavané typy

6.1. IStringConverter Rozhranie

JCommander vykonáva typovú konverziu z príkazového riadku String vstup do typov Java v našich triedach parametrov. The IStringConverter rozhranie spracováva typovú konverziu parametra z String na ľubovoľný ľubovoľný typ. Toto rozhranie teda implementujú všetky vstavané prevádzače JCommander.

Po vybalení z krabice prichádza JCommander s podporou bežných dátových typov ako napr String, Celé číslo, Boolovský, BigDecimala Enum.

6.2. Single-Arity typy

Arity súvisí s počtom ďalších parametrov, ktoré opcia spotrebuje. JCommander vstavané typy parametrov majú predvolenú arititu jednej, okrem Boolovský a Zoznam. Preto bežné typy ako napr String, Celé číslo, BigDecimal, Dlhé, a Enum, sú jednoaritné typy.

6.3. Boolovský Typ

Polia typu boolovský alebo Boolovský nepotrebujete žiadny ďalší parameter - tieto možnosti majú arity nula.

Pozrime sa na príklad. Možno by sme chceli vyzdvihnúť poplatky pre zákazníka, rozdelené podľa predplatného. Môžeme pridať a boolovský lúka podrobne rozpísané, ktorý je nepravdivé predvolene:

@Parameter (names = {"--itemized"}) private boolean itemized; 

Naša aplikácia vráti agregované poplatky s podrobne rozpísané nastavený na nepravdivé. Keď vyvoláme príkazový riadok pomocou podrobne rozpísané parameter sme nastavili pole na pravda:

$ java App --itemized Čítanie príznaku do položiek: true. 

To funguje dobre, pokiaľ nemáme prípad použitia, keď vždy chceme podrobne rozpísané poplatky, pokiaľ nie je uvedené inak. Mohli by sme zmeniť parameter na notItemized, ale mohlo by byť jasnejšie vedieť poskytnúť nepravdivé ako hodnota podrobne rozpísané.

Predstavme toto správanie pomocou predvolenej hodnoty pravda pre pole a jeho nastavenie arity ako jeden:

@Parameter (names = {"--itemized"}, arity = 1) private boolean itemized = true; 

Keď teraz zadáme možnosť, hodnota sa nastaví na nepravdivé:

$ java App --itemized false Čítanie príznaku do položiek: false. 

7. Zoznam Typy

JCommander poskytuje niekoľko spôsobov záväzných argumentov Zoznam polia.

7.1. Viacnásobné zadanie parametra

Predpokladajme, že chceme načítať poplatky iba za podmnožinu predplatného zákazníka:

@Parameter (names = {"--subscription", "-S"}) private List subscriptionIds; 

Toto pole nie je povinné a ak parameter nie je uvedený, aplikácia by načítala poplatky za všetky predplatné. Môžeme však určiť viac odberov viacnásobným použitím názvu parametra:

$ java Aplikácia -S predplatnéA001 -S predplatnéA002 -S predplatnéA003 Prečítajte si predplatné: [subscriptionA001, subscriptionA002, subscriptionA003]. 

7.2. Viazanie Zoznamy Pomocou rozdeľovača

Namiesto toho, aby sme zadali túto voľbu viackrát, skúsme zoznam spojiť zadaním čiarky String:

$ java App -S subscriptionA001, subscriptionA002, subscriptionA003 Prečítajte si predplatné: [subscriptionA001, subscriptionA002, subscriptionA003]. 

Na vyjadrenie zoznamu sa používa jedna hodnota parametra (arity = 1). JCommander použije triedu CommaParameterSplitter viazať oddelené čiarkou String k nášmu Zoznam.

7.3. Viazanie Zoznamy Používanie vlastného rozdeľovača

Predvolený rozdeľovač môžeme prepísať implementáciou IParameterSplitter rozhranie:

trieda ColonParameterSplitter implementuje IParameterSplitter {@Override public List split (hodnota reťazca) {return asList (value.split (":")); }}

A potom mapovanie implementácie do rozdeľovač atribút v @Parameter:

@Parameter (names = {"--subscription", "-S"}, splitter = ColonParameterSplitter.class) private List subscriptionIds; 

Vyskúšajme to:

$ java App -S „subscriptionA001: subscriptionA002: subscriptionA003“ Prečítajte si predplatné: [subscriptionA001, subscriptionA002, subscriptionA003]. 

7.4. Variabilné Arity Zoznamy

Variabilná aritita nám umožňuje deklarovaťzoznamy, ktoré môžu mať neobmedzené parametre, až po ďalšiu možnosť. Môžeme nastaviť atribút variableArity ako pravda na spresnenie tohto správania.

Skúsme to analyzovať predplatné:

@Parameter (names = {"--subscription", "-S"}, variableArity = true) private List subscriptionIds; 

A keď spustíme náš príkaz:

$ java App -S subscriptionA001 subscriptionA002 subscriptionA003 --itemized Read Subscriptions: [subscriptionA001, subscriptionA002, subscriptionA003]. 

JCommander naviaže všetky vstupné argumenty nasledujúce po voľbe „-S“ na pole zoznamu, až do ďalšej voľby alebo do konca príkazu.

7.5. Pevné arity Zoznamy

Doteraz sme videli neobmedzené zoznamy, kde môžeme odovzdať toľko položiek zoznamu, koľko si prajeme. Niekedy možno budeme chcieť obmedziť počet položiek odovzdaných do a Zoznam lúka. Aby sme to dosiahli, môžeme zadajte celočíselnú hodnotu arity pre a Zoznam lúkaaby to bolo ohraničené:

@Parameter (names = {"--subscription", "-S"}, arity = 2) private List subscriptionIds; 

Fixná aritma vynúti kontrolu počtu parametrov odovzdaných a Zoznam možnosť a hodí a Výnimka parametra v prípade porušenia:

$ java App -S subscriptionA001 subscriptionA002 subscriptionA003 Bol odovzdaný hlavný parameter 'subscriptionA003', ale vo vašej triede arg nebol definovaný žiadny hlavný parameter 

Chybové hlásenie naznačuje, že keďže JCommander očakával iba dva argumenty, pokúsil sa ako ďalšiu možnosť analyzovať ďalší vstupný parameter „subscriptionA003“.

8. Vlastné typy

Môžeme tiež viazať parametre písaním vlastných prevádzačov. Rovnako ako vstavané prevádzače, aj vlastné prevádzače musia implementovať IStringConverter rozhranie.

Napíšme prevodník na analýzu časovej pečiatky ISO8601:

trieda ISO8601TimestampConverter implementuje IStringConverter {private static final DateTimeFormatter TS_FORMATTER = DateTimeFormatter.ofPattern ("uuuu-MM-dd'T'HH: mm: ss"); @Override public Okamžitý prevod (hodnota reťazca) {try {return LocalDateTime .parse (value, TS_FORMATTER) .atOffset (ZoneOffset.UTC) .toInstant (); } catch (DateTimeParseException e) {throw new ParameterException ("Invalid timestamp"); }}} 

Tento kód analyzuje vstup String a vrátiť Okamžité, hádzanie a Výnimka parametra ak dôjde k chybe konverzie. Tento prevodník môžeme použiť tak, že ho naviažeme na pole typu Okamžité pomocou prevodník atribút v @Parameter:

@Parameter (names = {"--timestamp"}, prevádzač = ISO8601TimestampConverter.class) súkromná časová pečiatka; 

Pozrime sa na to v akcii:

$ java aplikácia - časová pečiatka 2019-10-03T10: 58: 00 Čítať časovú pečiatku: 2019-10-03T10: 58: 00Z.

9. Overenie parametrov

JCommander poskytuje niekoľko predvolených overení:

  • či sú dodané požadované parametre
  • ak sa počet zadaných parametrov zhoduje s aritou poľa
  • či už každý String parameter možno previesť na typ príslušného poľa

Navyše, možno budeme chcieť pridať vlastné overenia. Predpokladajme napríklad, že ID zákazníka musia byť UUID.

Môžeme napísať validátor pre pole zákazníka, ktoré implementuje rozhranie IParameterValidator:

trieda UUIDValidator implementuje IParameterValidator {private static final String UUID_REGEX = "[0-9a-fA-F] {8} (- [0-9a-fA-F] {4}) {3} - [0-9a-fA- F] {12} "; @Override public void validate (názov reťazca, hodnota reťazca) vyvolá ParameterException {if (! IsValidUUID (hodnota)) {vyvolať nový ParameterException ("parameter reťazca" + hodnota + "nie je platný UUID."); }} private boolean isValidUUID (hodnota reťazca) {return Pattern.compile (UUID_REGEX) .matcher (hodnota) .matches (); }} 

Potom to môžeme pripojiť pomocou overiť s atribút parametra:

@Parameter (names = {"--customer", "-C"}, validateWith = UUIDValidator.class) private String customerId; 

Ak príkaz vyvoláme s ID zákazníka bez UUID, aplikácia sa ukončí so správou o zlyhaní overenia:

$ java App --C customer001 Parameter reťazca customer001 nie je platný UUID. 

10. Podpríkazy

Teraz, keď sme sa dozvedeli o viazaní parametrov, vytvorme naše príkazy všetko dohromady.

V JCommander môžeme podporovať viac príkazov, ktoré sa nazývajú podpríkazy, každý s odlišnou sadou možností.

10.1. @Parametre Anotácia

Môžeme použiť @Parametre definovať podpríkazy. @Parametre obsahuje atribút commandNames na identifikáciu príkazu.

Poďme modelovať Predložiť a aportovať ako podpríkazy:

@Parameters (commandNames = {"submit"}, commandDescription = "Odoslať využitie pre daného zákazníka a predplatné," + "akceptuje jednu položku použitia") trieda SubmitUsageCommand {// ...} @Parameters (commandNames = {"načítať") }, commandDescription = "Načítať poplatky pre zákazníka v aktuálnom mesiaci," + "je možné rozdeliť na jednotlivé položky alebo agregovať") triedy FetchCurrentChargesCommand {// ...} 

JCommander používa atribúty v @Parametre nakonfigurovať podpríkazy, ako napríklad:

  • commandNames - názov velenia; viaže argumenty príkazového riadku na triedu s poznámkami @Parametre
  • commandDescription - dokumentuje účel podriadeného príkazu

10.2. Pridávanie čiastkových príkazov do JCommander

Pridávame podpríkazy do JCommander s addCommand metóda:

SubmitUsageCommand submitUsageCmd = nový SubmitUsageCommand (); FetchCurrentChargesCommand fetchChargesCmd = nový FetchCurrentChargesCommand (); JCommander jc = JCommander.newBuilder () .addCommand (submitUsageCmd) .addCommand (fetchChargesCmd) .build (); 

The addCommand metóda registruje podpríkazy s ich príslušnými názvami, ako je uvedené v commandNames atribút @Parametre anotácia.

10.3. Analýza čiastkových príkazov

Aby sme mali prístup k voľbe príkazu používateľom, musíme najskôr analyzovať argumenty:

jc.parse (args); 

Ďalej môžeme subpríkaz extrahovať pomocou getParsedCommand:

Reťazec parsedCmdStr = jc.getParsedCommand (); 

Okrem identifikácie príkazu JCommander viaže zvyšok parametrov príkazového riadku na ich polia v podpríkaze. Teraz musíme zavolať príkaz, ktorý chceme použiť:

switch (parsedCmdStr) {case "submit": submitUsageCmd.submit (); prestávka; prípad "načítanie": fetchChargesCmd.fetch (); prestávka; predvolené: System.err.println ("Neplatný príkaz:" + parsedCmdStr); } 

11. Pomocník používania JCommander

Môžeme sa dovolať použitie na vykreslenie sprievodcu používaním. Toto je súhrn všetkých možností, ktoré naša aplikácia spotrebúva. V našej aplikácii môžeme vyvolať použitie na hlavný príkaz alebo alternatívne na každý z dvoch príkazov „odoslať“ a „načítať“ osobitne.

Displej používania nám môže pomôcť niekoľkými spôsobmi: zobrazením možností pomoci a počas spracovania chýb.

11.1. Zobrazujú sa možnosti pomoci

Možnosť pomoci môžeme v našich príkazoch viazať pomocou a boolovský spolu s atribútom Pomoc nastavený na pravda:

@Parameter (names = "--help", help = true) súkromná logická pomoc; 

Potom môžeme zistiť, či v argumentoch bola poskytnutá „–pomoc“, a zavolať použitie:

if (cmd.help) {jc.usage (); } 

Pozrime sa na výstup pomocníka pre náš podriadený príkaz „submit“:

$ java App submit --help Použitie: odoslať [možnosti] Možnosti: * --zákazník, -C ID zákazníka, ktorý využíva služby * --subscription, -S Id zakúpeného predplatného * - množstvo Použité množstvo ; nahlásené množstvo sa pripočíta za fakturačné obdobie * --pricing-type, -P Cenový typ nahláseného použitia (hodnoty: [PRE_RATED, UNRATED]) * --timestamp Časová známka udalosti použitia, musí ležať v aktuálnom fakturačnom období - -cena Ak je PRE_RATED, jednotková cena sa má uplatniť na jednotku vykázaného množstva použitia 

The použitie metóda používa @Parameter atribúty ako napr popis zobraziť užitočné zhrnutie. Parametre označené hviezdičkou (*) sú povinné.

11.2. Spracovanie chyby

Môžeme chytiť Výnimka parametra a zavolaj použitie pomôcť používateľovi pochopiť, prečo bol jeho vstup nesprávny. Výnimka parametra obsahuje JCommander napríklad na zobrazenie pomoci:

skus {jc.parse (args); } catch (ParameterException e) {System.err.println (e.getLocalizedMessage ()); jc.usage (); } 

12. Záver

V tomto tutoriáli sme použili JCommander na zostavenie aplikácie príkazového riadku. Aj keď sme sa zaoberali mnohými z hlavných funkcií, v oficiálnej dokumentácii je toho viac.

Ako obvykle je zdrojový kód všetkých príkladov k dispozícii na serveri GitHub.


$config[zx-auto] not found$config[zx-overlay] not found