解决Springboot项目打成jar包后获取resources目录下的文件报错的问题

文章讲述了在将Java项目打包成jar后,资源文件无法在测试环境中正常读取的问题。作者通过断点调试发现`getResource()`方法在jar包中无法找到文件,因为`ResouceUtils.getFile()`不适用于加载Jar内的文件。解决方案是使用`ClassPathResource`或`PathMatchingResourcePatternResolver`以流的方式读取jar内的文件。

前几天在项目读取resources目录下的文件时碰到一个小坑,明明在本地是可以正常运行的,但是一发到测试环境就报错了,说找不到文件,报错信息是:class path resource [xxxx] cannot be resolved to absolute file path because it does not reside in the file system: jar:file:xxxx.jar!/BOOT-INF/classes!xxxx。

看了半天代码感觉没有问题,于是怀疑是打成项目jar包后和原项目存在差异导致的。于是我把的项目打成jar包,在本地直接调试jar,果然发现问题所在。下面我将以一个自己的测试项目api-test替代原来的公司项目来讲述一下排查过程。

一、项目代码

GetResourceTest:

public class GetResourceTest {
    public InputStream getResource1() throws IOException {
        File file = new DefaultResourceLoader().getResource("/template/qiankuan.ftl").getFile();
        return Files.newInputStream(file.toPath());
    }


    public InputStream getResource2() throws IOException {
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        Resource[] resources = resolver.getResources("/template/qiankuan.ftl");
        Resource resource = resources[0];
        return resource.getInputStream();
    }
}

TestController:

@RestController
@RequestMapping("/test")
public class TestController {
    @GetMapping(value = "/getResource")
    @ResponseBody
    public void getResource() throws IOException {
        GetResourceTest getResourceTest = new GetResourceTest();
        getResourceTest.getResource1();
    }
}

二、排查过程

1、首先使用Maven的install命令将项目打成jar包

命令执行成功后再target目录下就生成了jar包

2、在Termininal里cd到target目录下,然后执行下面的代码,9992可以替换成其他端口

java -jar -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=9992 api-test-1.0.0-SNAPSHOT.jar

执行成功如下

3、添加远程调试

依次点击菜单Run,点击Edit Configurations,点击+,点击Remote JVM Debug,端口后改成刚刚设置的9992。

4、请求接口

请求测试接口,9991是项目原来的端口

127.0.0.1:9991/test/getResource

5、请求结果

请求果然报错了,报错和之前测试环境的报错一摸一样。其实我们通过这个报错已经可以大致上看出问题了。。。

6、断点调试

在请求的入口打上断点开始断点调试

通过断点调试也可以看到这个文件地址在原来的地址/template/qiankuan.ftl 前拼接了jar:file:/D:/Project/test/fhey-test/api-test/target/api-test-1.0.0-SNAPSHOT.jar!/BOOT-INF/classes!成为了jar:file:/D:/Project/test/fhey-test/api-test/target/api-test-1.0.0-SNAPSHOT.jar!/BOOT-INF/classes!/template/qiankuan.ftl。

然后在后面一段代码中,resourceUrl.getProtocol()的返回结果是"jar"而不是"file", 被判定为不是文件然后抛出了一个FileNotFoundException异常。
 

三、解决方法

ResouceUtils.getFile()是专门用来加载非压缩和Jar包文件类型的资源,所以它根本不会去尝试加载Jar中的文件,要想加载Jar中的文件,只要用可以读取jar中文件的方式加载即可,比如 可以采用ClassPathResource这种以流的形式读取文件的方式或者PathMatchingResourcePatternResolver来读取文件。

ClassPathResource classPathResource = new ClassPathResource("/template/qiankuan.ftl" );
InputStream inputStream = classPathResource.getInputStream();

或者

ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource[] resources = resolver.getResources("/template/qiankuan.ftl");
Resource resource = resources[0];
InputStream inputStream = resource.getInputStream();
<think>嗯,用户想了解如何将Spring Boot项目JAR文件并在Windows本地运行。首先,我需要回想一下SpringBoot的打流程。根据之前的引用内容,用户可能遇到了打后没有主清单属性或者生成多个JAR问题。记得Maven和Gradle有不同的插件配置,用户可能用的是Maven,因为引用里提到了Maven的插件。第一步应该确认项目结构是否正确,比如是否有主类,并且使用了@SpringBootApplication注解。然后检查pom.xml中的打插件是否正确配置,特别是spring-boot-maven-plugin,这个插件负责生成可执行的JAR。用户可能在打时生成了.original文件,这时候需要确认是否使用了正确的插件,因为标准Maven插件生成的JAR含依赖,而Spring Boot插件生成的含依赖。接下来,用户需要在Windows环境下运行JAR,可能需要指导他们使用命令行,比如java-jar命令。同时,如果出现没有主清单属性的错误,应该检查MANIFEST.MF文件是否含Main-Class信息,这时候可能需要重新配置插件或者清理Maven缓存。 用户可能还遇到依赖问题,比如打时缺少某些依赖,这时候需要确认pom.xml中的依赖是否正确,并且资源插件版本是否兼容。例如引用3中提到需要添加maven-resources-plugin的特定版本,这可能解决资源过滤的问题。另外,用户可能在打步骤中漏掉了清理或重新打的步骤,比如需要先执行mvnclean再执行mvn package,以确保没有旧的构建文件影响。此外,运行时的环境问题,比如Java版本是否匹配,也是需要考虑的。最后,用户可能需要常见问题解决方法,比如处理依赖冲突或配置文件路径错误。这时候应该提醒他们检查日志,定位具体错误,并参考官方文档或社区解决方案。需要确保回答结构清晰,步骤明确,覆盖从配置到打再到运行的整个流程,并针对常见问题给出解决方案,帮助用户顺利完成本地运行。</think>### 如何将Spring Boot项目JAR文件并在Windows本地运行 #### 一、环境准备 1. 确保已安装以下工具: - **Java JDK 8+**(推荐JDK 11/17) - **Maven 3.6+**(或Gradle) - **IDE**(如IntelliJ IDEA或Eclipse) 2. 验证环境配置: ```bash java -version mvn -v ``` #### 二、项目配置 1. **确认主类存在** 主类需添加`@SpringBootApplication`注解,例如: ```java @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ``` 2. **配置Maven插件** 在`pom.xml`中必须含`spring-boot-maven-plugin`(否则生成不可执行的`.original`文件): ```xml <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>2.7.0</version> <!-- 与Spring Boot版本一致 --> </plugin> </plugins> </build> ``` #### 三、打与运行步骤 1. **清理并打项目** 在项目目录执行: ```bash mvn clean package ``` - 成功后会生成`target/项目名.jar`(可执行JAR)和`项目名.original`(仅项目代码)[^1] 2. **运行JAR文件** ```bash java -jar target/项目名.jar ``` - 若控制台显示`Started Application in X seconds`表示运行成功 #### 四、常见问题解决 1. **报错“没有主清单属性”** - **原因**:未正确配置`spring-boot-maven-plugin`或插件版本冲突[^2] - **解决方案**: - 检查`pom.xml`插件配置 - 清理Maven缓存:`mvn clean install -U` 2. **依赖缺失导致打失败** - **原因**:资源过滤插件未正确配置[^3] - **解决方案**:在`pom.xml`中添加: ```xml <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <version>3.3.0</version> </plugin> ``` #### 五、Windows本地运行优化 1. **后台运行** ```bash javaw -jar 项目名.jar ``` 2. **指定配置文件** ```bash java -jar 项目名.jar --spring.profiles.active=dev ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值