spring boot项目启动时读取静态资源文件,但打包jar包后获取不到路径
实现项目启动时调用某方法
实现ApplicationRunner接口、实现CommandLineRunner接口,注意搭配 @Component 注解使用
package com.pantech.cloudmessagehandler.provider;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.boot.ApplicationArguments;
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.util.Map;
/**
* @author lkh
* @date 2020/11/26 11:46
* @description 事件发布对象总入口
*/
@Component
@Slf4j
@Order(value = 1)
public class Publisher implements ApplicationRunner {
private static Map<String ,String> routingKeyMap;
@Override
public void run(ApplicationArguments args) {
try{
// 读取文件内容
ClassPathResource classPathResource = new ClassPathResource("eventPublisherConfig.json");
JSONObject json = JSON.parseObject(IOUtils.toString(new FileInputStream(classPathResource.getFile())));
//JSONObject转Map
routingKeyMap= com.alibaba.fastjson.JSON.parseObject(json.toJSONString(), new TypeReference<Map<String, String>>(){});
log.info("read eventPublisherConfig.json success!");
}catch (Exception e) {
log.error("failed to read eventPublisherConfig.json file");
}
}
}
代码中 IOUtils 工具类需要引入依赖
<!--读取配置文件-->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>1.3.2</version>
</dependency>
可以看到该两种方法是在 Application 启动后才执行的。
由于我开发项目时连接到rabbitMQ,并同时监听了多个队列,就导致 消费消息 在 读取该json文件之前,就导致我使用“routingKeyMap”这个变量值的时候为空,并且设置order值最小都无效,导致控制台报错,所以现在就希望读取静态资源json文件是先于mq连接的。
实现依赖注入完成后就读取资源文件
使用 @PostConstruct 注解,非spring提供的注解,Java自己的注解
用法:修饰一个非静态的void()方法,会在服务器加载Servlet的时候运行,并且只会被服务器执行一次。PostConstruct在构造函数之后执行,init()方法之前执行,该注解的方法在整个Bean初始化中的执行顺序:
Constructor(构造方法) -> @Autowired(依赖注入) -> @PostConstruct(注释的方法)
@Component
@Slf4j
public class Publisher {
private Map<String, String> routingKeyMap;
/**
* 类加载器时执行初始化
*/
@PostConstruct
public void init() {
this.getConfigMap();
}
/**
* 读取routingkey配置文件-eventPublisherConfig.json
*/
private void getConfigMap() {
try {
// 读取文件内容
ClassPathResource classPathResource = new ClassPathResource("eventPublisherConfig.json");
JSONObject json = JSON.parseObject(IOUtils.toString(new FileInputStream(classPathResource.getFile())));
//JSONObject转Map
routingKeyMap= com.alibaba.fastjson.JSON.parseObject(json.toJSONString(), new TypeReference<Map<String, String>>(){});
log.info("read eventPublisherConfig.json success!");
} catch (Exception e) {
log.info("failed to read eventPublisherConfig.json file"+e.getMessage());
}
}
}
打包jar包后运行报错:spring :cannot be resolved to absolute file path because it does not reside in the file system: jar
本机可以读取到静态文件,但是打包成jar包无法获取路径
原因:打包后Spring试图访问文件系统路径,但无法访问JAR中的路径。 因此必须使用 resource.getInputStream(),所以不能使用apache 工具包的IOUtils
最终代码:
package com.pantech.cloudmessagehandler.provider;
import com.alibaba.fastjson.JSON;
import com.pantech.cloud.event.publisher.EventPublisher;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
/**
* @author lkh
* @date 2020/11/26 11:46
* @description 事件发布对象总入口
*/
@Component
@Slf4j
public class Publisher {
private Map<String, String> routingKeyMap;
private final EventPublisher eventPublisher;
private final AcdmEventPublisher acdmEventPublisher;
public Publisher(EventPublisher eventPublisher, AcdmEventPublisher acdmEventPublisher) {
this.eventPublisher = eventPublisher;
this.acdmEventPublisher = acdmEventPublisher;
}
/**
* 类加载器时执行初始化
*/
@PostConstruct
public void init() {
this.getConfigMap();
}
/**
* 事件发布消息总入口
*
* @param routingKey routingKey
* @param data map参数
*/
public void publish(String routingKey, Map<String, Object> data) {
String publisherHost = routingKeyMap.get(routingKey);
if (StringUtils.isBlank(publisherHost)) {
throw new RuntimeException("未配置routingKey至eventPublisherConfig.json文件!");
}
switch (publisherHost) {
case "acdm":
acdmEventPublisher.publish(routingKey, data);
break;
case "fims":
eventPublisher.publish(routingKey, data);
break;
default:
break;
}
}
/**
* 读取routingkey配置文件-eventPublisherConfig.json
*/
private void getConfigMap() {
try {
InputStream inputStream = (new ClassPathResource("eventPublisherConfig.json")).getInputStream();
byte[] bytes;
bytes = new byte[inputStream.available()];
inputStream.read(bytes);
String str = new String(bytes);
routingKeyMap = JSON.parseObject(str, HashMap.class);
log.info("read eventPublisherConfig.json success!");
} catch (Exception e) {
log.info("failed to read eventPublisherConfig.json file"+e.getMessage());
}
}
}