本文共 3923 字,大约阅读时间需要 13 分钟。
在开发Spring Boot项目时,遇到静态资源文件访问问题。在本项目中需要读取eventPublisherConfig.json文件,路径配置存储在文件中,并通过routingKeyMap变量引用使用。在开发阶段可以正常读取,但在打包成jar包后,无法通过文件路径获取该文件,因为jar包属于 zip archived文件系统,无法直接访问内部文件路径。
为了确保配置文件读取在项目启动时完成,可以使用Spring Boot的ApplicationRunner接口或CommandLineRunner接口。这里使用ApplicationRunner更为合适,可以在application.properties中指定启动类。
需要注意的是,打包后无法通过file://路径访问jar包内部的资源文件必须使用Spring的resource.getInputStream()方法。
在构造逻辑中,如果要保证读取静态资源是在依赖注入之后进行,可以使用Spring的生命周期方法@PostConstruct注解。在@PostConstruct注解的初始化方法中读取配置文件。
在打包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()方法。
最终实现的代码如下:
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 MaproutingKeyMap; // 注入的参数 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
这样写出来的代码片段需要引入相应的依赖,包括:
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
在开发修正后,初次运行项目,确保程序可以正确读取配置文件,而不报错。
在生产环境中,建议使用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; }}
在资源文件中使用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");// 转换为待处理的类型Mapmap = JSON.parseObject(str, new TypeReference
这样可以避免所有类路径的问题,确保在打包后的jar包中也能正常工作。
转载地址:http://tapuk.baihongyu.com/