קבל שמות של כיתות בתוך קובץ JAR

1. סקירה כללית

מרבית ספריות Java זמינות כקבצי JAR. במדריך זה נעסוק כיצד להשיג שמות של שיעורים בתוך קובץ JAR נתון משורת הפקודה ומתוכנית Java.

לאחר מכן, נסתכל על דוגמה של תוכנית Java לטעינת הכיתות מקובץ JAR נתון בזמן הריצה.

2. דוגמה לקובץ JAR

במדריך זה ניקח את פס-0.0.1-SNAPSHOT.jar קובץ כדוגמה לטיפול כיצד להשיג את שמות הכיתות בקובץ JAR:

3. באמצעות קַנקַן פקודה

JDK שולח עם קַנקַן פקודה. אנו יכולים להשתמש בפקודה זו עם ה- t ו f אפשרויות לרשימת התוכן של קובץ JAR:

$ jar tf stripe-0.0.1-SNAPSHOT.jar META-INF / META-INF / MANIFEST.MF ... תבניות / תבניות result.html / checkout.html application.properties com / baeldung / stripe / StripeApplication.class com / baeldung / stripe / ChargeRequest.class com / baeldung / stripe / StripeService.class com / baeldung / stripe / ChargeRequest $ Currency.class ...

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

$ jar tf stripe-0.0.1-SNAPSHOT.jar | grep '\ .class $' com / baeldung / stripe / StripeApplication.class com / baeldung / stripe / ChargeRequest.class com / baeldung / stripe / StripeService.class com / baeldung / stripe / ChargeRequest $ Currency.class com / baeldung / stripe /ChargeController.class com / baeldung / strip / CheckoutController.class

זה נותן לנו רשימה של קבצי מחלקה בתוך קובץ JAR.

4. קבלת שמות כיתות של קובץ JAR בג'אווה

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

כדי להשיג את המטרה שלנו, אנחנו צריכים סרוק את קובץ ה- JAR מתוכנת Java ולקבל את שמות הכיתות.

בואו נסתכל כיצד לחלץ שמות כיתות מקובץ JAR לדוגמא משתמש ב JarFile ו ג'רנטרי שיעורים:

סט סטטי ציבורי getClassNamesFromJarFile (File givenFile) זורק IOException {Set classNames = HashSet new (); נסה (JarFile jarFile = JarFile חדש (givenFile)) {Enumeration e = jarFile.entries (); בעוד (e.hasMoreElements ()) {JarEntry jarEntry = e.nextElement (); אם (jarEntry.getName (). endsWith (". class")) {String className = jarEntry.getName () .replace ("/", "."). place (". class", ""); classNames.add (className); }} להחזיר classNames; }} 

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

  • נסה (JarFile jarFile = JarFile חדש (givenFile)) - הנה, השתמשנו בהצהרת ניסיון-עם-משאבים כדי להשיג את jarFile מהנתון קוֹבֶץ לְהִתְנַגֵד
  • אם (jarEntry.getName (). endsWith (". class")) {...} אנחנו לוקחים כל שיעור jarEntry, ושנה את הנתיב של קובץ הכיתה לשם הכיתה המוסמכת, למשל שינוי "Package1 / package2 / SomeType.class" לְתוֹך "Package1.package2.SomeType"

בואו נוודא אם השיטה יכולה לחלץ את שמות המחלקות מקובץ ה- JAR לדוגמא שלנו באמצעות שיטת בדיקת יחידה:

סופי סטטי פרטי מחרוזת JAR_PATH = "דוגמה-צנצנת / פס-0.0.1-SNAPSHOT.jar"; סופי סטטי פרטי סט EXPECTED_CLASS_NAMES = Sets.newHashSet ("com.baeldung.stripe.StripeApplication", "com.baeldung.stripe.ChargeRequest", "com.baeldung.stripe.StripeService", "com.baeldung.stripe.ChargeRequest $ Currency "," com.baeldung.stripe.ChargeController "," com.baeldung.stripe.CheckoutController "); @Test ציבורי בטל givenJarFilePath_whenLoadClassNames_thenGetClassNames () זורק IOException, URISyntaxException {File jarFile = קובץ חדש (Objects.requireNonNull (getClass (). GetClassLoader (). GetResource (JAR_PATH)). הגדר classNames = GetClassNamesFromJar.getClassNamesFromJarFile (jarFile); Assert.assertEquals (EXPECTED_CLASS_NAMES, classNames); } 

5. קבלת שיעורים מקובץ JAR בג'אווה

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

במקרה זה, תחילה נוכל לקבל את שמות הכיתות מקובץ ה- JAR הנתון באמצעות שלנו getClassNamesFromJarFile שיטה.

בשלב הבא נוכל ליצור ClassLoader לטעינת שיעורים נדרשים לפי שם:

סט סטטי ציבורי getClassesFromJarFile (קובץ jarFile) זורק IOException, ClassNotFoundException {Set classNames = getClassNamesFromJarFile (jarFile); הגדר כיתות = HashSet חדש (classNames.size ()); נסה (URLClassLoader cl = URLClassLoader.newInstance (URL חדש [] {new URL ("jar: file:" + jarFile + "! /")})) {עבור (שם מחרוזת: classNames) {Class clazz = cl.loadClass ( שֵׁם); // טען את הכיתה לפי השמות class.add (clazz); }} שיעורים חוזרים; }

בשיטה לעיל, יצרנו a URLClassLoader התנגד לטעינת הכיתות. היישום די פשוט.

עם זאת, כנראה שכדאי להסביר מעט את התחביר עבור כתובת ה- JAR. כתובת אתר JAR חוקית מכילה שלושה חלקים: “קַנקַן: + [המיקום של קובץ ה- JAR] + !/”.

הסיום "!/”מציין שכתובת ה- JAR מתייחסת לקובץ JAR שלם. בואו נראה כמה דוגמאות ל- JAR URL:

צנצנת: //www.example.com/some_jar_file.jar! / jar: file: /local/path/to/some_jar_file.jar! / jar: file: / C: /windows/path/to/some_jar_file.jar! /

בשלנו getClassesFromJarFile בשיטה, קובץ ה- JAR ממוקם במערכת הקבצים המקומית, ולכן הקידומת של כתובת ה- URL היא “קוֹבֶץ:“.

עכשיו, בואו נכתוב שיטת בדיקה כדי לוודא אם השיטה שלנו יכולה להשיג את כל המצופה מעמד חפצים:

@Test ציבורי בטל givenJarFilePath_whenLoadClass_thenGetClassObjects () זורק IOException, ClassNotFoundException, URISyntaxException {File jarFile = קובץ חדש (Objects.requireNonNull (getClass (). GetClassLoader ().). הגדר מחלקות = GetClassNamesFromJar.getClassesFromJarFile (jarFile); הגדר שמות = class.stream (). מפה (Class :: getName) .collect (Collectors.toSet ()); Assert.assertEquals (EXPECTED_CLASS_NAMES, שמות); } 

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

6. מסקנה

במאמר זה למדנו שתי גישות שונות לקבלת שמות כיתות מקובץ JAR נתון.

ה קַנקַן הפקודה יכולה להדפיס את שמות הכיתות. זה די שימושי אם עלינו לבדוק אם קובץ JAR מכיל מחלקה נתונה. עם זאת, אם עלינו לקבל את שמות הכיתות מתוכנית Java פועלת, JarFile ו ג'רנטרי יכול לעזור לנו להשיג זאת.

לבסוף ראינו גם דוגמא לתוכנית Java לטעינת שיעורים מקובץ JAR בזמן הריצה.

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