Stvorite program naredbenog retka Java s Picoclijem

1. Uvod

U ovom uputstvu pristupit ćemo pikokli knjižnica, koja nam omogućuje lako stvaranje programa naredbenog retka na Javi.

Prvo ćemo započeti stvaranjem naredbe Hello World. Zatim ćemo duboko zaroniti u ključne značajke knjižnice reproducirajući djelomično git naredba.

2. Hello World Command

Počnimo s nečim laganim: naredba Hello World!

Prvo, prvo moramo dodati ovisnost na pikokli projekt:

 info.picocli pikokli 3.9.6 

Kao što vidimo, koristit ćemo 3.9.6 inačici knjižnice, iako a 4.0.0 verzija je u izradi (trenutno dostupna u alfa testu).

Sada kada je ovisnost postavljena, kreirajmo našu naredbu Hello World. Da bi to učinili, koristit ćemo @Naredba napomena iz knjižnice:

@Command (name = "hello", description = "Says hello") javna klasa HelloWorldCommand {}

Kao što vidimo, napomena može uzimati parametre. Ovdje koristimo samo dva. Njihova je svrha pružiti informacije o trenutnoj naredbi i tekst za automatsku poruku pomoći.

Trenutno s ovom naredbom ne možemo puno učiniti. Da bismo nešto učinili, moramo dodati znak glavni pozivanje metode pogodnost CommandLine.run (pokretan, niz []) metoda. Za to su potrebna dva parametra: instanca naše naredbe, koja stoga mora implementirati Izvodljivo sučelje i Niz niz koji predstavlja naredbene argumente (opcije, parametri i potkomande):

javna klasa HelloWorldCommand implementira Runnable {public static void main (String [] args) {CommandLine.run (novi HelloWorldCommand (), args); } @Override public void run () {System.out.println ("Hello World!"); }}

Sada, kad pokrenemo glavni metodom, vidjet ćemo da konzola izlazi "Pozdrav svijete!"

Pakirani u staklenku, možemo pokrenuti naredbu Hello World pomoću Java naredba:

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

Bez iznenađenja, to također daje rezultat "Pozdrav svijete!" niz na konzolu.

3. Konkretan slučaj upotrebe

Sad kad smo vidjeli osnove, duboko ćemo zaroniti u pikokli knjižnica. Da bismo to učinili, reproducirat ćemo djelomično popularnu naredbu: git.

Naravno, svrha neće biti provedba git zapovjedno ponašanje, ali za reprodukciju mogućnosti git naredba - koji podzapovjedi postoje i koje su opcije dostupne za određenu podnaredbu.

Prvo, moramo stvoriti GitCommand klase kao što smo to učinili za našu naredbu Hello World:

@Command javna klasa GitCommand implementira Runnable {public static void main (String [] args) {CommandLine.run (novi GitCommand (), args); } @Override public void run () {System.out.println ("Popularna git naredba"); }}

4. Dodavanje podnaredbi

The git naredba nudi puno podnaredbi - dodaj, predaj, daljinski, i još mnogo toga. Ovdje ćemo se usredotočiti na dodati i počiniti.

Dakle, naš će cilj ovdje biti prijaviti ta dva podzapovjedništva glavnom zapovjedništvu. Pikokli nudi tri načina da se to postigne.

4.1. Koristiti @Naredba Bilješka o nastavi

The @Naredba anotacija nudi mogućnost registracije podnaredbi putem podzapovjedništva parametar:

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

U našem slučaju dodajemo dvije nove klase: GitAddCommand i GitCommitCommand. Oba su označena s @Naredba i provesti Izvodljivo. Važno je dati im ime jer će ih koristiti pikokli prepoznati koju podnaredbu (e) treba izvršiti:

@Command (name = "add") javna klasa GitAddCommand implementira Runnable {@Override public void run () {System.out.println ("Dodavanje nekih datoteka u scensko područje"); }}
@Command (name = "commit") javna klasa GitCommitCommand implementira Runnable {@Override public void run () {System.out.println ("Predavanje datoteka u scenskom području, kako je divno?"); }}

Stoga, ako pokrenemo našu glavnu naredbu s dodati kao argument, konzola će se pojaviti "Dodavanje nekih datoteka u scensko područje".

4.2. Koristiti @Naredba Bilješka o metodama

Drugi način deklariranja podnaredbi je stvoriti @Naredba-annotirane metode koje predstavljaju te naredbe u GitCommand razred:

@Command (name = "add") javna void addCommand () {System.out.println ("Dodavanje nekih datoteka u područje postavljanja"); } @Command (name = "commit") public void commitCommand () {System.out.println ("Predavanje datoteka u scenskom području, kako je divno?"); }

Na taj način možemo izravno implementirati svoju poslovnu logiku u metode, a ne stvarati zasebne klase koje će to rukovati.

4.3. Programsko dodavanje podnaredbi

Konačno, pikokli nudi nam mogućnost programske registracije naših podnaredbi. Ovaj je malo nezgodniji, jer moramo stvoriti CommandLine objekt koji omotava našu naredbu, a zatim joj dodajte naredbe:

CommandLine commandLine = novi CommandLine (novi GitCommand ()); commandLine.addSubcommand ("dodaj", novi GitAddCommand ()); commandLine.addSubcommand ("commit", novi GitCommitCommand ());

Nakon toga još moramo izvršiti zapovjedništvo, ali ne možemo iskoristiti CommandLine.run () metoda više. Sada moramo nazvati parseWithHandler () metoda na našem novostvorenom CommandLine objekt:

commandLine.parseWithHandler (novi RunLast (), args);

Trebali bismo primijetiti upotrebu RunLast razred, koji govori pikokli za pokretanje najkonkretnije potkomande. Postoje još dva rukovatelja naredbama koje pruža pikokli: RunFirst i Pokreni sve. Prvi izvršava najvišu naredbu, dok drugi upravlja svim njima.

Kada se koristi praktična metoda CommandLine.run (), RunLast obrađivač se koristi prema zadanim postavkama.

5. Upravljanje opcijama pomoću @Opcija Bilješka

5.1. Opcija bez argumenta

Pogledajmo sada kako dodati neke opcije našim naredbama. Doista, željeli bismo reći svoje dodati naredba da treba dodati sve izmijenjene datoteke. Da bi to postigli, dodati ćemo polje označeno s @Opcija bilješka našem GitAddCommand razred:

@Option (names = {"-A", "--all"}) private boolean allFiles; @Override public void run () {if (allFiles) {System.out.println ("Dodavanje svih datoteka u mjesto za postavljanje"); } else {System.out.println ("Dodavanje nekih datoteka u scensko područje"); }}

Kao što vidimo, bilješka uzima a imena parametar, koji daje različita imena opcije. Stoga, pozivanje dodati narediti s bilo kojim -A ili -svi postavit će sve datoteke polje do pravi. Dakle, ako pokrenemo naredbu s opcijom, prikazat će se konzola "Dodavanje svih datoteka u scensko područje".

5.2. Opcija s argumentom

Kao što smo upravo vidjeli, za opcije bez argumenata njihova se prisutnost ili odsutnost uvijek procjenjuje na boolean vrijednost.

Međutim, moguće je registrirati opcije koje uzimaju argumente. To možemo učiniti jednostavnim proglašavanjem svog polja drugim tipom. Dodajmo a poruka opcija za naš počiniti naredba:

@Option (names = {"-m", "--message"}) privatna niska poruka; @Override public void run () {System.out.println ("Predavanje datoteka u scenskom području, kako je divno?"); if (poruka! = null) {System.out.println ("Poruka urezivanja je" + poruka); }}

Nije iznenađujuće, kad je dobio poruka opcija, naredba će prikazati poruku urezivanja na konzoli. Dalje u članku obradit ćemo s kojim tipovima rukuje knjižnica i kako postupati s drugim vrstama.

5.3. Opcija s više argumenata

Ali sada, što ako želimo da naša naredba uzima više poruka, kao što se radi sa stvarnom git počiniti naredba? Bez brige, učinimo da naše polje bude niz ili a Kolekcija, i prilično smo gotovi:

@Option (names = {"-m", "--message"}) privatne String [] poruke; @Override public void run () {System.out.println ("Predavanje datoteka u scenskom području, kako je divno?"); if (messages! = null) {System.out.println ("Poruka urezivanja je"); for (String message: messages) {System.out.println (poruka); }}}

Sada možemo koristiti poruka opcija više puta:

commit -m "Moje urezivanje je sjajno" -m "Moje urezivanje je lijepo"

Međutim, možda bismo željeli dati opciju samo jednom i razdvojiti različite parametre regex graničnikom. Stoga možemo koristiti podjela parametar @Opcija napomena:

@Option (names = {"-m", "--message"}, split = ",") privatni niz [] poruka;

Sad možemo proći -m "Moja predaja je sjajna", "Moja predaja je lijepa" kako bi se postigao isti rezultat kao gore.

5.4. Potrebna opcija

Ponekad možemo imati potrebnu opciju. The potreban argument, koji je prema zadanim postavkama lažno, omogućuje nam to:

@Option (names = {"-m", "--message"}, obavezno = true) private String [] poruke;

Sada je nemoguće nazvati počiniti naredbu bez navođenja poruka opcija. Ako to pokušamo učiniti, pikokli ispisat će pogrešku:

Nedostaje potrebna opcija '--message =' Upotreba: git commit -m = [-m =] ... -m, --message =

6. Upravljanje pozicijskim parametrima

6.1. Hvatanje pozicijskih parametara

Sad, usredotočimo se na naše dodati naredba jer još nije jako moćna. Možemo samo odlučiti dodati sve datoteke, ali što ako bismo htjeli dodati određene datoteke?

Za to bismo mogli koristiti drugu opciju, ali ovdje bi bolji izbor bio korištenje pozicijskih parametara. Doista, pozicijski parametri namijenjeni su hvatanju naredbenih argumenata koji zauzimaju određene položaje i nisu ni podnaredbe ni opcije.

U našem primjeru to bi nam omogućilo nešto poput:

dodaj datoteku1 datoteku2

Da bi se uhvatili pozicijski parametri, iskoristit ćemo @Parameters bilješka:

Datoteke privatnog popisa @Parameters; @Override public void run () {if (allFiles) {System.out.println ("Dodavanje svih datoteka u mjesto za postavljanje"); } if (datoteke! = null) {files.forEach (putanja -> System.out.println ("Dodavanje" + putanja + "na mjesto postavljanja")); }}

Sada bi naša naredba od ranije ispisala:

Dodavanje datoteke1 u scensko područje Dodavanje datoteke2 u scensko područje

6.2. Snimite podskup pozicijskih parametara

Moguće je preciznije odrediti koje pozicijske parametre snimiti zahvaljujući indeks parametar bilješke. Indeks se temelji na nuli. Dakle, ako definiramo:

@Parametri (indeks = "2 .. *")

Ovo bi obuhvatilo argumente koji se ne podudaraju s opcijama ili podnaredbama, od trećeg do kraja.

Indeks može biti raspon ili jedan broj koji predstavlja jednu poziciju.

7. Riječ o pretvorbi tipova

Kao što smo vidjeli ranije u ovom vodiču, pikokli obrađuje neku pretvorbu tipa sam. Na primjer, preslikava više vrijednosti u nizovi ili Zbirke, ali također može preslikati argumente na određene tipove, na primjer kada koristimo Staza razred za dodati naredba.

Zapravo, pikokli dolazi s hrpom vrsta prethodno obrađenih vrsta. To znači da te vrste možemo koristiti izravno, a da sami ne razmišljamo o njihovoj konverziji.

Međutim, možda ćemo trebati preslikati svoje naredbene argumente na tipove koji nisu već obrađeni. Na našu sreću, to je moguće zahvaljujući ITypeConverter sučelje i CommandLine # registerConverter metoda koja asocira tip na pretvarač.

Zamislimo da želimo dodati znak konfiguracija potkomandu našem git naredbu, ali ne želimo da korisnici mijenjaju element konfiguracije koji ne postoji. Dakle, odlučili smo preslikati te elemente u nabrajanje:

javni popis ConfigElement {USERNAME ("user.name"), EMAIL ("user.email"); privatna konačna vrijednost niza; ConfigElement (vrijednost niza) {this.value = value; } javna vrijednost niza () {povratna vrijednost; } javni statički ConfigElement iz (vrijednost niza) {return Arrays.stream (values ​​()) .filter (element -> element.value.equals (value)) .findFirst () .orElseThrow (() -> new IllegalArgumentException ("The argument "+ vrijednost +" ne odgovara nijednom ConfigElementu ")); }}

Osim toga, u našem novostvorenom GitConfigCommand klase, dodajmo dva pozicijska parametra:

@Parameters (index = "0") privatni element ConfigElement; @Parameters (index = "1") vrijednost privatnog niza; @Preuzmi javno void vođenje () {System.out.println ("Postavljanje" + element.value () + "na" + vrijednost); }

Na ovaj način osiguravamo da korisnici neće moći mijenjati nepostojeće elemente konfiguracije.

Napokon, moramo registrirati naš pretvarač. Lijepo je to što, ako koristimo Javu 8 ili noviju, ne moramo ni stvoriti klasu koja implementira ITypeConverter sučelje. Jednostavno možemo proslijediti referencu lambda ili metode registerConverter () metoda:

CommandLine commandLine = novi CommandLine (novi GitCommand ()); commandLine.registerConverter (ConfigElement.class, ConfigElement :: from); commandLine.parseWithHandler (novi RunLast (), args);

To se događa u GitCommand glavni() metoda. Imajte na umu da smo morali pustiti pogodnost CommandLine.run () metoda.

Kada se koristi s neobrađenim elementom konfiguracije, naredba će prikazati poruku pomoći plus dio informacija koji nam govori da parametar nije moguće pretvoriti u ConfigElement:

Nevažeća vrijednost za pozicijski parametar u indeksu 0 (): ne može pretvoriti 'user.phone' u ConfigElement (java.lang.IllegalArgumentException: Argument user.phone ne odgovara nijednom ConfigElementu) Upotreba: git config 

8. Integriranje s Spring Boot-om

Napokon, pogledajmo kako sve to Springify!

Zapravo, možda radimo u Spring Boot okruženju i želimo imati koristi od toga u našem programu naredbenog retka. Da bi to učinili, moramo stvoriti a SpringBootApplicationprovedba CommandLineRunner sučelje:

@SpringBootApplication aplikacija javne klase implementira CommandLineRunner {public static void main (String [] args) {SpringApplication.run (Application.class, args); } @Override public void run (String ... args) {}}

Plus, označimo sve svoje naredbe i podzapovjednike Springom @Komponenta bilješka i automatski spojite sve to u našem Primjena:

privatni GitCommand gitCommand; privatni GitAddCommand addCommand; privatni GitCommitCommand commitCommand; privatni GitConfigCommand configCommand; javna aplikacija (GitCommand gitCommand, GitAddCommand addCommand, GitCommitCommand commitCommand, GitConfigCommand configCommand) {this.gitCommand = gitCommand; this.addCommand = addCommand; this.commitCommand = commitCommand; this.configCommand = configCommand; }

Imajte na umu da smo morali automatski povezivati ​​svaku podnaredbu. Nažalost, to je zato što, za sada, pikokli još nije u mogućnosti dohvatiti naredbe iz konteksta Spring kada se deklarativno deklariraju (s bilješkama). Stoga ćemo to ožičenje morati izvesti sami, na programski način:

@Override public void run (String ... args) {CommandLine commandLine = novi CommandLine (gitCommand); commandLine.addSubcommand ("dodaj", dodajCommand); commandLine.addSubcommand ("predati", predatiCommand); commandLine.addSubcommand ("config", configCommand); commandLine.parseWithHandler (novi CommandLine.RunLast (), args); }

I sada, naš program naredbenog retka djeluje poput čarapa s komponentama Spring. Stoga bismo mogli stvoriti neke klase usluga i koristiti ih u našim naredbama, a Spring pustiti da se pobrine za ubrizgavanje ovisnosti.

9. Zaključak

U ovom smo članku vidjeli neke ključne značajke pikokli knjižnica. Naučili smo kako stvoriti novu naredbu i dodati joj neke naredbe. Vidjeli smo mnogo načina kako se nositi s opcijama i pozicijskim parametrima. Osim toga, naučili smo kako implementirati vlastite pretvarače tipova kako bi naše naredbe bile jako otkucane. Napokon, vidjeli smo kako unijeti Spring Boot u naše naredbe.

Naravno, o tome se može otkriti još mnogo stvari. Knjižnica pruža cjelovitu dokumentaciju.

Što se tiče cjelovitog koda ovog članka, on se može naći na našem GitHubu.