方法一(ResourceBundle)
使用资源包的方式来实现导入自定义配置,这种方式是就java原生的方式,不需要其他第三方组件。
在名称为application.xml的文件中配置配置
#自定义内容
student.name = zhangsan
student.age = 18
student.sex = Man
编写java代码读取配置
package com.chen.space;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.ResourceBundle;
public class Solution1 {
public static void main(String[] args) {
// 资源包
ResourceBundle resourceBundle = ResourceBundle.getBundle("application");
String name = resourceBundle.getString("student.name");
String age = resourceBundle.getString("student.age");
String sex = resourceBundle.getString("student.sex");
System.out.println("姓名:" + name);
System.out.println("年龄:" + age);
System.out.println("性别:" + sex);
}
}
最后输出的结果和配置文件是一一对应的
方法二(@Value)注解的方式读取配置
需要通过Spring来进行操作,通过@Value("${key}")
主键来获取配置文件中的属性值
作用
可修饰到任一变量获取,使用较灵活
优点
使用简单,且使用关联的链路较短
缺点
配置名不能被有效枚举到
每一个配置的使用都需重新定义,使用较为麻烦
项目强依赖配置的定义,配置不存在则会导致项目无法启动
使用场景
项目强依赖该配置的加载,想要从源头避免因配置缺失导致的未知问题
只想使用少数几个配置
引入相关依赖
<!-- 引入SpringBoot依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.3.4.RELEASE</version>
</dependency>
<!--单元测试-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
<version>2.3.4.RELEASE</version>
</dependency>
对应的controller类
@RestController
public class JavaTestController {
@Value("${student.name}")
String name;
@Value("${student.age}")
String age;
@Value("${student.sex}")
String sex;
@GetMapping("/showInfo")
public String showInfo(){
return "name: " + name + " age: " + age + " sex: " + sex;
}
}
这样会自动的将配置文件中的值获取并装配到对应的字段上
方法三 通过 @ConfigurationProperties + 前缀方式批量获取
作用
用于配置类的修饰或批量配置的获取
优点
使用配置只需确定 key 的前缀即能使用,有利于批量获取场景的使用
因采用前缀匹配,所以在使用新的相同前缀 key 的配置时无需改动代码
缺点
使用复杂,需定义配置类或者手动创建 bean 后引入使用
增加新的前缀相同 key 时可能会引入不稳定因素
使用场景
需要同时使用多前缀相同 key 的配置
期望增加新配置但不修改代码的 properties 注入
@Component
@ConfigurationProperties(prefix = "server", ignoreInvalidFields = true)
public class ConfigByConfigurationProperties {
private Integer port;
public Integer getPort() {
return port;
}
public ConfigByConfigurationProperties setPort(Integer port) {
this.port = port;
return this;
}
}
方法四 通过 Environment 动态获取单个配置
作用
用于动态在程序代码中获取配置,而配置 key 不需提前定义
优点
获取的配置的 key 可不提前定义,程序灵活性高
配置 key 可使用枚举统一放置与管理
缺点
使用较复杂,需继承 Environment 接口形成工具类进行获取
获取 key 对应的枚举与 key 定义分离,value 获取链路较长
使用场景
只需使用少量的配置
获取配置的 key 无提前定义,需要根据对配置的有无进行灵活使用
@Component
public class ConfigByEnvironment implements EnvironmentAware {
private static final Logger log = LoggerFactory.getLogger(ConfigByEnvironment.class);
private Environment environment;
public Optional<String> get(String configKey){
String config = environment.getProperty(configKey);
return Objects.isNull(config) ? Optional.empty() : Optional.of(config);
}
public void get(String configKey, Consumer<String> consumer){
Optional<String> config = get(configKey);
if(!config.isPresent()){
log.warn("application config, get config by key fail, key: {}", configKey);
}
config.ifPresent(consumer);
}
@Override
public void setEnvironment(@NonNull Environment environment) {
this.environment = environment;
}
}
public enum ConfigByEnvironmentKey {
SERVER_PORT("server.port", "server port");
private String key;
private String description;
ConfigByEnvironmentKey(String key, String description) {
this.key = key;
this.description = description;
}
public String getKey() {
return key;
}
public String getDescription() {
return description;
}
}
总结
获取配置方式 | 优点 | 缺点 | 使用场景 |
---|---|---|---|
通过 @Value 动态获取单个配置 | 使用简单,且使用关联的链路较短 | 1. 配置名不能被有效枚举到 2. 每一个配置的使用都需重新定义,使用较为麻烦 3. 项目强依赖配置的定义,配置不存在则会导致项目无法启动 | 1. 项目强依赖该配置的加载,想要从源头避免因配置缺失导致的未知问题 2. 只想使用少数几个配置 |
通过 @ConfigurationProperties + 前缀方式批量获取 | 1. 使用配置只需确定 key 的前缀即能使用,有利于批量获取场景的使用 2. 因采用前缀匹配,所以在使用新的相同前缀 key 的配置时无需改动代码 | 1. 使用复杂,需定义配置类或者手动创建 bean 后引入使用 2. 增加新的前缀相同 key 时可能会引入不稳定因素 | 1. 需要同时使用多前缀相同 key 的配置 2. 期望增加新配置但不修改代码的 properties 注入 |
通过 Environment 动态获取单个配置 | 1. 获取的配置的 key 可不提前定义,程序灵活性高 2. 配置 key 可使用枚举统一放置与管理 | 1. 使用较复杂,需继承 Environment 接口形成工具类进行获取 2. 获取 key 对应的枚举与 key 定义分离,value 获取链路较长 | 1. 只需使用少量的配置 2. 获取配置的 key 无提前定义,需要根据对配置的有无进行灵活使用 |
评论区