先说使用场景:
开发时在resource目录下新建一个 config 文件夹, 在里面存放 myconf.properties 文件, 打包后这个文件会放到与jar包同级的目录下, 如下图
关键点:自定义的文件名(当然后缀是.properties),自定义的存放路径。
主要的要求是在打包后运行过程中, 修改了配置文件中的内容需要动态获取到最新的数据, 不能进行重启重新打包之类的操作。
直接上代码:
工具类的静态方法
public static String getProperties2(String fileName, String propName) {
try {
Properties pr = new Properties();
ApplicationHome home = new ApplicationHome(PropertiesUtil.class);
String path = home.getSource().getPath();
if (path.endsWith("jar")) {
System.out.println(">>>>>>>>>> 当前是生产环境(jar包环境)");
path = home.getSource().getParentFile().getPath();
} else {
System.out.println(">>>>>>>>>> 当前是开发环境");
}
path = path + "\\" + fileName;
System.out.println(">>>>>>>>>> getProperties2 path = " + path);
FileInputStream is = new FileInputStream(path);
InputStreamReader reader = new InputStreamReader(is, StandardCharsets.UTF_8);
pr.load(reader);
return pr.getProperty(propName);
} catch (IOException e) {
e.printStackTrace();
}
return "";
}
调用的位置:
@GetMapping("/test2")
public String test2(@RequestParam String key) {
return PropertiesUtil.getProperties2("config/myconf.properties", "userName");
}
-----------------------------------------------
疑问: 网上很多教程通过如下方式去读取, 测试过发现本地IDEA运行没问题, 打包后再修改就读取不到最新的了, 是有问题? 还是我使用的方式不对。顺便把代码贴上
方法1:
public static String getProperties1(String fileName, String propName) {
Properties pr = new Properties();
InputStream in = PropertiesUtil.class.getClassLoader().getResourceAsStream(fileName);
if (in == null) {
System.out.println("未读取到配置文件!");
return "";
}
InputStreamReader reader = new InputStreamReader(in, StandardCharsets.UTF_8);
try {
pr.load(reader);
} catch (IOException e) {
e.printStackTrace();
}
return pr.getProperty(propName);
}
方法2:
public static String getProperties3(String fileName, String propName) {
Properties pr = new Properties();
ClassPathResource classPathResource = new ClassPathResource(fileName);
String path = classPathResource.getPath();
System.out.println(">>>>>>>>>> getProperties3 path = " + path);
InputStream in = null;
try {
in = classPathResource.getInputStream();
InputStreamReader reader = new InputStreamReader(in, StandardCharsets.UTF_8);
pr.load(reader);
return pr.getProperty(propName);
} catch (IOException e) {
e.printStackTrace();
}
return "";
}
上述方法1 和方法2 都不能读取到打包后再修改配置文件的内容。怀疑这两种方式是读的jar包里面的配置文件。
---------------------------------------------------------------------------------------------------------------------------
第二天凌晨, 突然刷到一个教程, 可以用Springboot的一套注解来解决这个问题。
在项目中新建一个 config.MyConfig.java 的配置类, 代码如下:
package com.hejjon.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
/**
* @author: cs
* @date: 2025-04-01 04:48:13
* @since: 1.0
*/
@Configuration
@PropertySource(value = {"classpath:config/myconf.properties", "file:./config/myconf.properties"}, ignoreResourceNotFound = true)
public class MyConfig {
@Value("${carname}")
private String carName;
public String getCarName() {
return carName;
}
public void setCarName(String carName) {
this.carName = carName;
}
}
使用这个配置项时就直接将MyConfig 这个类通过@Resource 注入到Spring容器中即可。
@RestController
@RequestMapping("/resource")
public class ResourceTestController {
@Autowired
private MyConfig myConfig;
@GetMapping("/test4")
public String test4() {
return myConfig.getCarName();
}
}
注意看 @PropertySource 注解配置了两个文件路径。也就是说在本地启动时因为不存在file路径所以会加载classpath路径下的配置文件,也就是加载resource目录下的。而当项目被打成jar包运行时,file 路径会覆盖classpath 路径的配置内容。所以这种方式在打包后也能读取到配置内容。唯一的缺点是修改了配置需要重启jar包。
cp一段总结:
对于application.properties文件:
(1)默认是读取classpath下的application.properties文件。
(2)jar包同级下的application.properties可以直接读取,启动命名不需要做调整。
(3)jar包同级下的config/application.properties,可以直接读取,启动命令不需要调整。
(4)jar包同级下的conf/application.properties,不可以直接读取,需要通过参数--spring.config.location进行指定。
对于自定义的.properties文件:
(1)默认是读取classpath下的xxx.properties文件。
(2)jar包同级下的xxx.properties不可以直接读取,需要修改代码的配置@PropertySource指定多个路径,期望最终被使用的路径放到最后,因为会覆盖之前读取的配置信息。