2013-11-22 4 views
11

Ho una struttura semplice: un file jar di dati che contiene un batch di dati e un file jar di servizio, che esegue un servizio utilizzando i dati. Per semplificare la sostituzione dei dati, li ho separati e classpath di service.jar contiene la directory in cui si trova data.jar.Accesso alle risorse da un altro file jar

All'interno di service.jar, utilizzo getResource per caricare i file di dati. Funziona se i file di dati sono direttamente all'interno della cartella, ma falliscono quando si trovano all'interno di data.jar;

Questo fallisce:

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

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

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

Ma questo funziona:

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

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

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

Io non voglio cambiare il classpath (a meno che non posso cambiare a qualcosa di generico, che non dipende dalla nome del file jar dei dati), ma sto bene cambiando la stringa getResource (ho provato /data/mine.properties e /data.jar/mine.properties senza alcun risultato). C'è un cambiamento che posso fare in modo che le risorse possano essere caricate dall'interno del barattolo?

risposta

5

Soluzione 1

utilizzare un carattere jolly percorso di classe.

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

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

Soluzione 2

di leggere i dati in vasi non sul classpath, utilizzare URLClassLoader. L'algoritmo generale è questo:

  1. Trova l'elenco di JAR nella directory globalclasspath.
  2. Creare un URLClassLoader da questo elenco di JAR.
  3. Cercare la risorsa desiderata dall'istanza URLClassLoader.

Per trovare JAR nel classpath, ho usato ResourceList dall'articolo StackOverflow "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")); 
    } 
} 

Ho eseguito il seguente comando:

java -cp globalclasspath:daemons/service.jar MyClass 

L'uscita del terminale:

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

Hai provato getResourceAsStream come suggerito qui:

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

+0

Siamo spiacenti, In realtà sto usando 'getResourceAsStream' già (ho scritto' getResource' perché non ero consapevole di qualsiasi differenza e sembrava più semplice) – Dave