赞
踩
在传统的基于 Spring 搭建的应用中,我们一般会使用一个 properties 类型的文件来存放应用的相关属性配置,其中 properties 文件的内容是由一个个键值对组成的,即 key=value,然后在使用了 @Configuration 注解的配置类使用 @PropertySource 注解引入该文件,如 @PropertySource(“classpath:app.properties”)。
而在基于 SpringBoot 搭建应用时,SpringBoot 会自动在 resources 目录包含一个 application.properties 文件来作为该应用的默认属性配置文件,此文件的内容不需要使用 @PropertySource 注解引入也可以生效,如下:
SpringBoot 框架自动添加这个配置文件的目的,除了不需要应用额外指定该文件,方便进行应用配置,实现开箱即用的效果之外,更重要的一个原因是实现自动配置机制。
我们知道 SpringBoot 的自动配置机制会根据应用所引入的 starter 包来自动触发实现对应功能的 bean 对象的创建,而不需要我们在应用中额外创建。而在自动创建这些 bean 对象时,一般需要依赖一些配置信息,如引入 Redis 缓存功能时,我们需要指定所使用的 Redis 服务器的域名 host 和端口号 port。
此时我们只需要在应用的 application.properties 文件根据 SpringBoot 的配置规范进行配置即可。SpringBoot 内部对应该功能的配置类会自动识别该配置,从而完成该 bean 对象的创建,使得我们在应用中直接注入使用即可。如下为 Redis 在 application.properties 文件的相关配置:
# redis 配置
spring.redis.host=localhost
spring.redis.port=6379
在应用中,我们需要读取 application.properties 文件的属性值并赋值到对应的 Java 类(主要是使用了 @Component 注解及其相关注解的类)的属性中,从而可以在 Java 代码中使用这些属性值。对于在 application.properties 文件内配置的属性的使用,我们通常会基于以下三种方式来使用,分别为基于 @Value 注解,基于 Environment 类和基于 @ConfigurationProperties 注解与对应的属性类来使用。
基于 @Value 注解来将 application.properties 文件的某个键值对属性赋值到 Java 类的某个属性中,其中该属性对应的键需要放在 “${}” 的花括号里面,具体如下:
@Service
public class MyPropertiesService {
@Value("${my-key}")
private String myValue;
public String getMyValue() {
return myValue;
}
}
当 application.properties 文件的属性太多时,如果还是通过 @Value 来一个个引入未免过于繁琐,并且需要在 Java 类中定义太多的属性。此时我们可以根据需要,通过 Environment 类的对象实例来获取对应的属性值,其中 Environment 类是 Spring 框架内部用于存放属性数据的一个类似于 Map 的容器。
如下,我们可以直接注入 Environment 类的 bean 对象,然后调用该 bean 的 getProperty 方法来获取对应的属性值。
@Service
public class MyPropertiesService {
@Autowired
private Environment environment;
public String getMyValue2() {
return environment.getProperty("my-key");
}
}
另外一种情况是如果需要配置某个整体对象的配置信息,如数据库的连接信息,包括 URL、用户名和密码等,此时我们可以将这些信息封装到一个 Java 类中。该 Java 属性类的每个属性对应该整体下的一个属性值,这样可以增加代码可读性和以类型安全的方式来使用。
只定义 Java 属性类是不够的,我们还需要使用 @ConfigurationProperties 注解来修饰这个属性类,实现该属性类被 Spring 识别,从而在使用的地方可以直接注入使用。同时,我们还可以基于 @ConfigurationProperties 注解的 prefix 属性来配置以上配置信息的前戳,如 spring.datasource 前戳。
如下我们接着上一节关于天气查询的 starter 包来分析这种方式的使用。
定义一个使用 @ConfigurationProperties 注解的属性类来映射 application.properties 文件的内容,并且以weather.query 作为属性前戳。
@ConfigurationProperties(prefix = "weather.query")
public class WeatherProperties {
private String url;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
在配置类中使用 @EnableConfigurationProperties 注解来引入该属性类。除了在配置类中引入之外,我们也可以直接在其他类中使用 @Autowired 注解直接注入该属性类来使用对应的属性值。
@Configuration @ConditionalOnClass(WeatherTemplate.class) // 引入属性配置类 WeatherProperties @EnableConfigurationProperties(WeatherProperties.class) public class WeatherAutoConfiguration { @Autowired private WeatherProperties weatherProperties; @Bean @ConditionalOnMissingBean public WeatherTemplate weatherTemplate() { // 如果用户配置了其他API,则使用用户配置的,否则使用默认的。 WeatherTemplate weatherTemplate = weatherProperties.getUrl()==null ? new WeatherTemplate() : new WeatherTemplate(weatherProperties.getUrl()); return weatherTemplate; } }
拓展
SpringBoot 自动配置的各个功能组件的相关配置信息也是基于这种方式来实现的,具体为以功能特性来作为 application.properties 文件内的属性的前戳。以 Redis 为例:
- Redis 是使用 spring.redis 作为前戳的,如下为 SpringBoot 内部 Redis 的属性类定义:
@ConfigurationProperties(prefix = "spring.redis") public class RedisProperties { // 域名host信息 private String url; // 省略其他代码 }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
使用 @EnableConfigurationProperties 注解来引入该属性类。如下为 SpringBoot 内部 Redis 的自动配置类定义:
@Configuration @ConditionalOnClass(RedisOperations.class) // 引入属性类 @EnableConfigurationProperties(RedisProperties.class) @Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class }) public class RedisAutoConfiguration { // 省略其他代码 }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
application.properties 文件除了可以放在 resources 目录下之外,还可以放在其他几个位置,并且存在一个加载优先级的关系,即不同位置都存在一个 application.properties 文件,则以优先级高的位置的 application.properties 文件的内容为准。
如下以优先级从高到低的顺序来列举 application.properties 文件可以存放的位置:
拓展
可能有些同学会好奇,是否可以存放除了以上指定位置的其他位置?是否可以以其他名字来命名 application.properties 文件,如使用 app.properties 而不是 application.properties ?
对于第一个问题,我们可以在启动 Java 应用时通过 --spring.config.location 来指定文件位置,如下可以在 resources 目录指定子目录 myconfig 作为配置目录。
java -jar demo-0.0.1-SNAPSHOT.jar --spring.config.location=classpath:/myconfig/
- 1
对于第二个问题,我们也可以按照类似的方式,使用 --spring.config.name 来指定配置文件的文件名前戳,如 --spring.config.name=app。指定之后,SpringBoot 就会从以上四个位置查找 app.properties 文件。
除了可以通过 application.properties 文件来进行应用属性配置之外,还可以通过 application.yml 文件来进行配置,其中相同位置的 application.properties 文件优先级高于 application.yml 文件。
application.yml 文件是基于 YAML 语法来实现的,与 properties 文件使用点号进行多级定义不同的是, YAML 语法是基于梯级来定义的,这样在整体内容呈现方面更加直观。除此之外,对于列表数据,YAML 是支持按照指定顺序排序的,而 properties 是无序的。在使用方面也有着使用 application.yml 文件代替 application.properties 文件的趋势。
如下为 application.yml 文件内容的样例:
spring.redis:
host: localhost
port: 6379
my-key: my-value
我们再来总结一下本节的内容。application.properties 是基于 SpringBoot 搭建的应用的默认属性配置文件,并且默认位于 resources 目录。SpringBoot 框架通过自动提供该配置文件,除了可以方便应用的属性配置,而不需要应用额外指定之外,更主要的原因是 SpringBoot 自动配置的相关功能组件的相关参数需要在 application.properties 文件来配置,从而被 SpringBoot 内部的相关类来读取这些参数值。
在使用方面,首先对于文件内的属性值的使用,我们可以通过 @Value 注解,Environment 类以及 @ConfigurationProperties 注解与属性类来使用。对于文件的位置,我们可以在应用根目录的 config 目录、应用根目录、resources 目录的子目录 config 以及 resources 目录来存放,并且加载优先级依次降低。最后是我们可以使用 application.yml 文件来代替 application.properties 文件,application.yml 文件是基于 YAML 语法,内容呈现方面更加直观,数据结构更加丰富。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。