2014-09-16 44 views
50

Bu sorunu hem Spring Boot 1.1.5'de hem de 1.1.6'da kullanmaktan - @Value notu kullanarak bir classpath kaynağı yüklüyorum. STS (3.6.0, Windows). Ancak, bir mvn paketi çalıştırıp jar'ı çalıştırmayı denediğimde, FileNotFound istisnalarını alıyorum.Kavanoz olarak çalıştırılırken Classpath kaynağı bulunamadı

Kaynak, message.txt, src/main/resources içinde. Kavanozu inceledim ve "message.txt" dosyasını en üst düzeyde (application.properties ile aynı düzeyde) içerdiğini doğruladım.

@Configuration 
@ComponentScan 
@EnableAutoConfiguration 
public class Application implements CommandLineRunner { 

    private static final Logger logger = Logger.getLogger(Application.class); 

    @Value("${message.file}") 
    private Resource messageResource; 

    public static void main(String[] args) { 
     SpringApplication.run(Application.class, args); 
    } 

    @Override 
    public void run(String... arg0) throws Exception { 
     // both of these work when running as Spring boot app from STS, but 
     // fail after mvn package, and then running as java -jar 
     testResource(new ClassPathResource("message.txt")); 
     testResource(this.messageResource); 
    } 

    private void testResource(Resource resource) { 
     try { 
      resource.getFile(); 
      logger.debug("Found the resource " + resource.getFilename()); 
     } catch (IOException ex) { 
      logger.error(ex.toString()); 
     } 
    } 
} 

istisna:

c:\Users\glyoder\Documents\workspace-sts-3.5.1.RELEASE\classpath-resource-proble 
m\target>java -jar demo-0.0.1-SNAPSHOT.jar 

    . ____   _   __ _ _ 
/\\/___'_ __ _ _(_)_ __ __ _ \ \ \ \ 
(()\___ | '_ | '_| | '_ \/ _` | \ \ \ \ 
\\/ ___)| |_)| | | | | || (_| | )))) 
    ' |____| .__|_| |_|_| |_\__, |//// 
=========|_|==============|___/=/_/_/_/ 
:: Spring Boot ::  (v1.1.5.RELEASE) 

2014-09-16 08:46:34.635 INFO 5976 --- [   main] demo.Application 
        : Starting Application on 8W59XV1 with PID 5976 (C:\Users\glyo 
der\Documents\workspace-sts-3.5.1.RELEASE\classpath-resource-problem\target\demo 
-0.0.1-SNAPSHOT.jar started by glyoder in c:\Users\glyoder\Documents\workspace-s 
ts-3.5.1.RELEASE\classpath-resource-problem\target) 
2014-09-16 08:46:34.640 DEBUG 5976 --- [   main] demo.Application 
        : Running with Spring Boot v1.1.5.RELEASE, Spring v4.0.6.RELEA 
SE 
2014-09-16 08:46:34.681 INFO 5976 --- [   main] s.c.a.AnnotationConfigA 
pplicationContext : Refreshing org.springframework.context.annotation.Annotation 
[email protected]: startup date [Tue Sep 16 08:46:34 EDT 2014]; 
root of context hierarchy 
2014-09-16 08:46:35.196 INFO 5976 --- [   main] o.s.j.e.a.AnnotationMBe 
anExporter  : Registering beans for JMX exposure on startup 
2014-09-16 08:46:35.210 ERROR 5976 --- [   main] demo.Application 
        : java.io.FileNotFoundException: class path resource [message. 
txt] cannot be resolved to absolute file path because it does not reside in the 
file system: jar:file:/C:/Users/glyoder/Documents/workspace-sts-3.5.1.RELEASE/cl 
asspath-resource-problem/target/demo-0.0.1-SNAPSHOT.jar!/message.txt 
2014-09-16 08:46:35.211 ERROR 5976 --- [   main] demo.Application 
        : java.io.FileNotFoundException: class path resource [message. 
txt] cannot be resolved to absolute file path because it does not reside in the 
file system: jar:file:/C:/Users/glyoder/Documents/workspace-sts-3.5.1.RELEASE/cl 
asspath-resource-problem/target/demo-0.0.1-SNAPSHOT.jar!/message.txt 
2014-09-16 08:46:35.215 INFO 5976 --- [   main] demo.Application 
        : Started Application in 0.965 seconds (JVM running for 1.435) 

2014-09-16 08:46:35.217 INFO 5976 --- [  Thread-2] s.c.a.AnnotationConfigA 
pplicationContext : Closing org.springframework.context.annotation.AnnotationCon 
[email protected]: startup date [Tue Sep 16 08:46:34 EDT 2014]; roo 
t of context hierarchy 
2014-09-16 08:46:35.218 INFO 5976 --- [  Thread-2] o.s.j.e.a.AnnotationMBe 
anExporter  : Unregistering JMX-exposed beans on shutdown 

cevap

73

resource.getFile() kaynak kendisi dosya sisteminde kullanılabilir olmasını bekler, yani bir kavanoz dosyası içinde iç içe olamaz

İşte uygulamadır. Bu nedenle, uygulamanızı STS'de çalıştırdığınızda çalışır, ancak uygulamanızı oluşturduktan ve çalıştırılabilir jar'dan çalıştırdığınızda çalışmaz. Kaynağın içeriğine erişmek için getFile() kullanmak yerine, bunun yerine getInputStream() kullanmanızı öneririz. Bu, kaynağın bulunduğu yerden bağımsız olarak içeriği okumanıza izin verir. Bir dosyayı kullanmak istiyorsanız

+1

, ihtiyacım anahtar deposu dosyasına bir yol sağlamak için (bir tomcat https konektörü uğruna) .Jks dosyasını kavanozumun içine sarmak istiyorum. Yukarıdaki çözüme göre bu mümkün değildir. Bunu yapmak için ek bir yol biliyor musunuz? – Modi

+0

Çok benzer bir gereksinime sahibim ve anahtar deposunu kavanozun bir parçası olarak ayarlamanıza izin veren apiler yok. @Modi, herhangi bir çözüm buldunuz mu? –

+0

Anahtar deposu kullanım durumu için mi demek istiyorsunuz? Tomcat ile Spring Boot kullanıyor musunuz? – Modi

23

:

String data = ""; 
ClassPathResource cpr = new ClassPathResource("static/file.txt"); 
try { 
    byte[] bdata = FileCopyUtils.copyToByteArray(cpr.getInputStream()); 
    data = new String(bdata, StandardCharsets.UTF_8); 
} catch (IOException e) { 
    LOG.warn("IOException", e); 
} 
18

Spring framework's FileCopyUtils kullanarak oldukça basittir ve sorunu çözmek için bu kitaplığı oluşturdu: Temel olarak, kaynak önyükleme kaynaklarını JAR'dan gelen Spring Boot ile özel bir ResourceLoader kaydettirebilirsiniz. gerekli, şeffaf.

+1

Bu, Bahar kullanıcıları için en iyi çözüm gibi görünüyor. Benim için harika çalıştı. – Lucas

2

Ben de bu sınırlamayı karşılaştı: o zaman bir String içine ClassPathResource okuma Bahar çerçevesini kullanıyorsanız

ClassPathResource classPathResource = new ClassPathResource("static/something.txt"); 

InputStream inputStream = classPathResource.getInputStream(); 
File somethingFile = File.createTempFile("test", ".txt"); 
try { 
    FileUtils.copyInputStreamToFile(inputStream, somethingFile); 
} finally { 
    IOUtils.closeQuietly(inputStream); 
} 
5

bahar önyükleme proje bir kavanoza olarak çalışan ve sınıf yolunda bazı dosyayı okumak gerekmez, ben

Resource resource = new ClassPathResource("data.sql"); 
BufferedReader reader = new BufferedReader(new InputStreamReader(resource.getInputStream())); 
reader.lines().forEach(System.out::println); 
0

Jersey paketlenmemiş kavanoz olması gerekiyor kod altına tarafından uygulanması.

<build> 
    <plugins> 
     <plugin> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-maven-plugin</artifactId> 
      <configuration> 
       <requiresUnpack> 
        <dependency> 
         <groupId>com.myapp</groupId> 
         <artifactId>rest-api</artifactId> 
        </dependency> 
       </requiresUnpack> 
      </configuration> 
     </plugin> 
    </plugins> 
</build> 
0

ben sınıfyolundan kolay okuma dosyaları yapmak için bir java 8 yolla bir ClassPathResourceReader sınıf oluşturmak ettik

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.util.stream.Collectors; 

import org.springframework.core.io.ClassPathResource; 

public final class ClassPathResourceReader { 

    private final String path; 

    private String content; 

    public ClassPathResourceReader(String path) { 
     this.path = path; 
    } 

    public String getContent() { 
     if (content == null) { 
      try { 
       ClassPathResource resource = new ClassPathResource(path); 
       BufferedReader reader = new BufferedReader(new InputStreamReader(resource.getInputStream())); 
       content = reader.lines().collect(Collectors.joining("\n")); 
       reader.close(); 
      } catch (IOException ex) { 
       throw new RuntimeException(ex); 
      } 
     } 
     return content; 
    } 
} 

Kullanımı: Benim durumumda

String content = new ClassPathResourceReader("data.sql").getContent(); 
0
to get list of data from src/main/resources/data folder -- 
first of all mention your folder location in properties file as - 
resourceLoader.file.location=data 

inside class declare your location. 

@Value("${resourceLoader.file.location}") 
    @Setter 
    private String location; 

    private final ResourceLoader resourceLoader; 

public void readallfilesfromresources() { 
     Resource[] resources; 

     try { 
      resources = ResourcePatternUtils.getResourcePatternResolver(resourceLoader).getResources("classpath:" + location + "/*.json"); 
      for (int i = 0; i < resources.length; i++) { 
       try { 
       InputStream is = resources[i].getInputStream(); 
       byte[] encoded = IOUtils.toByteArray(is); 
       String content = new String(encoded, Charset.forName("UTF-8")); 
       } 
      } 
     } catch (IOException e) { 
      throw new UncheckedIOException(e); 
     } 
} 
İlgili konular