Dohvatite nazive klasa unutar JAR datoteke

1. Pregled

Većina Java knjižnica dostupna je u obliku JAR datoteka. U ovom uputstvu pozabavit ćemo se načinima donošenja naziva klasa unutar zadane JAR datoteke iz naredbenog retka i Java programa.

Zatim ćemo pogledati primjer Java programa za učitavanje klasa iz zadane JAR datoteke tijekom izvođenja.

2. Primjer JAR datoteke

U ovom ćemo uputstvu uzeti pruga-0.0.1-SNAPSHOT.jar datoteka kao primjer za adresiranje načina dobivanja naziva klasa u JAR datoteci:

3. Korištenje staklenka Naredba

JDK isporučuje s staklenka naredba. Ovu naredbu možemo koristiti s t i f opcije za popis sadržaja JAR datoteke:

$ jar tf stripe-0.0.1-SNAPSHOT.jar META-INF / META-INF / MANIFEST.MF ... predlošci / rezultat.html predlošci / checkout.html application.properties com / baeldung / stripe / StripeApplication.class com / baeldung / pruga / ChargeRequest.class com / baeldung / stripe / StripeService.class com / baeldung / pruga / ChargeRequest $ Currency.class ...

Budući da nas zanima samo * .razred datoteke u arhivi, izlaz možemo filtrirati pomoću datoteke grep naredba:

$ jar tf pruga-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 / pruga / CheckoutController.class

Ovo nam daje popis datoteka klase unutar JAR datoteke.

4. Dobivanje naziva klasa JAR datoteke na Javi

Koristiti staklenka naredba za ispis naziva klasa iz JAR datoteke prilično je jednostavna. Međutim, ponekad želimo učitati neke klase iz JAR datoteke u naš Java program. U ovom slučaju, izlaz naredbenog retka nije dovoljan.

Da bismo postigli svoj cilj, moramo skenirajte JAR datoteku iz Java programa i dobiti imena razreda.

Pogledajmo kako izvući imena klasa iz naše primjera JAR datoteke koristiti JarFile i JarEntry razreda:

javni statički skup getClassNamesFromJarFile (Datoteka givenFile) baca IOException {Set classNames = new HashSet (); try (JarFile jarFile = new JarFile (givenFile)) {Enumeration e = jarFile.entries (); while (e.hasMoreElements ()) {JarEntry jarEntry = e.nextElement (); if (jarEntry.getName (). endsWith (". class")) {String className = jarEntry.getName () .replace ("/", ".") .replace (". class", ""); classNames.add (className); }} return classNames; }} 

Sada, pogledajmo bliže kod u gornjoj metodi i shvatimo kako on funkcionira:

  • probajte (JarFile jarFile = novi JarFile (givenFile)) - Evo, koristili smo izjavu try-with-resources da bismo dobili jarFile od datog Datoteka objekt
  • if (jarEntry.getName (). ENDWith (“. class”)) {…} - Pohađamo svaki sat jarEntryi promijenite put datoteke klase u kvalificirano ime klase, na primjer promijenite “Package1 / package2 / SomeType.class” u “Package1.package2.SomeType”

Provjerimo može li metoda izvući imena klasa iz naše primjera JAR datoteke kroz metodu jedinstvenog testiranja:

privatni statički završni niz JAR_PATH = "example-jar / stripe-0.0.1-SNAPSHOT.jar"; privatni statički konačni set EXPECTED_CLASS_NAMES = Sets.newHashSet ("com.baeldung.stripe.StripeApplication", "com.baeldung.stripe.ChargeRequest", "com.baeldung.stripe.StripeService", "com.baeldung.stripe.ChargeRequest $. "," com.baeldung.stripe.ChargeController "," com.baeldung.stripe.CheckoutController "); @Test public void givenJarFilePath_whenLoadClassNames_thenGetClassNames () baca IOException, URISyntaxException {Datoteka jarFile = nova datoteka (Objects.requireNonNull (getClass (). GetClassLoader (). GetResource ()) getResource (). Postavite classNames = GetClassNamesFromJar.getClassNamesFromJarFile (jarFile); Assert.assertEquals (EXPECTED_CLASS_NAMES, imena klasa); } 

5. Dobivanje nastave iz JAR datoteke na Javi

Vidjeli smo kako dobiti nazive klasa iz JAR datoteke. Ponekad neke dinamike želimo učitati iz JAR datoteke u vrijeme izvođenja.

U ovom slučaju, imena klasa možemo prvo dobiti iz dane JAR datoteke pomoću naše getClassNamesFromJarFile metoda.

Dalje, možemo stvoriti ClassLoader za učitavanje potrebnih klasa po imenu:

javni statički Set getClassesFromJarFile (File jarFile) baca IOException, ClassNotFoundException {Set classNames = getClassNamesFromJarFile (jarFile); Postavi klase = novi HashSet (classNames.size ()); try (URLClassLoader cl = URLClassLoader.newInstance (new URL [] {new URL ("jar: file:" + jarFile + "! /"}})) {for (Naziv niza: classNames) {Class clazz = cl.loadClass ( Ime); // Učitaj klasu pod nazivom class.add (clazz); }} klase povratka; }

U gornjoj metodi stvorili smo a URLClassLoader objekt za učitavanje klasa. Provedba je prilično jednostavna.

Međutim, vjerojatno je vrijedno malo objasniti sintaksu za JAR URL. Važeći JAR URL sadrži tri dijela: “tegla: + [mjesto JAR datoteke] + !/”.

Završetak!/”Označava da se JAR URL odnosi na cijelu JAR datoteku. Pogledajmo nekoliko primjera JAR URL-a:

jar: //www.example.com/some_jar_file.jar! / jar: datoteka: /local/path/to/some_jar_file.jar! / jar: file: / C: /windows/path/to/some_jar_file.jar! /

U našem getClassesFromJarFile metoda, datoteka JAR nalazi se na lokalnom datotečnom sustavu, stoga je prefiks URL-a "datoteka:“.

Napišimo sada test metodu kako bismo provjerili može li naša metoda dobiti sve što se očekuje Razred objekti:

@Test public void givenJarFilePath_whenLoadClass_thenGetClassObjects () baca IOException, ClassNotFoundException, URISyntaxException {File jarFile = new File (Objects.requireNonNull (getClass (). GetClassIar. GetClassLar. GetClassLar. GetClassLar. Postavite klase = GetClassNamesFromJar.getClassesFromJarFile (jarFile); Postavite imena = class.stream (). Map (Class :: getName) .collect (Collectors.toSet ()); Assert.assertEquals (EXPECTED_CLASS_NAMES, imena); } 

Jednom kad imamo traženo Razred objektima, pomoću refleksije Java možemo stvoriti instance klasa i pozvati metode.

6. Zaključak

U ovom smo članku naučili dva različita pristupa za dobivanje naziva klasa iz zadane JAR datoteke.

The staklenka naredba može ispisati imena klasa. Prilično je zgodno ako moramo provjeriti sadrži li JAR datoteka zadanu klasu. Međutim, ako trebamo dobiti nazive klasa iz pokrenutog Java programa, JarFile i JarEntry može nam pomoći da to postignemo.

Napokon smo vidjeli i primjer Java programa za učitavanje klasa iz JAR datoteke tijekom izvođenja.

Kao i uvijek, puni izvorni kôd članka dostupan je na GitHub-u.