caricare una risorsa contenuta in un barattolo


21

Nella mia domanda ho caricare le risorse in questo modo:

WinProcessor.class.getResource("repository").toString(); 

e questo mi dà:

file:/root/app/repository (and I replace "file:" with empty string) 

Questo funziona bene quando faccio funzionare la mia applicazione dall'IDE , ma quando ho eseguito il vaso della mia candidatura:

java -jar app.jar 

il percorso diventa:

jar:/root/app.jar!/repository 

c'è un modo per risolvere questo problema?

Userò il "repository" nome dir al fine di creare questa:

ConfigurationContext ctx = (ConfigurationContext) ConfigurationContextFactory.createConfigurationContextFromFileSystem(repositoryString, null); 

Allo stesso modo, vado a prendere un nome di file (invece di un dir) e userò in questo modo:

System.setProperty("javax.net.ssl.trustStore", fileNameString) 
35

Sembra che tu stia cercando di caricare la risorsa utilizzando uno FileInputStream o qualcosa del genere. Non farlo: invece di chiamare getResource, chiama getResourceAsStream e leggi i dati da quello.

(è possibile caricare le risorse dal URL invece, ma chiamare getResourceAsStream è un po 'più conveniente.)

EDIT: Dopo aver visto la tua risposta aggiornato, a quanto pare altri pezzi di codice si basano sui dati di essere in un singolo file fisico nel file system. La risposta quindi non è di raggrupparla in un file jar in primo luogo. È possibile verificare se si trova in un file separato, e se non estrarlo in un file temporaneo, ma è IMO piuttosto hacky.

+1

Accetto. Ogni volta che non puoi dire con certezza al 100% che ti occuperai di singoli file fisici (java web start per uno) devi sempre codificare con i flussi. 22 feb. 092009-02-22 12:16:38


5

costruire una URL, è possibile caricare una risorsa (anche in un file jar) utilizzando il metodo openStream.

+1

Questo è ciò che 'getResourceAsStream' fa. 12 lug. 162016-07-12 14:20:56


9

Quando si esegue il codice utilizzando java -jar app.jar, java utilizza SOLO il percorso di classe definito nel manifest del file JAR (ovvero l'attributo Class-Path). Se la classe è in app.jar o la classe si trova nel percorso classe impostato nell'attributo Class-Path del manifest di JAR, è possibile caricare tale classe utilizzando il seguente frammento di codice, in cui lo className è il nome di classe completo.

final String classAsPath = className.replace('.', '/') + ".class"; 
final InputStream input = ClassLoader.getSystemResourceAsStream(path/to/class); 

Ora, se la classe non fa parte della JAR, e non è nel manifesto del Class-Path, quindi il caricatore di classe non lo troverete. Invece, è possibile utilizzare lo URLClassLoader, con un po 'di attenzione per gestire le differenze tra Windows e Unix/Linux/MacOSX.

// the class to load 
final String classAsPath = className.replace('.', '/') + ".class"; 

// the URL to the `app.jar` file (Windows and Unix/Linux/MacOSX below) 
final URL url = new URL("file", null, "///C:/Users/diffusive/app.jar"); 
//final URL url = new URL("file", null, "/Users/diffusive/app.jar"); 

// create the class loader with the JAR file 
final URLClassLoader urlClassLoader = new URLClassLoader(new URL[] { url }); 

// grab the resource, through, this time from the `URLClassLoader` object 
// rather than from the `ClassLoader` class 
final InputStream input = urlClassLoader.getResourceAsStream(classAsPath); 

In entrambi gli esempi di cui ha bisogno per affrontare le eccezioni, e il fatto che il flusso di input è null se la risorsa non può essere trovato. Inoltre, se è necessario ottenere lo InputStream in un byte[], è possibile utilizzare i comuni di Apache IOUtils.toByteArray(...). E, se successivamente si desidera un Class, è possibile utilizzare il metodo defineClass(...) del caricatore di classi, che accetta lo byte[].

È possibile trovare questo codice in una classe ClassLoaderUtils nel codice sorgente diffusivo, che potete trovare su SourceForge a github.com/robphilipp/diffusive

E un metodo per creare URL per Windows e Unix/Linux/MacOSX da percorsi relativi e assoluti in RestfulDiffuserManagerResource.createJarClassPath(...)