Charger une ressource contenue dans un bocal


21

Dans mon application je charge les ressources de cette manière:

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

et cela me donne:

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

Cela fonctionne bien quand je lance mon application à partir de l'IDE , mais quand je lance le pot de ma demande:

java -jar app.jar 

le chemin devient:

jar:/root/app.jar!/repository 

est-il un moyen de résoudre ce problème?

Je vais utiliser le nom de répertoire « référentiel » afin de créer ceci:

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

De la même manière, je vais en obtenir un nom de fichier (au lieu d'un répertoire) et je vais utiliser cette façon:

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

Il semble que vous essayez ensuite de charger la ressource en utilisant un FileInputStream ou quelque chose comme ça. Ne faites pas cela: au lieu d'appeler getResource, appelez le getResourceAsStream et lisez les données de cela.

(Vous pouvez charger les ressources de l'URL au lieu, mais appeler getResourceAsStream est un peu plus pratique.)

EDIT: Après avoir vu votre réponse mise à jour, il semble d'autres morceaux de code se fondent sur les données dans un fichier unique physique dans le système de fichiers. La réponse est donc de ne pas le regrouper dans un fichier jar en premier lieu. Vous pouvez vérifier si c'est dans un fichier séparé, et si ce n'est pas l'extraire dans un fichier temporaire, mais c'est assez IMO hacky.

+1

D'accord. Chaque fois que vous ne pouvez pas dire avec une certitude de 100% que vous allez traiter avec des fichiers individuels physiques (java web start pour un), vous devriez toujours coder avec des flux. 22 févr.. 092009-02-22 12:16:38


5

construire un URL, vous pouvez charger une ressource (même dans un fichier jar) en utilisant la méthode openStream.

+1

C'est ce que 'getResourceAsStream' fait. 12 juil.. 162016-07-12 14:20:56


9

Lors de l'exécution du code en utilisant java -jar app.jar, java utilise UNIQUEMENT le chemin de classe défini dans le manifeste du fichier JAR (c'est-à-dire l'attribut Class-Path). Si la classe est dans app.jar ou si la classe se trouve dans le chemin de classe défini dans l'attribut Class-Path du manifeste JAR, vous pouvez charger cette classe à l'aide de l'extrait de code suivant, où className est le nom de classe pleinement qualifié.

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

Maintenant, si la classe ne fait pas partie du JAR, et il est pas dans le manifeste de Class-Path, le chargeur de classe ne le trouvera pas. Au lieu de cela, vous pouvez utiliser le URLClassLoader, en faisant attention aux différences entre Windows et 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); 

Dans les deux exemples que vous aurez besoin pour traiter les exceptions, et le fait que le flux d'entrée est null si la ressource ne peut pas être trouvé. En outre, si vous devez obtenir le InputStream dans un byte[], vous pouvez utiliser les communs d'Apache IOUtils.toByteArray(...). Et, si vous voulez ensuite un Class, vous pouvez utiliser la méthode defineClass(...) du chargeur de classe, qui accepte le byte[].

Vous pouvez trouver ce code dans une classe ClassLoaderUtils dans le code source Diffusive, que vous pouvez trouver sur SourceForge à github.com/robphilipp/diffusive

Et une méthode pour créer l'URL pour Windows et Unix/Linux/MacOSX à partir de chemins relatifs et absolus dans RestfulDiffuserManagerResource.createJarClassPath(...)