Parancssori paraméterek elemzése a JCommanderrel

1. Áttekintés

Ebben az oktatóanyagban megtanuljuk, hogyan használható a JCommander a parancssori paraméterek elemzésére. Egy egyszerű parancssori alkalmazás létrehozása során számos funkcióját megvizsgáljuk.

2. Miért pont a JCommander?

"Mivel az élet túl rövid a parancssori paraméterek elemzéséhez" - Cédric Beust

A Cédric Beust által létrehozott JCommander egy annotáció alapú könyvtárparancssori paraméterek elemzése. Csökkentheti a parancssori alkalmazások kiépítésének erőfeszítéseit, és segíthet abban, hogy jó felhasználói élményt nyújtsunk számukra.

A JCommander segítségével olyan trükkös feladatokat tölthetünk le, mint az elemzés, az érvényesítés és a típuskonverziók, hogy lehetővé tegyük számunkra, hogy az alkalmazáslogikánkra összpontosítsunk.

3. A JCommander beállítása

3.1. Maven konfiguráció

Kezdjük azzal, hogy hozzáadjuk a parancsnok függőség a mi pom.xml:

 com.beust jcommander 1.78 

3.2. Helló Világ

Hozzunk létre egy egyszerű HelloWorldApp ehhez egyetlen bemenetre van szükség név és üdvözletet nyomtat, "Helló ".

Mivel A JCommander a parancssori argumentumokat a Java osztály mezőihez köti, először meghatározzuk a HelloWorldArgs osztály mezővel név jelöléssel @Paraméter:

class HelloWorldArgs {@Parameter (nevek = "--név", leírás = "Felhasználónév", kötelező = igaz) privát karakterlánc neve; }

Most használjuk a JCommander osztály a parancssori argumentumok elemzéséhez és a mezők hozzárendeléséhez HelloWorldArgs tárgy:

HelloWorldArgs jArgs = új HelloWorldArgs (); JCommander helloCmd = JCommander.newBuilder () .addObject (jArgs) .build (); helloCmd.parse (érvek); System.out.println ("Hello" + jArgs.getName ());

Végül hívjuk meg a főosztályt ugyanazokkal az argumentumokkal a konzolból:

$ java HelloWorldApp --name JavaWorld Hello JavaWorld

4. Valódi alkalmazás készítése a JCommander alkalmazásban

Most, hogy elindultunk, vegyünk fontolóra egy összetettebb felhasználási esetet - egy parancssori API-klienst, amely kölcsönhatásba lép egy olyan számlázási alkalmazással, mint például a Stripe, különösen a Mért (vagy használaton alapuló) számlázási forgatókönyvvel. Ez a harmadik fél számlázási szolgáltatása kezeli előfizetésünket és számlázásunkat.

Képzeljük el, hogy SaaS-vállalkozást működtetünk, amelyben ügyfeleink előfizetéseket vásárolnak szolgáltatásainkra, és számlázzák a szolgáltatásainkhoz tartozó havi API-hívások számát. Két műveletet fogunk végrehajtani ügyfelünkön:

  • Beküldés: A felhasználás mennyiségének és egységárának megadása egy előfizetés ellenében
  • elhozni: Beszedjen egy ügyfél költségeit az előfizetésük egy részének vagy egészének az adott hónapban történő felhasználása alapján - ezeket a díjakat összesíthetjük az összes előfizetésre, vagy tételesen feltüntethetjük az egyes előfizetéseket.

A könyvtár szolgáltatásainak áttekintésekor építjük az API klienst.

Kezdjük!

5. Paraméter meghatározása

Kezdjük azzal, hogy meghatározzuk azokat a paramétereket, amelyeket alkalmazásunk használhat.

5.1. A @Paraméter Megjegyzés

Egy mező jelölése a @Paraméter utasítja a JCommandert, hogy kössön hozzá egy megfelelő parancssori argumentumot. @Paraméter rendelkezik attribútumokkal a fő paraméter leírására, például:

  • nevek - az opció egy vagy több neve, például „–név” vagy „-n”
  • leírás - az opció mögött rejlő jelentés a végfelhasználó segítésére
  • kívánt - az opció kötelező-e, alapértelmezés szerint hamis
  • aritás - az opció által elfogyasztott további paraméterek száma

Konfiguráljunk egy paramétert Ügyfél-azonosító a számlázási forgatókönyvünkben:

@Parameter (names = {"--customer", "-C"}, description = "A szolgáltatást igénybe vevő ügyfél azonosítója", arity = 1, kötelező = true) String customerId; 

Most hajtsuk végre a parancsunkat az új „–customer” paraméterrel:

$ java App - ügyfél cust0000001A Olvassa el a CustomerId: cust0000001A. 

Ugyanígy használhatjuk a rövidebb „-C” paramétert is ugyanazon hatás eléréséhez:

$ java App -C cust0000001A Olvassa el a CustomerId-t: cust0000001A. 

5.2. Szükséges paraméterek

Ahol egy paraméter kötelező, az alkalmazás kilép a ParameterException ha a felhasználó nem adja meg:

$ java App Exception a "main" szálban com.beust.jcommander.ParameterException: A következő opcióra van szükség: [--customer | -C]

Meg kell jegyeznünk, hogy általában a paraméterek értelmezésében bekövetkezett bármilyen hiba a ParameterException a JCommanderben.

6. Beépített típusok

6.1. IStringConverter Felület

A JCommander a parancssorból hajt végre típusátalakítást Húr bemenet a Java-típusokba a paraméterosztályainkban. A IStringConverter interfész kezeli a paraméter típusátalakítását innen: Húr tetszőleges típusúnak. Tehát a JCommander összes beépített átalakítója megvalósítja ezt az interfészt.

A dobozból a JCommander támogatja az olyan általános adattípusokat, mint a Húr, Egész szám, Logikai, BigDecimal, és Enum.

6.2. Single-Arity típusok

Az Arity az opció által elfogyasztott további paraméterek számára vonatkozik. JCommander's a beépített paramétertípusok alapértelmezett aritása egy, kivéve Logikai és Lista. Ezért olyan általános típusok, mint pl Húr, Egész szám, BigDecimal, Hosszú, és Enum, egy arit típusúak.

6.3. Logikai típus

Típusmezők logikai vagy Logikai nincs szükség további paraméterekre - ezeknek az opcióknak van egy aritás nulla.

Nézzünk meg egy példát. Talán meg akarjuk szerezni az ügyfelek költségeit előfizetésenként tételesen. Hozzáadhatjuk a logikai terület részletes, ami hamis alapértelmezés szerint:

@Parameter (nevek = {"--itemized"}) privát logikai tételesen; 

Alkalmazásunk az összesített költségeket visszaadná a részletes állítva hamis. Amikor meghívjuk a parancssort a részletes paraméterre állítottuk a mezőt igaz:

$ java App --itemized Jelölés olvasása tételesen: true. 

Ez jól működik, hacsak nincs olyan felhasználási esetünk, amikor mindig tételes díjakat szeretnénk, hacsak másként nem írjuk elő. Megváltoztathatnánk a paramétert notItemized, de lehet, hogy világosabb, ha képesek vagyunk szolgáltatni hamis mint az értéke részletes.

Vezesd be ezt a viselkedést egy alapértelmezett érték használatával igaz a mező számára, és annak beállítását aritás mint az egyik:

@Parameter (nevek = {"--itemized"}, arity = 1) privát logikai tételes = igaz; 

Most, amikor megadjuk az opciót, az értékre állítjuk hamis:

$ java App --itemized false Olvasás tételesen: false. 

7. Lista Típusok

A JCommander néhány módszert kínál az érvek megkötésére Lista mezők.

7.1. A paraméter többszörös megadása

Tegyük fel, hogy az ügyfél előfizetésének csak egy részhalmazát szeretnénk lekérni:

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

A mező nem kötelező, és ha az paraméter nem kerül megadásra, az alkalmazás az összes előfizetés díját lekérné. Megadhatunk azonban több előfizetést is a paraméter nevének többszöri használatával:

$ java App -S előfizetésA001 -S előfizetésA002 -S előfizetésA003 Olvassa el az előfizetéseket: [előfizetésA001, előfizetésA002, előfizetésA003]. 

7.2. Kötés Listák A Splitter használata

Ahelyett, hogy többször megadná az opciót, próbáljunk vesszővel elválasztva átkötni a listát Húr:

$ java App -S előfizetésA001, előfizetésA002, előfizetésA003 Olvassa el az előfizetéseket: [előfizetésA001, előfizetésA002, előfizetésA003]. 

Ez egyetlen paraméterértéket (arity = 1) használ a lista ábrázolására. JCommander fogja használni az osztályt CommaParameterSplitter hogy vesszővel elválasztva kösse meg Húr a miénknek Lista.

7.3. Kötés Listák Egyéni osztó használata

Az alapértelmezett osztót felülírhatjuk a IParameterSplitter felület:

class ColonParameterSplitter végrehajtja az IParameterSplitter {@Orride public List split (String value) {return asList (value.split (":")); }}

Ezután hozzárendeli a megvalósítást a osztó attribútum @Paraméter:

@Parameter (nevek = {"--subscription", "-S"}, splitter = ColonParameterSplitter.class) privát lista subscriptionIds; 

Próbáljuk ki:

$ java App -S "előfizetésA001: előfizetésA002: előfizetésA003" Előfizetések olvasása: [előfizetésA001, előfizetésA002, előfizetésA003]. 

7.4. Változó Arity Listák

A változó aritás lehetővé teszi számunkra a nyilatkozattételtlisták, amelyek határozatlan paramétereket vehetnek fel, a következő lehetőségig. Beállíthatjuk az attribútumot variableArity mint igaz hogy meghatározza ezt a viselkedést.

Próbáljuk meg az előfizetéseket elemezni:

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

És amikor végrehajtjuk a parancsunkat:

$ java App -S előfizetésA001 előfizetésA002 előfizetésA003 - tematizált Olvasott előfizetések: [előfizetésA001, előfizetésA002, előfizetésA003]. 

A JCommander az összes „-S” opciót követő bemeneti argumentumot a lista mezőjéhez köti, a parancs következő végéig vagy végéig.

7.5. Fix Arity Listák

Eddig láttunk korlátlan listákat, ahol annyi listaelemet adhatunk át, amennyit csak akarunk. Előfordulhat, hogy korlátozni szeretnénk az a-ra továbbított elemek számát Lista terület. Ehhez megtehetjük adjon meg egy egész aritási értéket a számára Lista területhogy korlátos legyen:

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

A fix aritás kényszeríti az a-nak átadott paraméterek számának ellenőrzését Lista opciót és dob a ParameterException jogsértés esetén:

$ java App -S előfizetésA001 előfizetésA002 előfizetésA003 átadták az 'subscriptionA003' főparamétert, de az arg osztályban nem definiáltak főparamétert 

A hibaüzenet arra utal, hogy mivel a JCommander csak két argumentumra számított, megpróbálta a következő opcióként elemezni az „subscriptionA003” extra bemeneti paramétert.

8. Egyedi típusok

A paramétereket egyedi konverterek megírásával is köthetjük. A beépített átalakítókhoz hasonlóan az egyedi átalakítóknak is végre kell hajtaniuk a IStringConverter felület.

Írjunk egy átalakítót az ISO8601 időbélyeg elemzéséhez:

az ISO8601TimestampConverter osztály megvalósítja az IStringConverter {private static final DateTimeFormatter TS_FORMATTER = DateTimeFormatter.ofPattern ("uuuu-MM-dd'T'HH: mm: ss"); @Orride public Instant convert (String value) {try {return LocalDateTime .parse (value, TS_FORMATTER) .atOffset (ZoneOffset.UTC) .toInstant (); } catch (DateTimeParseException e) {dobjon új ParameterException ("Érvénytelen időbélyeg"); }}} 

Ez a kód elemzi a bemenetet Húr és adjon vissza egy Azonnali, dobott egy ParameterException ha van konverziós hiba. Ezt a konvertert úgy használhatjuk, hogy egy típusú mezőhöz kötjük Azonnali használni a átalakító attribútum @Paraméter:

@Parameter (names = {"--timestamp"}, konverter = ISO8601TimestampConverter.class) privát Azonnali időbélyeg; 

Lássuk működés közben:

$ java App - időbélyeg 2019-10-03T10: 58: 00 Olvassa el az időbélyeget: 2019-10-03T10: 58: 00Z.

9. Paraméterek ellenőrzése

A JCommander néhány alapértelmezett ellenőrzést nyújt:

  • megadják-e a szükséges paramétereket
  • ha a megadott paraméterek száma megegyezik egy mező aritusságával
  • hogy mindegyik Húr paraméter a megfelelő mező típusává konvertálható

Továbbá, esetleg egyedi érvényesítéseket kívánunk hozzáadni. Tegyük fel például, hogy az ügyfél-azonosítóknak UUID-nek kell lenniük.

Valírátort írhatunk az interfészt megvalósító ügyfél mezőhöz IParameterValidator:

class UUIDValidator implementálja az IParameterValidator {private static final String UUID_REGEX = "[0-9a-fA-F] {8} (- [0-9a-fA-F] {4}) {3} - [0-9a-fA- F] {12} "; A @Orride public void validate (karakterlánc neve, karakterlánc értéke) dobja a ParameterException {if (! IsValidUUID (érték)) {dob új ParameterException szolgáltatást ("A" + "+" + "karakterlánc nem érvényes UUID."); }} private boolean isValidUUID (karakterlánc értéke) {return Pattern.compile (UUID_REGEX) .matcher (value) .matches (); }} 

Ezután összekapcsolhatjuk a validateWith a paraméter attribútuma:

@Parameter (names = {"--customer", "-C"}, validateWith = UUIDValidator.class) privát karakterlánc customerId; 

Ha nem UUID ügyfél-azonosítóval hívjuk meg a parancsot, az alkalmazás egy érvényesítési hibaüzenettel lép ki:

$ java App --C customer001 A string001 paraméter nem érvényes UUID. 

10. Alparancsok

Most, hogy megtanultuk a paraméterek kötését, húzzunk össze mindent a parancsok felépítéséhez.

A JCommanderben támogathatunk több parancsot, úgynevezett alparancsokat, mindegyiknek külön opcióval rendelkezik.

10.1. @Paraméterek Megjegyzés

Tudjuk használni @Paraméterek alparancsok meghatározásához. @Paraméterek tartalmazza az attribútumot commandNames parancs azonosítására.

Modellezzünk Beküldés és elhozni alparancsokként:

@Parameters (commandNames = {"submit"}, commandDescription = "Használat benyújtása egy adott ügyfélhez és előfizetéshez," + "elfogad egy használati elemet") class SubmitUsageCommand {// ...} @Parameters (commandNames = {"fetch" }, commandDescription = "Ügyfél költségeinek lekérése az aktuális hónapban, a" + "tételesen vagy összesítve adható") class FetchCurrentChargesCommand {// ...} 

A JCommander az attribútumokat a @Paraméterek az alparancsok konfigurálásához, például:

  • commandNames - az alparancs neve; a parancssori argumentumokat a -val jegyzetelt osztályhoz köti @Paraméterek
  • commandDescription - dokumentálja az alparancsnokság célját

10.2. Alparancsok hozzáadása ehhez: JCommander

Hozzáadjuk az alparancsokat a JCommander a ... val addCommand módszer:

SubmitUsageCommand submitUsageCmd = új SubmitUsageCommand (); FetchCurrentChargesCommand fetchChargesCmd = új FetchCurrentChargesCommand (); JCommander jc = JCommander.newBuilder () .addCommand (submitUsageCmd) .addCommand (fetchChargesCmd) .build (); 

A addCommand metódus regisztrálja az alparancsokat a megfelelő nevükkel, a commandNames attribútuma @Paraméterek annotáció.

10.3. Alparancsok elemzése

A felhasználó által kiválasztott parancs eléréséhez először elemeznünk kell az argumentumokat:

jc.parse (érvek); 

Ezután kivonhatjuk az alparancsot a getParsedCommand:

String parsedCmdStr = jc.getParsedCommand (); 

A parancs azonosításán túl a JCommander a többi parancssori paramétert az alparancs mezőihez köti. Most csak meg kell hívnunk a használni kívánt parancsot:

kapcsoló (parsedCmdStr) {eset "beküldés": submUsageCmd.submit (); szünet; case "fetch": fetchChargesCmd.fetch (); szünet; alapértelmezett: System.err.println ("Érvénytelen parancs:" + parsedCmdStr); } 

11. A JCommander használati súgója

Felhívhatjuk használat használati útmutató megjelenítéséhez. Ez az alkalmazásunk által használt összes lehetőség összefoglalása. Alkalmazásunkban meghívhatjuk a fõparancs használatát, vagy alternatívaként a „beküldés” és a „lekérés” parancsok mindegyikét külön-külön.

A használati kijelző néhány szempontból segíthet nekünk: a súgó opcióinak bemutatásában és a hibakezelés során.

11.1. A Súgó opciók megjelenítése

A súgó opciót leköthetjük a parancsunkba az a használatával logikai paraméter az attribútummal együtt Segítség állítva igaz:

@Parameter (names = "--help", help = true) privát logikai segítség; 

Ezután észlelhetjük, hogy a „–help” át lett-e adva az argumentumokban, és felhívhatjuk használat:

if (cmd.segítség) {jc.usage (); } 

Lássuk a „beküldés” alparancsunk súgó kimenetét:

$ java alkalmazás benyújtása - segítség Használat: beküldés [opciók] Opciók: * --ügyfél, a szolgáltatásokat igénybe vevő ügyfél -C azonosítója * --subscription, -S a vásárolt előfizetés azonosítója * --quantity Használt mennyiség ; a jelentett mennyiség hozzáadódik a számlázási időszak alatt * --pricing-type, -P A bejelentett felhasználás árazási típusa (értékek: [PRE_RATED, UNRATED]) * --timestamp A használati esemény időbélyegének az aktuális számlázási időszakban kell lennie - -ár Ha PRE_RATED, a bejelentett használati egység egységenként alkalmazandó egységár 

A használat módszer a @Paraméter attribútumok, mint pl leírás hasznos összefoglaló megjelenítéséhez. A csillaggal (*) jelölt paraméterek kötelezőek.

11.2. Hibakezelés

Foghatjuk a ParameterException és hívjon használat hogy segítsen a felhasználónak megérteni miért nem volt megfelelő a bevitel ParameterException tartalmazza a JCommander példány a súgó megjelenítéséhez:

próbáld ki a {jc.parse (args); } catch (ParameterException e) {System.err.println (e.getLocalizedMessage ()); jc.usage (); } 

12. Következtetés

Ebben az oktatóanyagban a JCommander segítségével parancssori alkalmazást készítettünk. Noha a főbb jellemzők közül sok mindent áttekintettünk, a hivatalos dokumentációban még többet találunk.

Szokás szerint az összes példa forráskódja elérhető a GitHubon.


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