En CLI med Spring Shell
1. Oversikt
Enkelt sagt, Spring Shell-prosjektet gir et interaktivt skall for behandling av kommandoer og bygging av en fullverdig CLI ved hjelp av vårprogrammeringsmodellen.
I denne artikkelen vil vi utforske funksjonene, nøkkelklassene og merknadene, og implementere flere tilpassede kommandoer og tilpasninger.
2. Maven avhengighet
Først må vi legge til vårskall avhengighet til vår pom.xml:
org.springframework.shell spring-shell 1.2.0.RELEASE
Den siste versjonen av denne gjenstanden finner du her.
3. Få tilgang til skallet
Det er to måter å få tilgang til skallet i applikasjonene våre.
Den første er å bootstrape skallet i inngangspunktet til applikasjonen vår og la brukeren skrive inn kommandoene:
public static void main (String [] args) kaster IOException {Bootstrap.main (args); }
Det andre er å få en JLineShellComponent og utføre kommandoene programmatisk:
Bootstrap bootstrap = ny Bootstrap (); JLineShellComponent shell = bootstrap.getJLineShellComponent (); shell.executeCommand ("hjelp");
Vi skal bruke den første tilnærmingen siden den passer best for eksemplene i denne artikkelen, men i kildekoden kan du finne testtilfeller som bruker det andre skjemaet.
4. Kommandoer
Det er allerede flere innebygde kommandoer i skallet, som f.eks klar, hjelp, exitosv. som gir standardfunksjonaliteten til alle CLI-er.
Egendefinerte kommandoer kan eksponeres ved å legge til metoder merket med @CliCommand kommentar inne i en vårkomponent som implementerer CommandMarker grensesnitt.
Hvert argument av denne metoden må merkes med a @CliOption merknad, hvis vi ikke klarer dette, vil vi støte på flere feil når vi prøver å utføre kommandoen.
4.1. Legge til kommandoer i skallet
Først må vi la skallet vite hvor kommandoene våre er. For dette krever det filen META-INF / vår / vår-skall-plugin.xml for å være til stede i prosjektet vårt, der, kan vi bruke komponentskanningsfunksjonaliteten til Spring:
Når komponentene er registrert og instantiert av Spring, blir de registrert i skallparseren, og merknadene deres behandles.
La oss lage to enkle kommandoer, en for å hente innholdet i en URL og vise dem, og den andre for å lagre innholdet i en fil:
@Komponent offentlig klasse SimpleCLI implementerer CommandMarker {@CliCommand (verdi = {"web-get", "wg"}) offentlig String webGet (@CliOption (key = "url") String url) {return getContentsOfUrlAsString (url); } @CliCommand (value = {"web-save", "ws"}) offentlig String webSave (@CliOption (key = "url") String url, @CliOption (key = {"out", "file"}) Streng fil) {Strenginnhold = getContentsOfUrlAsString (url); prøv (PrintWriter ut = ny PrintWriter (fil)) {out.write (innhold); } returner "Ferdig."; }}
Merk at vi kan sende mer enn én streng til verdi og nøkkel attributter av @CliCommand og @CliOption henholdsvis dette tillater oss å avsløre flere kommandoer og argumenter som oppfører seg likt.
La oss nå sjekke om alt fungerer som forventet:
spring-shell> web-get --url //www.google.com web-save --url //www.google.com --out contents.txt Ferdig.
4.2. Tilgjengelighet av kommandoer
Vi kan bruke @CliAvailabilityIndicator kommentar på en metode som returnerer en boolsk for å endre, ved kjøretid, hvis en kommando skulle bli utsatt for skallet.
La oss først lage en metode for å endre tilgjengeligheten av web-lagre kommando:
privat boolsk adminEnableExecuted = false; @CliAvailabilityIndicator (value = "web-save") offentlig boolsk isAdminEnabled () {retur adminEnableExecuted; }
La oss nå lage en kommando for å endre adminEnableExecuted variabel:
@CliCommand (verdi = "admin-aktivere") offentlig streng adminEnable () {adminEnableExecuted = true; returner "Admin-kommandoer aktivert."; }
Til slutt, la oss bekrefte det:
spring-shell> web-save --url //www.google.com --out contents.txt Kommandoen 'web-save --url //www.google.com --out contents.txt' ble funnet, men er ikke for øyeblikket tilgjengelig (skriv 'hjelp', deretter ENTER for å lære mer om denne kommandoen) spring-shell> admin-aktivere Admin-kommandoer aktivert. spring-shell> web-save --url //www.google.com --out contents.txt Ferdig.
4.3. Nødvendige argumenter
Som standard er alle kommandoargumenter valgfrie. Imidlertid kan vi gjøre dem nødvendige med påbudt, bindende attributt til @CliOption kommentar:
@CliOption (key = {"out", "file"}, obligatorisk = true)
Nå kan vi teste at hvis vi ikke introduserer det, resulterer det i en feil:
spring-shell> web-save --url //www.google.com Du bør angi alternativet (--out) for denne kommandoen
4.4. Standardargumenter
En tom nøkkel verdi for en @CliOption gjør argumentet til standard. Der vil vi motta verdiene introdusert i skallet som ikke er en del av noe navngitt argument:
@CliOption (key = {"", "url"})
La oss nå sjekke at det fungerer som forventet:
spring-shell> web-get //www.google.com
4.5. Hjelpe brukere
@CliCommand og @CliOption merknader gir en hjelp attributt som lar oss veilede brukerne når vi bruker den innebygde hjelp kommandoen eller når du faner for å få automatisk fullføring.
La oss endre vår web-get for å legge til tilpassede hjelpemeldinger:
@CliCommand (// ... help = "Viser innholdet i en URL") offentlig String webGet (@CliOption (// ... help = "URL hvis innhold vil bli vist.") String url) {//. ..}
Nå kan brukeren vite nøyaktig hva kommandoen vår gjør:
spring-shell> help web-get Keyword: web-get Keyword: wg Beskrivelse: Viser innholdet i en URL. Søkeord: ** standard ** Søkeord: url Hjelp: URL hvis innhold vil bli vist. Obligatorisk: false Standard hvis spesifisert: '__NULL__' Standard hvis ikke spesifisert: '__NULL__' * web-get - Viser innholdet i en URL. * wg - Viser innholdet i en URL.
5. Tilpasning
Det er tre måter å tilpasse skallet ved å implementere BannerProvider, PromptProvider og HistoryFileNameProvider grensesnitt, alle med standardimplementeringer som allerede er gitt.
Vi må også bruke @Rekkefølge kommentar for å tillate leverandørene våre å gå foran disse implementeringene.
La oss lage et nytt banner for å begynne vår tilpasning:
@Component @Order (Ordered.HIGHEST_PRECEDENCE) offentlig klasse SimpleBannerProvider utvider DefaultBannerProvider {public String getBanner () {StringBuffer buf = new StringBuffer (); buf.append ("===========================================") .append (OsUtils .LINE_SEPARATOR); buf.append ("* Baeldung Shell *") .append (OsUtils.LINE_SEPARATOR); buf.append ("===========================================") .append (OsUtils .LINE_SEPARATOR); buf.append ("Versjon:") .append (this.getVersion ()); retur buf.toString (); } offentlig String getVersion () {return "1.0.1"; } public String getWelcomeMessage () {return "Velkommen til Baeldung CLI"; } public String getProviderName () {return "Baeldung Banner"; }}
Merk at vi også kan endre versjonsnummer og velkomstmelding.
La oss endre ledeteksten:
@Component @Order (Ordered.HIGHEST_PRECEDENCE) offentlig klasse SimplePromptProvider utvider DefaultPromptProvider {public String getPrompt () {return "baeldung-shell"; } public String getProviderName () {return "Baeldung Prompt"; }}
Til slutt, la oss endre navnet på historikkfilen:
@Component @Order (Ordered.HIGHEST_PRECEDENCE) offentlig klasse SimpleHistoryFileNameProvider utvider DefaultHistoryFileNameProvider {public String getHistoryFileName () {return "baeldung-shell.log"; } public String getProviderName () {return "Baeldung History"; }}
Historikkfilen registrerer alle kommandoer som er utført i skallet, og blir lagt sammen med applikasjonen vår.
Med alt på plass kan vi ringe skallet vårt og se det i aksjon:
========================================== * Baeldung Shell * ======== ================================= Versjon: 1.0.1 Velkommen til Baeldung CLI baeldung-shell>
6. Omformere
Så langt har vi bare brukt enkle typer som argumenter for kommandoene våre. Vanlige typer som Heltall, Dato, Enum, Fil, etc., har en standardkonverter allerede registrert.
Ved å implementere Konverter grensesnitt, kan vi også legge til omformerne for å motta egendefinerte objekter.
La oss lage en omformer som kan transformere en String inn i en URL:
@Komponent offentlig klasse SimpleURLConverter implementerer Converter {public URL convertFromText (String value, Class requiredType, String optionContext) {return new URL (value); } offentlig boolsk getAllPossibleValues (Listefullførelser, Class requiredType, String existingData, String optionContext, MethodTarget target) {return false; } offentlige boolske støtter (Class requiredType, String optionContext) {return URL.class.isAssignableFrom (requiredType); }}
Til slutt, la oss endre vår web-get og web-lagre kommandoer:
public String webSave (... URL url) {// ...} public String webSave (... URL url) {// ...}
Som du kanskje har gjettet, oppfører kommandoene seg det samme.
7. Konklusjon
I denne artikkelen tok vi en kort titt på kjernefunksjonene i Spring Shell-prosjektet. Vi var i stand til å bidra med kommandoene våre og tilpasse skallet med leverandørene våre, vi endret tilgjengeligheten av kommandoer i henhold til forskjellige kjøretidsforhold og opprettet en enkel type omformer.
Komplett kildekode for denne artikkelen finner du på GitHub.