Spring Boot 官方提供了两种常用的配置文件格式,分别是properties、yml格式。相比于properties来说,yml更加年轻,层级也是更加分明。
Java 中的 properties 文件是一种配置文件,主要用于表达配置信息,文件类型为 “.properties”,格式为文本文件,这种文件以 key=value 格式存储内容。
Properties 类继承自 Hashtable,是线程安全的,多个线程可以共享单个properties 对象而无需进行外部同步。
一般这个文件作为一些参数的存储,代码可以灵活一点。通俗点讲就相当于定义一个变量,在这个文件里面定义这些变量的值,在程序里面可以调用这些变量,好处就是,如果程序中的参数值需要变动,直接修改这个 “.properties” 文件就可以了,不用去修改源代码。
userinfo.name=example
userinfo.age=25
userinfo.active=true
userinfo.created-date=2023/01/06 11:20:20
userinfo.map.k1=v1
userinfo.map.k2=v2
@Data
@ToString
public class UserInfo {
private String name;
private Integer age;
private Boolean active;
private Map<String, Object> map;
private Date createdDate;
private List<String> hobbies;
}
yml 文件是 spring boot 推荐使用的配置文件格式,它相较于 properties 格式文件更强大,比如可以实现 SpEl表达式、松散绑定等。
以空格的缩进程度来控制层级关系。空格的数量并不重要,只要左边空格对齐则视为同一个层级。不能用 tab 代替空格,且大小写敏感。支持字面值、对象和数组三种数据结构,也支持复合结构。
UserInfo:
name: example
age: 25
active: true
created-date: 2023/01/06 11:40:00
map: {k1: v1, k2: v2}
hobbies:
- football
- basketball
- ping-pong ball
@Data
@ToString
public class UserInfo {
private String name;
private Integer age;
private Boolean active;
private Map<String, Object> map;
private Date createdDate;
private List<String> hobbies;
}
这个注解用于从配置文件中取值,支持复杂的数据类型,但是不支持 SPEL 表达式。
该注解中有一个属性 prefix, 用于指定获取配置的前缀,毕竟配置文件中的属性很多,也有很多重名的配置,所以必须用一个前缀来区分下。
该注解可以标注在类上也可以标注在方法上,所以它有两种获取值的方式。
这种方式用于从实体类上取值,并且赋值到对应的属性。
/**
* @Component 注入到 IOC 容器中
* @ConfigurationProperties 从配置文件中读取数据
*/
@Data
@ToString
@Component
@ConfigurationProperties(prefix = "userinfo")
public class UserInfo {
private String name;
private Integer age;
private Boolean active;
private Map<String, Object> map;
private Date createdDate;
private List<String> hobbies;
}
在 controller 中注入配置类后进行使用
@RestController
@RequestMapping("demo")
public class DemoController {
@Autowired
private UserInfo userInfo;
@GetMapping("test")
public String demoTest() {
return JSON.toJSONString(userInfo);
}
}
访问对应的 url 之后可以看到在配置文件中配置的信息已经获取到
{"active":true,"age":25,"createdDate":"2023-01-06 11:20:20","hobbies":["football","basketball","ping-pong ball"],"map":{"k1":"v1","k2":"v2"},"name":"example"}
标注在配置类上的方法上,同样是从配置文件中取值赋值到返回值的属性中
/**
* @Bean 将返回的结果注入到 IOC 容器中
* @ConfigurationProperties 从配置文件中取值
* @return
*/
@ConfigurationProperties(prefix = "userinfo")
@Bean
public UserInfo userInfo() {
return new UserInfo();
}
总结:@ConfigurationProperties 注解能够很轻松的从配置文件中取值,优点如下:
注意:@ConfigurationProperties 注解仅仅支持从 spring boot 的默认配置文件中取值,比如 application.properties, application.yml, application.yaml
@Value 这个注解应该是很熟悉了,spring 中从属性取值的注解,支持 SPEL 表达式,不支持复杂的数据类型,比如 List
@RestController
@RequestMapping("demo")
public class DemoController {
@Value("${userinfo.name}")
private String name;
@GetMapping("test")
public String demoTest() {
return JSON.toJSONString(name);
}
}
访问对应的 url 之后可以看到在配置文件中配置的信息已经获取到
"example"
该注解只能是获取到配置的某一条属性值,不能获取到整个对象的属性配置并封装类
spring boot 在启动的时候会自动加载 application.xxx 配置文件,但为了区分,有时候需要自定义一个配置文件,读取这种自定义文件,就需要配合 @propertySource 注解来获取自定义配置文件了,只需要在启动类上标注 @PropertySource 并指定自定义的配置文件即可。
// 文件名称 customConfig.properties
student.name=example
student.age=20
student.birthday=2022/01/06 15:00:00
实体类
@Data
@ToString
@Component
@ConfigurationProperties(prefix = "student")
public class Student {
private String name;
private Integer age;
private Date birthday;
}
启动类
@SpringBootApplication
@PropertySource(value = {"classpath:customConfig.properties"})
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
value 属性是一个数组,可以指定多个配置文件同时引入。
@PropertySource 默认加载 application.properties,不能加载 yml 格式的配置文件,yml 配置文件需要另外处理。
controller
@RestController
@RequestMapping("demo")
public class DemoController {
@Autowired
private Student student;
@GetMapping("test")
public String demoTest() {
return JSON.toJSONString(student);
}
}
启动后访问对应的 url 可以查看到已经能够读取到配置文件属性并对数据进行封装了,能够获取到
{"age":20,"birthday":"2022-01-06 15:00:00","name":"example"}
@PropertySource 注解有一个属性 factory,默认是 PropertySourceFactory.class,这个就说用来加载 properties 格式的配置文件,我们可以自定义一个用来加载 yml 格式的配置文件。
public class YmlConfigFactory extends DefaultPropertySourceFactory {
@Override
public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
String sourceName = name != null ? name : resource.getResource().getFilename();
if (!resource.getResource().exists()) {
return new PropertiesPropertySource(sourceName, new Properties());
} else if (sourceName.endsWith(".yml") || sourceName.endsWith(".yaml")) {
Properties propertiesFromYaml = loadYml(resource);
return new PropertiesPropertySource(sourceName, propertiesFromYaml);
} else {
return super.createPropertySource(name, resource);
}
}
private Properties loadYml(EncodedResource resource) throws IOException {
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
factory.setResources(resource.getResource());
factory.afterPropertiesSet();
return factory.getObject();
}
}
启动类
@SpringBootApplication
@PropertySource(value = {"classpath:customConfig.yml"}, factory = YmlConfigFactory.class)
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
经过测试,可以实现和 properties 自定义配置文件一样的效果。
@PropertySource 指定加载自定义配置文件,默认只能加载 properties 格式,但是可以指定 factory 属性来加载 yml 格式的配置文件。