2013-11-22 12 views
11

Ich habe eine einfache Struktur: Eine Data JAR-Datei, die einen Batch von Daten enthält, und eine Service-JAR-Datei, die einen Dienst unter Verwendung der Daten ausführt. Um die Daten einfach zu ersetzen, habe ich sie getrennt, und der Klassenpfad von service.jar enthält das Verzeichnis, in dem sich data.jar befindet.Zugriff auf Ressourcen aus einer anderen JAR-Datei

Innerhalb der Datei service.jar verwende ich getResource, um die Datendateien zu laden. Dies funktioniert, wenn sich die Datendateien direkt im Ordner befinden, aber fehlschlägt, wenn sie sich in data.jar befinden.

Dies schlägt fehl:

all 
+ globalclasspath 
| + data.jar 
| + mine.properties 
+ daemons 
    + service.jar 

jsvc -cp globalclasspath:daemons/service.jar (...) 

MyClass.class.getClassLoader().getResource("mine.properties"); // <-- null 

Aber das funktioniert:

all 
+ globalclasspath 
| + mine.properties 
+ daemons 
    + service.jar 

jsvc -cp globalclasspath:daemons/service.jar (...) 

MyClass.class.getClassLoader().getResource("mine.properties"); // <-- not null 

Ich will nicht den Classpath ändern (wenn ich es zu etwas ändern kann, generic, die auf dem nicht davon abhängen, Name der Datenjar-Datei), aber ich bin in Ordnung mit dem Ändern der Zeichenfolge getResource (Ich habe versucht,/Data/min.properties und /data.jar/mine.properties vergeblich). Gibt es eine Änderung, die ich vornehmen kann, damit die Ressourcen aus dem Glas geladen werden können?

Antwort

5

Lösung 1

Verwenden Sie einen Platzhalter Classpath.

jsvc -cp globalclasspath/*:daemons/service.jar (...) 

Siehe "How to use a wildcard in the classpath to add multiple jars?"

Lösung 2

Um Daten in JAR-Dateien nicht auf dem Classpath zu lesen, verwenden URLClassLoader. Der allgemeine Algorithmus lautet wie folgt:

  1. Suchen Sie die Liste der JARs im Verzeichnis globalclasspath.
  2. Erstellen Sie eine URLClassLoader aus dieser Liste von JARs.
  3. Suchen Sie die gewünschte Ressource von der URLClassLoader Instanz.

Um JAR-Dateien auf dem Classpath zu finden, habe ich ResourceList aus dem Stackoverflow Artikel „Get a list of resources from classpath directory“.

public class MyClass { 
    /** 
    * Creates a {@code URLClassLoader} from JAR files found in the 
    * globalclasspath directory, assuming that globalclasspath is in 
    * {@code System.getProperty("java.class.path")}. 
    */ 
    private static URLClassLoader createURLClassLoader() { 
     Collection<String> resources = ResourceList.getResources(Pattern.compile(".*\\.jar")); 
     Collection<URL> urls = new ArrayList<URL>(); 
     for (String resource : resources) { 
      File file = new File(resource); 
      // Ensure that the JAR exists 
      // and is in the globalclasspath directory. 
      if (file.isFile() && "globalclasspath".equals(file.getParentFile().getName())) { 
       try { 
        urls.add(file.toURI().toURL()); 
       } catch (MalformedURLException e) { 
        // This should never happen. 
        e.printStackTrace(); 
       } 
      } 
     } 
     return new URLClassLoader(urls.toArray(new URL[urls.size()])); 
    } 

    public static void main(String[] args) { 
     URLClassLoader classLoader = createURLClassLoader(); 
     System.out.println(classLoader.getResource("mine.properties")); 
    } 
} 

ich den folgenden Befehl lautete:

java -cp globalclasspath:daemons/service.jar MyClass 

Das Terminal-Ausgang:

jar:file:/workspace/all/globalclasspath/data.jar!/mine.properties 
1

Haben Sie getResourceAsStream versucht, wie hier vorgeschlagen:

how-to-a-read-file-from-jar-in-java

+0

Sorry, ich bin mit 'getResourceAsStream' eigentlich schon (schrieb ich' getResource' weil ich wasn Ich bin mir keiner Unterschiede bewusst und es schien einfacher zu sein. – Dave