Hozzon létre egy Java parancssori programot a Picocli alkalmazással

1. Bemutatkozás

Ebben az oktatóanyagban megközelítjük a pikocli könyvtár, amely lehetővé teszi számunkra a parancssori programok egyszerű létrehozását Java-ban.

Először egy Hello World parancs létrehozásával kezdjük. Ezután mélyen belemerülünk a könyvtár legfontosabb jellemzőibe, részben reprodukálva a git parancs.

2. Helló Világparancsnokság

Kezdjük valami egyszerűvel: egy Hello World parancs!

Először is hozzá kell adnunk a függőséget a pikocli projekt:

 info.picocli picocli 3.9.6 

Amint láthatjuk, használjuk a 3.9.6 a könyvtár változata, bár a 4.0.0 verzió fejlesztés alatt áll (jelenleg alfa tesztben érhető el).

Most, hogy a függőség be van állítva, hozzuk létre a Hello World parancsot. Ennek érdekében használjuk a @Parancs annotáció a könyvtárból:

@Command (name = "hello", description = "Hello") public class HelloWorldCommand {}

Mint láthatjuk, az annotáció paramétereket vehet fel. Csak kettőt használunk itt. Céljuk, hogy információkat szolgáltassanak az aktuális parancsról és az automatikus súgó szövegéről.

Jelenleg nem sokat tehetünk ezzel a paranccsal. Ahhoz, hogy valamit csináljon, hozzá kell adnunk a fő- módszer hívása a kényelem CommandLine.run (Futható, String []) módszer. Ehhez két paraméterre van szükség: a parancsunk egy példányára, amelynek így végre kell hajtania a Futható interfész, és a Húr tömb, amely a parancs argumentumait (opciók, paraméterek és alparancsok) képviseli:

public class HelloWorldCommand megvalósítja a Runnable {public static void main (String [] args) {CommandLine.run (new HelloWorldCommand (), args); } @Orride public void run () {System.out.println ("Hello Világ!"); }}

Most, amikor lefuttatjuk a fő- módszerrel látni fogjuk, hogy a konzol kimeneti "Helló Világ!"

Üvegbe csomagolva futtathatjuk a Hello World parancsunkat a Jáva parancs:

java -cp "pathToPicocliJar; pathToCommandJar" com.baeldung.picoli.helloworld.HelloWorldCommand

Nem meglepő, hogy ez is kimeneti a "Helló Világ!" húr a konzolhoz.

3. Egy konkrét felhasználási eset

Most, hogy megláttuk az alapokat, mélyen belemerülünk a pikocli könyvtár. Ennek érdekében részben megismételjük egy népszerű parancsot: git.

Természetesen a cél nem az lesz git parancs viselkedését, hanem reprodukálni a git parancs - melyik alparancs létezik, és mely opciók állnak rendelkezésre egy sajátos alparancshoz.

Először létre kell hoznunk a GitCommand osztály, mint a Hello World parancsunknál:

@Command public class A GitCommand végrehajtja a Runnable {public static void main (String [] args) {CommandLine.run (new GitCommand (), args); } @Orride public void run () {System.out.println ("A népszerű git parancs"); }}

4. Alparancsok hozzáadása

A git a parancs sok alparancsot kínál - hozzá, elkötelez, távoli, és még sok más. Itt összpontosítunk hozzá és elkövetni.

Tehát itt az lesz a célunk, hogy ezt a két alparancsot deklaráljuk a fő parancsnak. Picocli három módot kínál ennek elérésére.

4.1. Használni a @Parancs Megjegyzés az osztályokhoz

A @Parancs az annotáció lehetőséget nyújt az alparancsok regisztrációjára a alparancsnokok paraméter:

@Command (alparancsok = {GitAddCommand.class, GitCommitCommand.class})

Esetünkben két új osztályt adunk hozzá: GitAddCommand és GitCommitCommand. Mindkettő be van jelölve @Parancs és végrehajtja Futható. Fontos nevet adni nekik, mivel a neveket használni fogják pikocli végrehajtandó alparancsok felismerése:

@Command (name = "add") public class GitAddCommand megvalósítja a Runnable {@Override public void run () {System.out.println ("Néhány fájl hozzáadása az átmeneti területhez"); }}
@Command (name = "kötelezettségvállalás") public class A GitCommitCommand megvalósítja a Runnable {@Override public void run () {System.out.println ("Mennyire csodálatos a fájlok elküldése az átmeneti területen"); }}

Így, ha a fõparancsunkat futtatjuk hozzá érvként a konzol fogja kiadni „Néhány fájl hozzáadása az átmeneti területhez”.

4.2. Használni a @Parancs Megjegyzés a módszerekről

Az alparancsok deklarálásának másik módja a teremt @Parancs-nevezett módszerek, amelyek a parancsokat képviselik a GitCommand osztály:

@Command (name = "add") public void addCommand () {System.out.println ("Néhány fájl hozzáadása az átmeneti területhez"); } @Command (name = "kötelezettségvállalás") public void kötelezettségCommand () {System.out.println ("Milyen csodálatos a fájlok végrehajtása az átmeneti területen?"); }

Így közvetlenül megvalósíthatjuk üzleti logikánkat a módszerekben, és nem hozhatunk létre külön osztályokat annak kezelésére.

4.3. Alparancsok programszerű hozzáadása

Végül, pikocli lehetőséget kínál az alparancsok programozott regisztrálására. Ez egy kicsit bonyolultabb, mivel létre kell hoznunk a Parancs sor objektum becsomagolja a parancsunkat, majd adja hozzá az alparancsokat:

CommandLine commandLine = új CommandLine (új GitCommand ()); commandLine.addSubcommand ("add", új GitAddCommand ()); commandLine.addSubcommand ("kötelezettség", új GitCommitCommand ());

Ezt követően még mindig futtatnunk kell a parancsunkat, de nem használhatjuk a CommandLine.run () módszer már. Most hívnunk kell a parseWithHandler () módszer az újonnan létrehozott CommandLine tárgy:

commandLine.parseWithHandler (új RunLast (), érvel);

Meg kell jegyeznünk a RunLast osztály, ami elmondja pikocli a legspecifikusabb alparancs futtatásához. Két másik parancskezelő is rendelkezésre áll pikocli: RunFirst és RunAll. Az előbbi a legfelső parancsot hajtja végre, míg az utóbbi mindet.

A kényelmi módszer használatakor CommandLine.run (), a RunLast alapértelmezés szerint a handlert használja.

5. Opciók kezelése a @Választási lehetőség Megjegyzés

5.1. Opció argumentum nélkül

Most nézzük meg, hogyan adhatunk hozzá néhány beállítást a parancsunkhoz. Valóban szeretnénk elmondani a mi hozzá parancsot, hogy hozzá kell adnia az összes módosított fájlt. Ennek elérése érdekében hozzáadunk egy mezőt, amelyhez a @Választási lehetőség annotáció a miénknek GitAddCommand osztály:

@Option (names = {"-A", "--all"}) privát logikai allFiles; @Orride public void run () {if (allFiles) {System.out.println ("Az összes fájl hozzáadása az átmeneti területhez"); } else {System.out.println ("Néhány fájl hozzáadása az átmeneti területhez"); }}

Mint láthatjuk, az annotáció a nevek paraméter, amely megadja az opció különböző neveit. Ezért a hozzá parancsolj valamelyikkel -A vagy -minden beállítja a Minden fájl mezőt igaz. Tehát, ha az opcióval futtatjuk a parancsot, a konzol megjelenik „Az összes fájl hozzáadása az átmeneti területhez”.

5.2. Opció argumentummal

Amint láttuk, az érvek nélküli opciók esetében a jelenlétüket vagy hiányukat mindig a-ra értékelik logikai érték.

Lehetséges azonban olyan argumentumok regisztrálása, amelyek argumentumokat tartalmaznak. Megtehetjük ezt egyszerűen úgy, hogy a mezőnket más típusúnak nyilvánítjuk. Tegyük hozzá a üzenet lehetőség a mi elkövetni parancs:

@Option (nevek = {"-m", "--message"}) privát karakterlánc-üzenet; @Orride public void run () {System.out.println ("Milyen csodálatos a fájlok végrehajtása az átmeneti területen?"); if (üzenet! = null) {System.out.println ("Az elkötelezett üzenet" + üzenet); }}

Nem meglepő, ha megadják a üzenet opciót, a parancs megjeleníti az elkövetési üzenetet a konzolon. A cikk későbbiben kitérünk arra, hogy mely típusokat kezeli a könyvtár, és hogyan kezeljük más típusokat.

5.3. Opció több érvvel

De most mi van, ha azt akarjuk, hogy a parancsunk több üzenetet is fogadjon, ahogyan a valódival történik git elkövetni parancs? Semmi gond, tegyük mezőnket egy sor vagy a Gyűjtemény, és nagyjából elkészültünk:

@Option (nevek = {"-m", "--message"}) privát karakterlánc [] üzenetek; @Orride public void run () {System.out.println ("Fájlok elkötelezése az átmeneti területen, milyen csodálatos?"); if (üzenetek! = null) {System.out.println ("Az elkötelezett üzenet az"); for (Karakterlánc üzenet: üzenetek) {System.out.println (üzenet); }}}

Most használhatjuk a üzenet opció többször:

elkövetni -m "Az elkötelezettségem nagyszerű" -m "Az elkötelezettségem gyönyörű"

Lehetséges azonban, hogy csak egyszer adjuk meg az opciót, és a különböző paramétereket egy regex elválasztóval választjuk el. Ezért használhatjuk a hasított paramétere @Választási lehetőség kommentár:

@Option (nevek = {"-m", "--message"}, split = ",") privát karakterlánc [] üzenetek;

Most átmehetünk -m „Nagy az elkötelezettségem”, „gyönyörű az elkötelezettségem” hogy a fentivel azonos eredményt érjünk el.

5.4. Szükséges opció

Előfordulhat, hogy van egy szükséges lehetőségünk. A kívánt argumentum, amely alapértelmezés szerint hamislehetővé teszi számunkra, hogy:

@Option (nevek = {"-m", "--message"}, kötelező = igaz) privát karakterlánc [] üzenetek;

Most lehetetlen felhívni a elkövetni parancsot a üzenet választási lehetőség. Ha megpróbáljuk ezt megtenni, pikocli hibát nyomtat:

Hiányzik a kötelező opció '--message =' Használat: git elkövetés -m = [-m =] ... -m, --message =

6. Pozíciós paraméterek kezelése

6.1. Helyzeti paraméterek rögzítése

Most koncentráljunk a sajátjainkra hozzá parancsot, mert még nem túl erős. Csak az összes fájl hozzáadásáról dönthetünk, de mi van, ha konkrét fájlokat akarunk hozzáadni?

Ehhez használhatnánk egy másik opciót is, de itt jobb választás lenne a helyzeti paraméterek használata. Valóban, A helyzeti paraméterek olyan parancs argumentumokat hivatottak rögzíteni, amelyek meghatározott pozíciókat foglalnak el, és amelyek sem alparancsok, sem opciók.

Példánkban ez lehetővé tenné számunkra, hogy ilyesmit tegyünk:

add fájl1 fájl2

A helyzeti paraméterek rögzítése érdekében ki fogjuk használni a @Paraméterek annotáció:

@Parameters private List fájlok; @Orride public void run () {if (allFiles) {System.out.println ("Az összes fájl hozzáadása az átmeneti területhez"); } if (fájlok! = null) {files.forEach (elérési út -> System.out.println ("+ útvonal +" hozzáadása az átmeneti területhez ")); }}

Most a korábbi parancsunk kinyomtatta:

File1 hozzáadása az átmeneti területhez File2 hozzáadása az átmeneti területhez

6.2. Rögzítse a pozícióparaméterek egy részhalmazát

A.-Nek köszönhetően pontosabban meg lehet határozni, hogy mely pozíciós paramétereket rögzítse index az annotáció paramétere. Az index nulla alapú. Így, ha meghatározzuk:

@Parameters (index = "2 .. *")

Ez olyan argumentumokat rögzítene, amelyek nem felelnek meg az opcióknak vagy az alparancsoknak, a harmadiktól a végéig.

Az index lehet tartomány vagy egyetlen szám, amely egyetlen pozíciót képvisel.

7. Egy szó a típusátalakításról

Amint azt az oktatóanyag korábban látta, pikocli valamilyen típusú átalakítást egyedül kezel. Például több értéket is leképez tömbök vagy Gyűjtemények, de az argumentumokat meghatározott típusokhoz is leképezheti, például amikor a Pálya osztály a hozzá parancs.

Ami azt illeti, pikocli csomó előre kezelt típus érkezik. Ez azt jelenti, hogy ezeket a típusokat közvetlenül használhatjuk anélkül, hogy saját magunk kellene átalakítanunk őket.

Előfordulhat azonban, hogy a parancs argumentumait a már kezelt típusoktól eltérő típusokra kell feltérképeznünk. Szerencsénkre ez a ITypeConverter interfész és a CommandLine # registerConverter metódus, amely egy típust társít egy átalakítóhoz.

Képzeljük el, hogy hozzá akarjuk adni a konfig alparancsnokság a mi git parancsot, de nem akarjuk, hogy a felhasználók megváltoztassanak egy nem létező konfigurációs elemet. Tehát úgy döntünk, hogy ezeket az elemeket egy enumra térképezzük fel:

public enum ConfigElement {USERNAME ("felhasználónév"), EMAIL ("user.email"); privát végső karakterlánc értéke; ConfigElement (String érték) {this.value = érték; } public String value () {return value; } public static ConfigElement from (String value) {return Arrays.stream (values ​​()) .filter (element -> element.value.equals (value)) .findFirst (). orElseThrow (() -> new IllegalArgumentException ("A "+ value +" argumentum nem egyezik meg a ConfigElement elemével ")); }}

Ráadásul az újonnan létrehozott GitConfigCommand osztály, adjunk hozzá két helyzeti paramétert:

@Parameters (index = "0") privát ConfigElement elem; @Parameters (index = "1") privát karakterlánc értéke; @Orride public void run () {System.out.println ("Setting" + element.value () + "to" + value); }

Így megbizonyosodunk arról, hogy a felhasználók nem módosíthatják a nem létező konfigurációs elemeket.

Végül regisztrálnunk kell a konverterünket. A legszebb az, hogy ha Java 8-at vagy újabbat használunk, nem is kell létrehoznunk egy osztályt a ITypeConverter felület. Csak átadhatunk egy lambda vagy módszer hivatkozást a registerConverter () módszer:

CommandLine commandLine = új CommandLine (új GitCommand ()); commandLine.registerConverter (ConfigElement.class, ConfigElement :: from); commandLine.parseWithHandler (új RunLast (), érvel);

Ez történik a GitCommand fő() módszer. Ne feledje, hogy el kellett engednünk a kényelmet CommandLine.run () módszer.

Kezeletlen konfigurációs elemnél használva a parancs megmutatja a súgó üzenetet és egy olyan információt, amely elmondja nekünk, hogy a paramétert nem lehet konvertálni ConfigElement:

A 0. index helyzeti paraméterének érvénytelen értéke (): nem lehet átalakítani a 'user.phone' fájlt ConfigElement-re (java.lang.IllegalArgumentException: A user.phone argumentum nem felel meg egyetlen ConfigElement-nek sem) Használat: git config 

8. Integrálás a tavaszi csomagtartóval

Végül lássuk, hogyan lehet mindezt ruganyosítani!

Valójában lehet, hogy egy Spring Boot környezetben dolgozunk, és a parancssori programunkban szeretnénk hasznot húzni belőle. Ennek érdekében létre kell hoznunk a SpringBootApplicationa CommandLineRunner felület:

@SpringBootApplication public class Application végrehajtja a CommandLineRunner {public static void main (String [] args) {SpringApplication.run (Application.class, args); } @Orride public void run (String ... args) {}}

Plusz, jegyezzük fel az összes parancsunkat és alparancsunkat a Tavaszra @Összetevő annotáció és írja be mindezt a miénkbe Alkalmazás:

privát GitCommand gitCommand; privát GitAddCommand addCommand; privát GitCommitCommand commCommand; privát GitConfigCommand configCommand; nyilvános alkalmazás (GitCommand gitCommand, GitAddCommand addCommand, GitCommitCommand commCommand, GitConfigCommand configCommand) {this.gitCommand = gitCommand; this.addCommand = addCommand; this.commitCommand = kötelezettségCommand; this.configCommand = configCommand; }

Ne feledje, hogy minden alparancsot automatikusan be kellett írnunk. Sajnos ez azért van, mert egyelőre pikocli még nem képes az alparancsok lekérésére a tavaszi kontextusból, amikor deklaratív módon (annotációkkal) deklarálják. Így ezt a vezetéket magunknak kell elvégeznünk, programozott módon:

@Orride public void run (String ... args) {CommandLine commandLine = new CommandLine (gitCommand); commandLine.addSubcommand ("add", addCommand); commandLine.addSubcommand ("elkövetés", kötelezettségCommand); commandLine.addSubcommand ("config", configCommand); commandLine.parseWithHandler (új CommandLine.RunLast (), érvel); }

És most a parancssori programunk varázslatként működik a Spring alkatrészekkel. Ezért létrehozhatunk néhány szolgáltatási osztályt, és felhasználhatjuk őket a parancsainkban, és hagyhatjuk, hogy Spring gondoskodjon a függőségi injekcióról.

9. Következtetés

Ebben a cikkben láttuk a pikocli könyvtár. Megtanultuk, hogyan kell új parancsot létrehozni, és hozzáadni néhány alparancsot. Számos módot láthattunk az opciók és a helyzeti paraméterek kezelésére. Ráadásul megtanultuk, hogyan kell saját típusú átalakítóinkat megvalósítani, hogy a parancsaink erőteljesen be legyenek írva. Végül láttuk, hogyan lehet a Spring Boot-ot bevinni a parancsokba.

Természetesen még sok mindent felfedezhetünk benne. A könyvtár teljes dokumentációt biztosít.

Ami a cikk teljes kódját illeti, megtalálható a GitHub-on.