[spring] 봄에는 항아리 내부의 파일이 보이지 않습니다.

모두

다음 MANIFEST.MF를 사용하여 jar 파일을 만들었습니다.

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

루트에는 다음과 같이 내 spring-context.xml에서 참조되는 my.config라는 파일이 있습니다.

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

항아리를 실행하면 해당 특정 파일의로드를 제외한 모든 것이 잘 보입니다.

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
  • 클래스는 항아리 내부에서로드됩니다.
  • 스프링 및 기타 종속성은 분리 된 jar에서로드됩니다.
  • 스프링 컨텍스트가로드 됨 (new ClassPathXmlApplicationContext ( “spring-context / applicationContext.xml”))
  • my.properties는 PropertyPlaceholderConfigurer ( “classpath : my.properties”)에로드됩니다.
  • .config 파일을 파일 시스템 외부에 놓고 리소스 URL을 ‘file :’로 변경하면 모든 것이 정상인 것 같습니다.

팁이 있습니까?



답변

spring-context.xml과 my.config 파일이 서로 다른 jar에 classpath*:my.config있다면?

여기에 더 많은 정보

또한 jar 파일 내부에서로드 할 때 resource.getInputStream()not 을 사용하고 있는지 확인하십시오 resource.getFile().


답변

이 질문에 대한 답변이 이미 있다는 것을 알고 있습니다. 그러나 스프링 부트를 사용하는 사람들에게는이 링크가 도움이되었습니다-https: //smarterco.de/java-load-file-classpath-spring-boot/

그러나이 resourceLoader.getResource("classpath:file.txt").getFile();문제와 sbk의 의견을 일으켰습니다.

그게 다야. java.io.File은 디렉토리 구조에서 파일 시스템의 파일을 나타냅니다. Jar는 java.io.File입니다. 그러나 해당 파일 내의 모든 것은 java.io.File의 범위를 벗어납니다. 자바에 관한 한, 압축이 풀릴 때까지 jar 파일의 클래스는 단어 문서의 단어와 다르지 않습니다.

getInputStream()대신 사용하는 이유를 이해하는 데 도움이 되었습니다. 이제 저에게 효과적입니다!

감사!


답변

spring jar 패키지 ClassPathResource(filename).getFile()에서 예외를 발생시키는 new를 사용 합니다.

파일 시스템에 상주하지 않으므로 절대 파일 경로로 해석 할 수 없습니다. jar

그러나 new ClassPathResource(filename).getInputStream()를 사용 하면이 문제가 해결됩니다. 그 이유는 jar의 구성 파일이 운영 체제의 파일 트리에 존재하지 않으므로 getInputStream().


답변

Tomcat6.x를 사용할 때 비슷한 문제가 있었고 내가 찾은 조언 중 아무것도 도움이되지 않았습니다. 결국 workTomcat의 폴더를 삭제 하고 문제가 사라졌습니다.

비논리적이지만 문서화 목적으로 …


답변

@sbk의 대답은 스프링 부트 환경 (@Value ( “$ {classpath * :})과는 별도로)에서 수행해야하는 방법입니다.하지만 내 시나리오에서는 독립 실행 형에서 실행하면 작동하지 않았습니다. 항아리 .. 내가 뭔가 잘못했을 수 있습니다.

하지만 이것은 이것을하는 또 다른 방법이 될 수 있습니다.

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


답변

동일한 이름을 가진 파일이 두 개 이상 있고 하나는 기본 Spring Boot jar에 있고 다른 하나는 main fat jar 내부의 jar에 있기 때문에 더 복잡한 문제가 발생했습니다. 내 솔루션은 동일한 이름의 모든 리소스를 가져오고 그 후에 패키지 이름으로 필터링해야하는 리소스를 가져 왔습니다. 모든 파일을 가져 오려면 :

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


답변

내 Spring 앱에서 리소스를 재귀 적으로로드하는 데 문제가 있었고 문제가 resource.getInputStream. 다음 config/myfilesjson파일 인 모든 파일을 재귀 적으로 읽는 방법을 보여주는 예 입니다.

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;
  }
}