צור תוכנית שורת פקודה של Java עם Picocli

1. הקדמה

במדריך זה ניגש ל- פיקוקלי הספרייה, המאפשרת לנו ליצור בקלות תוכניות שורת פקודה בג'אווה.

ראשית נתחיל ביצירת פקודה Hello World. לאחר מכן נצלול עמוק לתכונות המפתח של הספרייה על ידי שכפול, חלקי, של ה- git פקודה.

2. שלום פיקוד העולם

נתחיל במשהו קל: פקודה Hello World!

ראשית, עלינו להוסיף את התלות ב- פיקוקלי פּרוֹיֶקט:

 info.picocli picocli 3.9.6 

כפי שאנו רואים, נשתמש ב- 3.9.6 גרסת הספרייה, אם כי א 4.0.0 הגרסה נמצאת בבנייה (זמינה כעת במבחן אלפא).

עכשיו עם הגדרת התלות, בואו ניצור את הפקודה Hello World שלנו. על מנת לעשות זאת, נשתמש ב- @פקודה ביאור מהספריה:

@ Command (name = "שלום", תיאור = "אומר שלום") מעמד ציבורי HelloWorldCommand {}

כפי שאנו רואים, ההערה יכולה לקחת פרמטרים. אנו משתמשים רק בשניים מהם כאן. מטרתם לספק מידע אודות הפקודה הנוכחית והטקסט להודעת העזרה האוטומטית.

כרגע, אין הרבה מה שאנחנו יכולים לעשות עם פקודה זו. כדי לגרום לזה לעשות משהו, עלינו להוסיף a רָאשִׁי שיטת קריאה הנוחות CommandLine.run (Runnable, String []) שיטה. זה לוקח שני פרמטרים: מופע של הפקודה שלנו, ולכן צריך ליישם את ניתן לרוץ ממשק, ו חוּט מערך המייצג את ארגומנטים הפקודה (אפשרויות, פרמטרים ותתי-פקודות):

מחלקה ציבורית HelloWorldCommand מיישמת Runnable {public static void main (String [] args) {CommandLine.run (HelloWorldCommand חדש (), args); } @ ביטול הפעלה בטלנית ציבורית () {System.out.println ("שלום עולם!"); }}

עכשיו, כשאנחנו מנהלים את רָאשִׁי בשיטה, נראה שהקונסולות מוציאות "שלום עולם!"

כאשר אנו ארוזים לצנצנת, אנו יכולים להריץ את הפקודה Hello World באמצעות ה- ג'אווה פקודה:

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

ללא הפתעה, זה גם פלט את "שלום עולם!" מחרוזת למסוף.

3. מקרה שימוש קונקרטי

עכשיו, כשראינו את היסודות, נצלול עמוק לתוך ה פיקוקלי סִפְרִיָה. על מנת לעשות זאת, אנו הולכים לשחזר, באופן חלקי, פקודה פופולרית: git.

כמובן, המטרה לא תהיה ליישם את git התנהגות פקודה אך כדי לשחזר את האפשרויות של git פקודה - אילו תת-פקודות קיימות ואילו אפשרויות זמינות לפקודת משנה מוזרה.

ראשית, עלינו ליצור GitCommand כמו שעשינו לפקודת Hello World שלנו:

מחלקה ציבורית @Command GitCommand מיישמת Runnable {public static void main (String [] args) {CommandLine.run (GitCommand חדש (), args); } @Override public void run () {System.out.println ("פקודת git הפופולרית"); }}

4. הוספת תת-פקודות

ה git הפקודה מציעה הרבה תת-פקודות - להוסיף, להתחייב, להרחיק, ועוד רבים. נתמקד כאן ב לְהוֹסִיף ו לְבַצֵעַ.

לכן, מטרתנו כאן תהיה להכריז על שתי תתי-הפקודות האלה לפקודה הראשית. פיקוקלי מציע שלוש דרכים להשיג זאת.

4.1. משתמש ב @פקודה ביאור לשיעורים

ה @פקודה ביאור מציע אפשרות לרשום תתי-פקודות באמצעות תת-פקודות פָּרָמֶטֶר:

@Command (תת-פקודות = {GitAddCommand.class, GitCommitCommand.class})

במקרה שלנו, אנו מוסיפים שתי מחלקות חדשות: GitAddCommand ו GitCommitCommand. שניהם מוסברים עם @פקודה וליישם ניתן לרוץ. חשוב לתת להם שם, מכיוון שהשמות ישמשו אותם פיקוקלי לזהות איזה פקודות משנה לבצע:

@Command (name = "add") מחלקה ציבורית GitAddCommand מיישם Runnable {@Override public void run () {System.out.println ("הוספת כמה קבצים לאיזור ההיערכות"); }}
@Command (name = "commit") מחלקה ציבורית GitCommitCommand מיישם Runnable {@Override public void run () {System.out.println ("ביצוע קבצים באזור ההיערכות, כמה נפלא?"); }}

לפיכך, אם אנו מריצים את הפקודה העיקרית שלנו עם לְהוֹסִיף כארגומנט, הקונסולה תפלט "הוספת כמה קבצים לאזור ההיערכות".

4.2. משתמש ב @פקודה ביאור על שיטות

דרך נוספת להכריז על תתי-פקודות היא לִיצוֹר @פקודה-שיטות המאושרות המייצגות פקודות אלה ב- GitCommand מעמד:

@Command (name = "add") ריק ריק addCommand () {System.out.println ("הוספת קבצים לאיזור ההיערכות"); } @ Command (name = "commit") public void commitCommand () {System.out.println ("ביצוע קבצים באזור ההיערכות, כמה נפלא?"); }

בדרך זו, אנו יכולים ליישם ישירות את ההיגיון העסקי שלנו בשיטות ולא ליצור שיעורים נפרדים לטיפול בו.

4.3. הוספת תת-פקודות באופן תכנותי

סוף כל סוף, פיקוקלי מציע לנו אפשרות לרשום את פקודות המשנה שלנו באופן פרוגרמטי. זה קצת יותר מסובך, מכיוון שעלינו ליצור CommandLine אובייקט שעוטף את הפקודה שלנו ואז הוסף לה את תת-הפקודות:

CommandLine commandLine = CommandLine חדש (GitCommand חדש ()); commandLine.addSubcommand ("הוסף", GitAddCommand חדש ()); commandLine.addSubcommand ("commit", GitCommitCommand חדש ());

אחרי זה, אנחנו עדיין צריכים להפעיל את הפקודה שלנו, אבל אנחנו לא יכולים לעשות שימוש ב- CommandLine.run () שיטה יותר. עכשיו, אנחנו חייבים להתקשר ל parseWithHandler () שיטה על C החדש שנוצראומנדליין לְהִתְנַגֵד:

commandLine.parseWithHandler (חדש RunLast (), args);

עלינו לציין את השימוש ב- RunLast בכיתה, המספרת פיקוקלי להפעלת פקודת המשנה הספציפית ביותר. ישנם שני מטפלי פיקוד נוספים שמספקים פיקוקלי: RunFirst ו RunAll. הראשון מפעיל את הפקודה העליונה, ואילו האחרון מפעיל את כולם.

כאשר משתמשים בשיטת הנוחות CommandLine.run (), ה RunLast המטפל משמש כברירת מחדל.

5. ניהול אפשרויות באמצעות @אוֹפְּצִיָה ביאור

5.1. אפשרות ללא ויכוח

בואו נראה כעת כיצד להוסיף כמה אפשרויות לפקודות שלנו. ואכן, ברצוננו לספר את שלנו לְהוֹסִיף פקודה כי עליו להוסיף את כל הקבצים שהשתנו. כדי להשיג זאת, נוסיף שדה עם הערה עם @אוֹפְּצִיָה ביאור שלנו GitAddCommand מעמד:

@Option (names = {"-A", "--all"}) allFiles בוליאני פרטי; @ ביטול הפעלה בטלנית ציבורית () {if (allFiles) {System.out.println ("הוספת כל הקבצים לאזור ההיערכות"); } אחר {System.out.println ("הוספת כמה קבצים לאזור ההיערכות"); }}

כפי שאנו רואים, ההערה אורכת שמות פרמטר, אשר נותן את השמות השונים של האופציה. לכן, קורא לְהוֹסִיף פקודה עם אחד מהם אוֹ -את כל יקבע את כל הקבצים שדה ל נָכוֹן. לכן, אם נפעיל את הפקודה עם האפשרות, המסוף יופיע "הוספת כל הקבצים לאזור ההיערכות".

5.2. אפשרות עם ויכוח

כפי שראינו זה עתה, עבור אפשרויות ללא ויכוחים, נוכחותם או היעדרותם מוערכים תמיד ל- a בוליאני ערך.

עם זאת, ניתן לרשום אפשרויות שלוקחות טיעונים. אנו יכולים לעשות זאת פשוט על ידי הכרזת התחום שלנו מסוג אחר. בואו נוסיף a הוֹדָעָה אפשרות שלנו לְבַצֵעַ פקודה:

@ Option (names = {"-m", "--message"}) הודעת מחרוזת פרטית; @Override public void run () {System.out.println ("ביצוע קבצים באזור ההיערכות, כמה נפלא?"); if (message! = null) {System.out.println ("הודעת ההתחייבות היא" + הודעה); }}

באופן לא מפתיע, כאשר נותנים את הוֹדָעָה אפשרות, הפקודה תציג את הודעת ההתחייבות במסוף. בהמשך המאמר נסקור אילו סוגים מטפלים בספרייה וכיצד לטפל בסוגים אחרים.

5.3. אפשרות עם ארגומנטים מרובים

אבל עכשיו, מה אם אנו רוצים שהפקודה שלנו תקבל מספר הודעות, כפי שנעשה עם האמיתי git commit פקודה? אין דאגות, בואו נהפוך את התחום שלנו להיות מַעֲרָך או א אוסףוגמרנו די:

@Option (names = {"-m", "--message"}) הודעות מחרוזת [] פרטיות; @Override public void run () {System.out.println ("ביצוע קבצים באזור ההיערכות, כמה נפלא?"); אם (הודעות! = null) {System.out.println ("הודעת ההתחייבות היא"); עבור (הודעת מחרוזת: הודעות) {System.out.println (הודעה); }}}

כעת, אנו יכולים להשתמש ב- הוֹדָעָה אפשרות מספר פעמים:

להתחייב -m "ההתחייבות שלי היא נהדרת" -מ "ההתחייבות שלי יפה"

עם זאת, ייתכן שנרצה לתת את האפשרות רק פעם אחת ולהפריד בין הפרמטרים השונים על ידי מפריד regex. לפיכך, אנו יכולים להשתמש ב- לְפַצֵל פרמטר של @אוֹפְּצִיָה ביאור:

@Option (names = {"-m", "--message"}, split = ",") הודעות מחרוזת [] פרטיות;

עכשיו, אנחנו יכולים לעבור -m "ההתחייבות שלי גדולה", "ההתחייבות שלי יפה" כדי להשיג את אותה התוצאה כמו לעיל.

5.4. אפשרות חובה

לפעמים, תהיה לנו אפשרות הנדרשת. ה נדרש טענה, אשר ברירת מחדל היא שֶׁקֶר, מאפשר לנו לעשות זאת:

@Option (names = {"-m", "--message"}, חובה = true) הודעות מחרוזת [] פרטיות;

עכשיו אי אפשר להתקשר ל לְבַצֵעַ פקודה מבלי לציין את הוֹדָעָה אוֹפְּצִיָה. אם ננסה לעשות זאת, פיקוקלי ידפיס שגיאה:

חסרה אפשרות חובה '--message =' שימוש: git commit -m = [-m =] ... -m, --message =

6. ניהול פרמטרים מיקוםיים

6.1. לכידת פרמטרים למיקום

עכשיו, בואו נתמקד ב לְהוֹסִיף פקודה כי היא עדיין לא חזקה במיוחד. אנחנו יכולים להחליט רק להוסיף את כל הקבצים, אבל מה אם נרצה להוסיף קבצים ספציפיים?

נוכל להשתמש באפשרות אחרת לשם כך, אך אפשרות טובה יותר כאן תהיה להשתמש בפרמטרים מיקוםיים. אכן, פרמטרים של מיקום נועדו ללכוד ארגומנטים של פקודה שתופסים עמדות ספציפיות ואינם פקודות משנה ולא אפשרויות.

בדוגמה שלנו, זה יאפשר לנו לעשות משהו כמו:

הוסף קובץ 1 קובץ 2

על מנת לתפוס פרמטרים מיקוםיים, נשתמש ב- @פרמטרים ביאור:

@Parameters קבצי רשימה פרטיים; @ ביטול הפעלה בטלנית ציבורית () {if (allFiles) {System.out.println ("הוספת כל הקבצים לאזור ההיערכות"); } אם (קבצים! = null) {files.forEach (path -> System.out.println ("הוספת" + נתיב + "לאזור ההיערכות")); }}

כעת, הפקודה שלנו מקודם תדפיס:

הוספת קובץ 1 לאזור ההיערכות הוספת קובץ 2 לאזור ההיערכות

6.2. צלם קבוצת משנה של פרמטרים מיקום

אפשר להיות מדויקים יותר לגבי הפרמטרים המיקוםיים לתפוס, הודות ל- אינדקס פרמטר ההערה. המדד מבוסס על אפס. לפיכך, אם נגדיר:

@Parameters (אינדקס = "2 .. *")

זה יתפוס טיעונים שאינם תואמים אפשרויות או תת-פקודות, מהשלישית ועד הסוף.

האינדקס יכול להיות טווח או מספר בודד, המייצג מיקום יחיד.

7. מילה על המרת סוג

כפי שראינו קודם במדריך זה, פיקוקלי מטפל בהמרה מסוג כלשהו בפני עצמו. לדוגמה, הוא ממפה ערכים מרובים אל מערכים אוֹ אוספים, אך הוא יכול גם למפות טיעונים לסוגים ספציפיים כמו כאשר אנו משתמשים ב- נָתִיב כיתה עבור לְהוֹסִיף פקודה.

למעשה, פיקוקלי מגיע עם חבורה של סוגים שטופלו מראש. המשמעות היא שנוכל להשתמש בסוגים אלה ישירות מבלי שנצטרך לחשוב להמיר אותם בעצמנו.

עם זאת, ייתכן שנצטרך למפות את טיעוני הפקודה שלנו לסוגים אחרים מאלה שכבר מטופלים. למזלנו, זה אפשרי בזכות ממיר IType ממשק ו- CommandLine # registerConverter שיטה, המקשרת סוג לממיר.

בואו נדמיין שאנחנו רוצים להוסיף את config פקודת משנה שלנו git פקודה, אך איננו רוצים שמשתמשים ישנו אלמנט תצורה שאינו קיים. לכן, אנו מחליטים למפות את האלמנטים הללו לאומה:

enum ציבורי ConfigElement {USERNAME ("user.name"), EMAIL ("user.email"); ערך סופי פרטי מחרוזת; ConfigElement (ערך מחרוזת) {this.value = value; } ערך מחרוזת ציבורי () {ערך החזרה; } ConfigElement סטטי ציבורי מ- (ערך מחרוזת) {return Arrays.stream (values ​​()) .filter (element -> element.value.equals (value)) .findFirst () .orElseThrow (() -> IllegalArgumentException ("The IllegalArgumentException" הארגומנט "+ value +" אינו תואם שום ConfigElement ")); }}

בנוסף, לאחרונה שנוצרנו GitConfigCommand מחלקה, בואו נוסיף שני פרמטרים מיקומיים:

@Parameters (index = "0") רכיב ConfigElement פרטי; @Parameters (index = "1") ערך מחרוזת פרטי; @ ביטול הפעלה בטלנית ציבורית () {System.out.println ("הגדרת" + element.value () + "ל-" + value); }

בדרך זו אנו מוודאים כי המשתמשים לא יוכלו לשנות רכיבי תצורה שאינם קיימים.

לבסוף, עלינו לרשום את הממיר שלנו. מה שיפה הוא שאם אנו משתמשים בג'אווה 8 ומעלה, אנחנו אפילו לא צריכים ליצור מחלקה המיישמת את ממיר IType מִמְשָׁק. אנחנו יכולים פשוט להעביר למבדה או התייחסות לשיטה registerConverter () שיטה:

CommandLine commandLine = CommandLine חדש (GitCommand חדש ()); commandLine.registerConverter (ConfigElement.class, ConfigElement :: from); commandLine.parseWithHandler (RunLast חדש (), טענות);

זה קורה ב GitCommand רָאשִׁי() שיטה. שימו לב שהיינו צריכים להרפות מהנוחות CommandLine.run () שיטה.

כאשר משתמשים בו עם אלמנט תצורה שלא מטופל, הפקודה תציג את הודעת העזרה בתוספת פיסת מידע שתאמר לנו שלא ניתן להמיר את הפרמטר ל- ConfigElement:

ערך לא חוקי עבור פרמטר מיקום באינדקס 0 (): לא יכול להמיר את 'user.phone' ל- ConfigElement (java.lang.IllegalArgumentException: הארגומנט user.phone אינו תואם שום ConfigElement) שימוש: git config 

8. שילוב עם מגף קפיץ

לבסוף, בואו נראה איך להקפיץ את כל זה!

ואכן, אנו עשויים לעבוד בסביבת Spring Boot ונרצה ליהנות ממנה בתוכנית שורת הפקודה שלנו. על מנת לעשות זאת, עלינו ליצור יישום SpringBootיישום ה- CommandLineRunner מִמְשָׁק:

@SpringBootApplication מחלקה ציבורית יישום מיישם את CommandLineRunner {public static void main (String [] args) {SpringApplication.run (Application.class, args); } @Override הפעלה בטלנית ציבורית (מחרוזת ... טוענת) {}}

ועוד, בואו נרשום את כל הפקודות והתתי-פקודות שלנו עם האביב @רְכִיב ביאור וחוט אוטומטי כל זה שלנו יישום:

פרטי GitCommand gitCommand; פרטי GitAddCommand addCommand; פרטי GitCommitCommand commitCommand; פרטי GitConfigCommand configCommand; יישום ציבורי (GitCommand gitCommand, GitAddCommand addCommand, GitCommitCommand commitCommand, GitConfigCommand configCommand) {this.gitCommand = gitCommand; this.addCommand = addCommand; this.commitCommand = commitCommand; this.configCommand = configCommand; }

שים לב שהיינו חייבים לבצע חוט אוטומטי בכל פקודת משנה. למרבה הצער, זה בגלל, לעת עתה, פיקוקלי אינו מסוגל עדיין לאחזר תתי-פקודות מהקשר האביב כאשר הם מוכרזים בהצהרה (עם ביאורים). לפיכך, נצטרך לבצע את החיווט בעצמנו, באופן פרוגרמטי:

@ עקוף הפעלה בטלנית ציבורית (String ... args) {CommandLine commandLine = CommandLine חדש (gitCommand); commandLine.addSubcommand ("הוסף", addCommand); commandLine.addSubcommand ("commit", commitCommand); commandLine.addSubcommand ("config", configCommand); commandLine.parseWithHandler (CommandLine.RunLast חדש (), טוען); }

ועכשיו, תוכנית שורת הפקודה שלנו עובדת כמו קסם עם רכיבי אביב. לכן, נוכל ליצור כמה שיעורי שירות ולהשתמש בהם בפקודות שלנו, ולתת לאביב לטפל בהזרקת התלות.

9. מסקנה

במאמר זה ראינו כמה תכונות עיקריות של ה- פיקוקלי סִפְרִיָה. למדנו כיצד ליצור פקודה חדשה ולהוסיף לה כמה פקודות משנה. ראינו דרכים רבות להתמודד עם אפשרויות ופרמטרים מיקוםיים. בנוסף, למדנו כיצד ליישם ממירי סוג משלנו כדי להקליד את הפקודות שלנו. לבסוף ראינו כיצד להביא את Spring Boot לפקודות שלנו.

כמובן שיש עוד הרבה דברים לגלות בנושא. הספרייה מספקת תיעוד מלא.

באשר לקוד המלא של מאמר זה, ניתן למצוא אותו ב- GitHub שלנו.


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