博客
关于我
spring boot项目启动时读取静态资源文件,但打包jar包后获取不到路径
阅读量:786 次
发布时间:2019-03-25

本文共 3988 字,大约阅读时间需要 13 分钟。

在开发Spring Boot项目时,遇到静态资源文件访问问题。在本项目中需要读取eventPublisherConfig.json文件,路径配置存储在文件中,并通过routingKeyMap变量引用使用。在开发阶段可以正常读取,但在打包成jar包后,无法通过文件路径获取该文件,因为jar包属于 zip archived文件系统,无法直接访问内部文件路径。

1. 项目启动时读取静态资源文件

为了确保配置文件读取在项目启动时完成,可以使用Spring Boot的ApplicationRunner接口或CommandLineRunner接口。这里使用ApplicationRunner更为合适,可以在application.properties中指定启动类。

需要注意的是,打包后无法通过file://路径访问jar包内部的资源文件必须使用Spring的resource.getInputStream()方法。

2. 依赖注入处理

在构造逻辑中,如果要保证读取静态资源是在依赖注入之后进行,可以使用Spring的生命周期方法@PostConstruct注解。在@PostConstruct注解的初始化方法中读取配置文件。

3. 常见问题处理

在打包jar包后运行报错: "Spring Boot: Cannot be resolved to absolute file path because it does not reside in the file system: jar"

这是因为Spring尝试通过Path.getFile()访问文件,但文件不存在于文件系统中,而在打包机构资源时,资源通常位于jar包内部。因此,在读取资源时应避免使用常见文件操作工具包,如IOUtils,而是使用Spring提供的resouce.getInputStream()方法。

4. 优化解决方案

最终实现的代码如下:

package com.pantech.cloudmessagehandler.provider;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Component;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
// @Component注解表示这是一个Spring管理的Bean
// @Order注解用于指定执行顺序
// @Slf4j注解用于日志记录
public class Publisher implements ApplicationRunner {
// 定义一个private字段来存储映射
private Map
routingKeyMap;
// 注入的参数
public Publisher() {
// 这里可以不需要额外的参数,只做无参数初始化
}
// @PostConstruct注解的作用:在Object初始化完成后,بواسطةSpring管理,执行此方法
// 会被调用一次,只能在构造函数完成之后,初始化方法之前
// 通过@Order注解,指定执行顺序为1,表示较早执行
@Order(1)
public void run(ApplicationArguments args) throws IOException {
// 读取静态资源文件
ClassPathResource resource = new ClassPathResource("eventPublisherConfig.json");
try (FileInputStream fis = new FileInputStream(resource.getFile())) {
// 读取文件内容
byte[] content = new byte[resource.getInputStream().available()];
resource.getInputStream().read(content);
// 转换为JSON对象
JSONObject json = JSON.parseObject(new String(content));
// 将JSON对象转换为通用的Map类型
routingKeyMap = JSON.parseObject(json.toString(), new TypeReference
>() {}.getType());
// 打印日志
log.info("成功读取配置文件eventPublisherConfig.json, 内容:{}", json);
} catch (IOException e) {
log.error("读取配置文件失败,原因是: {}", e.getMessage());
throw e;
}
}
}

5. 打包后运行配置

这样写出来的代码片段需要引入相应的依赖,包括:

com.alibaba.fastjson
fastjson
1.2.16

以及

org.springframework.boot
spring-boot-dependencies
2.3.1

此外,确保你的项目构建时,加入下列插件以支持资源处理:

org.apache.maven.plugins
maven-source-plugin
3.2.1
attach-sources
jar-with-dependencies

6. 测试验证

在开发修正后,初次运行项目,确保程序可以正确读取配置文件,而不报错。

在生产环境中,建议使用docker镜像技术,时刻获取最终版本的jar包,并使用相应的Enum类或配置管理工具进行版本管理,比如:

public enum EnvironmentConfig {
DEV("localhost:8080"),
PROD("prod-internal.pantech.com:9999");
private final String endpoint;
EnvironmentConfig(String ep) {
endpoint = ep;
}
public String getEndpoint() {
return endpoint;
}
}

7. 处理文件资源

在资源文件中使用resource.getInputStream()访问更安全可靠:

// 获取资源流
Resource resource = new ClassPathResource("配置文件名.conf");
InputStream inputStream = resource.getInputStream();
// 读取内容
byte[] content = new byte[100];
inputStream.read(content);
String str = new String(content, "UTF-8");
// 转换为待处理的类型
Map
map = JSON.parseObject(str, new TypeReference
>() {}.getType());
// 注入成员变量
成员变量 = map;

这样可以避免所有类路径的问题,确保在打包后的jar包中也能正常工作。

转载地址:http://tapuk.baihongyu.com/

你可能感兴趣的文章
NN&DL4.3 Getting your matrix dimensions right
查看>>
NN&DL4.7 Parameters vs Hyperparameters
查看>>
NN&DL4.8 What does this have to do with the brain?
查看>>
nnU-Net 终极指南
查看>>
No 'Access-Control-Allow-Origin' header is present on the requested resource.
查看>>
NO 157 去掉禅道访问地址中的zentao
查看>>
no available service ‘default‘ found, please make sure registry config corre seata
查看>>
No compiler is provided in this environment. Perhaps you are running on a JRE rather than a JDK?
查看>>
no connection could be made because the target machine actively refused it.问题解决
查看>>
No Datastore Session bound to thread, and configuration does not allow creation of non-transactional
查看>>
No fallbackFactory instance of type class com.ruoyi---SpringCloud Alibaba_若依微服务框架改造---工作笔记005
查看>>
No Feign Client for loadBalancing defined. Did you forget to include spring-cloud-starter-loadbalanc
查看>>
No mapping found for HTTP request with URI [/...] in DispatcherServlet with name ...的解决方法
查看>>
No mapping found for HTTP request with URI [/logout.do] in DispatcherServlet with name 'springmvc'
查看>>
No module named 'crispy_forms'等使用pycharm开发
查看>>
No module named cv2
查看>>
No module named tensorboard.main在安装tensorboardX的时候遇到的问题
查看>>
No module named ‘MySQLdb‘错误解决No module named ‘MySQLdb‘错误解决
查看>>
No new migrations found. Your system is up-to-date.
查看>>
No qualifying bean of type XXX found for dependency XXX.
查看>>