Kavanozun içindeki dosya ilkbaharda görünmüyor


107

Herşey

İçinde aşağıdaki MANIFEST.MF ile bir jar dosyası oluşturdum:

Manifest-Version: 1.0
Ant-Version: Apache Ant 1.8.3
Created-By: 1.6.0_25-b06 (Sun Microsystems Inc.)
Main-Class: my.Main
Class-Path: . lib/spring-core-3.2.0.M2.jar lib/spring-beans-3.2.0.M2.jar

Kökünde, spring-context.xml dosyamda şu şekilde referans verilen my.config adında bir dosya var:

<bean id="..." class="...">
    <property name="resource" value="classpath:my.config" />
</bean>

Kavanozu çalıştırırsam, o dosyanın yüklenmesi dışında her şey yolunda görünüyor:

Caused by: java.io.FileNotFoundException: class path resource [my.config] cannot be resolved to absolute file path because it does not reside in the file system: jar:file:/D:/work/my.jar!/my.config
        at org.springframework.util.ResourceUtils.getFile(ResourceUtils.java:205)
    at org.springframework.core.io.AbstractFileResolvingResource.getFile(AbstractFileResolvingResource.java:52)
    at eu.stepman.server.configuration.BeanConfigurationFactoryBean.getObject(BeanConfigurationFactoryBean.java:32)
    at eu.stepman.server.configuration.BeanConfigurationFactoryBean.getObject(BeanConfigurationFactoryBean.java:1)
    at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:142)
    ... 22 more
  • sınıflar kavanozun içinden yüklenir
  • yay ve diğer bağımlılıklar ayrı kavanozlardan yüklenir
  • bahar bağlamı yüklendi (yeni ClassPathXmlApplicationContext ("spring-context / applicationContext.xml"))
  • my.properties, PropertyPlaceholderConfigurer'a yüklenir ("sınıf yolu: my.properties")
  • .config dosyamı dosya sisteminin dışına koyarsam ve kaynak url'sini 'dosya:' olarak değiştirirsem, her şey yolunda görünüyor ...

Herhangi bir ipucu?

Yanıtlar:


217

Spring-context.xml ve my.config dosyalarınız farklı kavanozlarda ise, o zaman kullanmanız gerekecek classpath*:my.config?

Daha fazla bilgi burada

Ayrıca, emin kullandığınız yapmak resource.getInputStream()değil resource.getFile()ne zaman bir kavanoz dosyasından içinden yükleniyor.


1
Bunlar aynı kavanozda, ancak çözümünüzü aynı sonuçla denedim: java.io.FileNotFoundException: sınıf yolu kaynağı [classpath *: my.config], mevcut olmadığı için URL'ye çözümlenemiyor
BTakacs

14
Tekrar baktığımızda, bazı arama kodunuz (muhtemelen BeanConfigurationFactoryBean) bir java.io.File yüklemeye çalışıyor. Dosya, bir jar dosyasındaki girişlerin olmadığı, dosya sistemindeki dosyaları ifade eder. Çağıran kod, bir jar'ten yüklemek yerine resource.getInputStream kullanıyor olmalıdır.
sbk

60
... ve cevap BU ... Teşekkürler! Bir kavanozun içinde resource.getFile () kullanmayın :-)
BTakacs

2
bir "neden" olma ihtimali var mı? kavanozun içinde getFile () kullanmamanın arkasında? Basitçe dosya Jar'ın içinde mi ve dolayısıyla "dosya" jar dosyası mı?
RockMeetHardplace

8
Bu kadar. Bir java.io.File, dosya sistemindeki bir dizin yapısındaki bir dosyayı temsil eder. Kavanoz bir java.io.File dosyasıdır. Ancak bu dosyadaki herhangi bir şey java.io.File'ın erişemeyeceği bir yerdedir. Java söz konusu olduğunda, sıkıştırılmamış olana kadar, jar dosyasındaki bir sınıf, bir sözcük belgesindeki bir sözcükten farklı değildir.
sbk

53

Bu sorunun zaten cevaplandığını biliyorum. Ancak, yaylı önyükleme kullananlar için bu bağlantı bana yardımcı oldu - https://smarterco.de/java-load-file-classpath-spring-boot/

Ancak, resourceLoader.getResource("classpath:file.txt").getFile();bu soruna ve sbk'nin yorumuna neden oluyordu:

Bu kadar. Bir java.io.File, dosya sistemindeki bir dizin yapısındaki bir dosyayı temsil eder. Kavanoz bir java.io.File dosyasıdır. Ancak bu dosyadaki herhangi bir şey java.io.File'ın erişemeyeceği bir yerdedir. Java söz konusu olduğunda, sıkıştırılmamış olana kadar, jar dosyasındaki bir sınıf, bir sözcük belgesindeki bir sözcükten farklı değildir.

getInputStream()bunun yerine neden kullanılacağını anlamama yardımcı oldu . Şimdi benim için çalışıyor!

Teşekkürler!


39

Bahar kavanozu paketinde, ClassPathResource(filename).getFile()istisnayı atan yeni kullanıyorum :

dosya sisteminde bulunmadığı için mutlak dosya yoluna çözümlenemiyor: jar

Ancak kullanmak new ClassPathResource(filename).getInputStream()bu sorunu çözecektir. Bunun nedeni, jar'deki konfigürasyon dosyasının işletim sisteminin dosya ağacında olmaması, bu yüzden kullanılması gerekir getInputStream().


2

Tomcat6.x'i kullanırken benzer bir sorun yaşadım ve bulduğum hiçbir tavsiye yardımcı olmadı. Sonunda work(Tomcat'in) klasörünü sildim ve sorun ortadan kalktı.

Mantıksız olduğunu biliyorum ama dokümantasyon amaçlı ...


1

@Sbk'nin cevabı, bence ilkbahar önyükleme ortamında (@Value ("$ {classpath *:}) dışında) yapmamız gereken yol. kavanoz .. yanlış bir şey yapmış olabilirim.

Ancak bu, bunu yapmanın başka bir yolu olabilir.

InputStream is = this.getClass().getClassLoader().getResourceAsStream(<relative path of the resource from resource directory>);

1

Daha karmaşık bir sorun yaşıyordum çünkü aynı isimli birden fazla dosyam var, biri ana Spring Boot kavanozunda ve diğerleri ana yağ kavanozunun içinde kavanozlarda. Çözümüm, tüm kaynakları aynı isimde almaktı ve bundan sonra paket adına göre filtrelemeye ihtiyacım olanı elde ettim. Tüm dosyaları almak için:

ResourceLoader resourceLoader = new FileSystemResourceLoader();
final Enumeration<URL> systemResources = resourceLoader.getClassLoader().getResources(fileNameWithoutExt + FILE_EXT);

0

Spring uygulamamdaki kaynakları yinelemeli olarak yüklerken bir sorun yaşıyordum ve sorunun kullanmam gerektiğini fark ettim resource.getInputStream. İşte yinelemeli tüm dosyalarda nasıl okunacağını gösteren bir örnek config/myfilesolduğu jsondosyaları.

Example.java

private String myFilesResourceUrl = "config/myfiles/**/";
private String myFilesResourceExtension = "json";

ResourceLoader rl = new ResourceLoader();

// Recursively get resources that match. 
// Big note: If you decide to iterate over these, 
// use resource.GetResourceAsStream to load the contents
// or use the `readFileResource` of the ResourceLoader class.
Resource[] resources = rl.getResourcesInResourceFolder(myFilesResourceUrl, myFilesResourceExtension);

// Recursively get resource and their contents that match. 
// This loads all the files into memory, so maybe use the same approach 
// as this method, if need be.
Map<Resource,String> contents = rl.getResourceContentsInResourceFolder(myFilesResourceUrl, myFilesResourceExtension);

ResourceLoader.java

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.util.StreamUtils;

public class ResourceLoader {
  public Resource[] getResourcesInResourceFolder(String folder, String extension) {
    ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
    try {
      String resourceUrl = folder + "/*." + extension;
      Resource[] resources = resolver.getResources(resourceUrl);
      return resources;
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

  public String readResource(Resource resource) throws IOException {
    try (InputStream stream = resource.getInputStream()) {
      return StreamUtils.copyToString(stream, Charset.defaultCharset());
    }
  }

  public Map<Resource, String> getResourceContentsInResourceFolder(
      String folder, String extension) {
    Resource[] resources = getResourcesInResourceFolder(folder, extension);

    HashMap<Resource, String> result = new HashMap<>();
    for (var resource : resources) {
      try {
        String contents = readResource(resource);
        result.put(resource, contents);
      } catch (IOException e) {
        throw new RuntimeException("Could not load resource=" + resource + ", e=" + e);
      }
    }
    return result;
  }
}

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.