Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/spring-boot/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 作为jar运行时未找到类路径资源_Java_Spring Boot - Fatal编程技术网

Java 作为jar运行时未找到类路径资源

Java 作为jar运行时未找到类路径资源,java,spring-boot,Java,Spring Boot,在Spring Boot 1.1.5和1.1.6中都存在这个问题-我正在使用@Value注释加载一个类路径资源,当我从STS(3.6.0,Windows)中运行应用程序时,它工作得很好。但是,当我运行一个mvn包,然后尝试运行jar时,会出现FileNotFound异常 资源message.txt位于src/main/resources中。我已经检查了jar,并验证它在顶层(与application.properties相同的级别)包含文件“message.txt” 以下是应用程序: @配置 @

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

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

以下是应用程序:

@配置
@组件扫描
@启用自动配置
公共类应用程序实现CommandLineRunner{
私有静态最终记录器=Logger.getLogger(Application.class);
@值(“${message.file}”)
私有资源;
公共静态void main(字符串[]args){
SpringApplication.run(Application.class,args);
}
@凌驾
公共无效运行(字符串…arg0)引发异常{
//当从STS作为Spring boot应用程序运行时,这两种方法都可以工作,但是
//mvn包后失败,然后作为java-jar运行
testResource(新类路径资源(“message.txt”);
testResource(this.messageResource);
}
私有void testResource(资源){
试一试{
resource.getFile();
debug(“找到资源”+resource.getFilename());
}捕获(IOEX异常){
logger.error(例如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

期望资源本身在文件系统上可用,即不能嵌套在jar文件中。这就是为什么在STS中运行应用程序时它可以工作,但在构建应用程序并从可执行jar运行应用程序后就不工作了。与其使用
getFile()
来访问资源的内容,我建议使用。这将允许您读取资源的内容,而不管它位于何处。

如果要使用文件:

ClassPathResource ClassPathResource=newclassPathResource(“static/something.txt”);
InputStream InputStream=classPathResource.getInputStream();
File somethingFile=File.createTempFile(“test”,“.txt”);
试一试{
copyInputStreamToFile(inputStream,somethingFile);
}最后{
IOUtils.close安静(inputStream);
}

如果您使用的是Spring框架,那么将
ClassPathResource
读入
字符串
非常简单:

字符串数据=”;
ClassPathResource cpr=新的ClassPathResource(“static/file.txt”);
试一试{
byte[]bdata=FileCopyUtils.copyToByteArray(cpr.getInputStream());
数据=新字符串(bdata,StandardCharsets.UTF_8);
}捕获(IOE异常){
日志警告(“IOException”,e);
}

我也遇到了这个限制,创建了这个库来克服这个问题:
它基本上允许您向Spring Boot注册一个定制的ResourceLoader,它可以根据需要透明地从JAR中提取类路径资源。

当Spring Boot项目作为JAR运行并且需要读取类路径中的一些文件时,我通过以下代码实现它

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

球衣需要拆开包装

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

org.springframework.boot
springbootmaven插件
com.myapp
RESTAPI

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

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();
从src/main/resources/data文件夹获取数据列表--
首先,在属性文件中提到您的文件夹位置为-
resourceLoader.file.location=数据
在类内声明您的位置。
@值(${resourceLoader.file.location}”)
@塞特
私有字符串位置;
私有最终资源加载器资源加载器;
public void readallfilesfromresources(){
资源[]资源;
试一试{
resources=ResourcePatternUtils.getResourcePatternResolver(resourceLoader.getResources(“类路径:“+location+”/*.json”);
for(int i=0;i
基于Andy的,我使用以下方法来获取参考资料中目录和子目录下所有YAML的输入流(请注意,传递的路径不是以
/
开头):

私有静态流getInputStreamsFromClasspath(
字符串路径,
路径匹配源模式解析程序解析程序
) {
试一试{
返回Arrays.stream(resolver.getResources(“/”+path+“/***.yaml”))
.filter(资源::存在)
.map(资源->{
试一试{
返回resource.getInputStream();
}捕获(IOE异常){
返回null;
}
})
.filter(对象::非空);
}捕获(IOE异常){
错误(“未能从目录{}获取定义”,路径e);
返回流。of();
}
}

关于最初的错误消息

无法解析为绝对文件路径,因为它不位于 文件系统

以下代码可能有助于找到路径问题的解决方案:

Paths.get("message.txt").toAbsolutePath().toString();

这样,您就可以确定应用程序希望丢失文件的位置。您可以在应用程序的主方法中执行此操作。

我注意到的另一个重要问题是,在运行应用程序时,它会忽略文件/文件夹中的大写字母
in spring boot :

1) if your file is ouside jar you can use :        

@Autowired
private ResourceLoader resourceLoader;

**.resource(resourceLoader.getResource("file:/path_to_your_file"))**

2) if your file is inside resources of jar you can `enter code here`use :

**.resource(new ClassPathResource("file_name"))**
Paths.get("message.txt").toAbsolutePath().toString();
@Autowired
ApplicationContext appContext;

// this will work when running the application, but will fail when running as jar
appContext.getResource("classpath:testfolder/message.txt");
appContext.getResource("classpath:Testfolder/message.txt");