首页 文章

运行jar时找不到类路径资源

提问于
浏览
80

在Spring Boot 1.1.5和1.1.6中都有这个问题 - 我正在使用@Value注释加载一个类路径资源,当我在STS(3.6.0,Windows)中运行应用程序时,它可以正常工作 . 但是,当我运行mvn包然后尝试运行jar时,我得到FileNotFound异常 .

资源message.txt位于src / main / resources中 . 我检查了jar并验证它在顶层包含文件“message.txt”(与application.properties相同的级别) .

这是应用程序:

@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());
        }
    }
}

例外:

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
ConfigApplicationContext@1c77b086: 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
figApplicationContext@1c77b086: 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

8 回答

  • 0

    resource.getFile()期望资源本身在文件系统上可用,即,一旦您构建了应用程序并从可执行jar运行它,它就可以工作 . 而不是使用 getFile() 来访问资源's contents, I'建议使用getInputStream()代替 . 那个'll allow you to read the resource'的内容无论它位于何处 .

  • 2

    如果您正在使用Spring框架,那么使用Spring framework's FileCopyUtilsClassPathResource 读入 String 非常简单:

    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);
    }
    
  • 29

    如果要使用文件:

    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);
    }
    
  • 2

    当spring boot项目作为jar运行并且需要在classpath中读取一些文件时,我通过下面的代码实现它

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

    我也遇到了这个限制并创建了这个库来克服这个问题:spring-boot-jar-resources它基本上允许你用Spring Boot注册一个自定义ResourceLoader,它可以根据需要透明地从JAR中提取类路径资源 .

  • 119

    我以java 8方式创建了一个ClassPathResourceReader类,以便从类路径中轻松读取文件

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

    利用:

    String content = new ClassPathResourceReader("data.sql").getContent();
    
  • 38
    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);
            }
    }
    
  • 1

    Jersey 需要打开包装 .

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

相关问题