SpringBoot 项目有一些基本的配置,比如启动图案(banner),比如默认配置文件 application.properties,以及相关的默认配置项。
示例项目代码在:https://github.com/laolunsi/spring-boot-examples
一、启动图案 banner
编写 banner.txt 放入 resources 文件夹下,然后启动项目即可修改默认图案。
关于 banner 的生成,可以去一些专门的网站。
比如:https://www.bootschool.net/ascii
二、配置文件 application
2.1 application.properties/yml
resources 下通常会默认生成一个 application.properties 文件,这个文件包含了 SpringBoot 项目的全局配置文件。里面的配置项通常是这样的:
server.port=8080
在这个文件里我们可以添加框架支持的配置项,比如项目端口号、JDBC 连接的数据源、日志级别等等。
现在比较流行的是将 properties 文件改为 yml 文件。yml 文件的格式 yaml 是这样的:
server:
port: 8080
yml 和 properties 的作用是一样的。而 yml 的好处是显而易见的——更易写易读。
属性之间互相调用使用 ${name}:
eknown:
email: eknown@163.com
uri: http://www.eknown.cn
title: 'hello, link to ${eknown.uri} or email to ${eknown.email}'
链接:SpringBoot 所有官方配置属性
2.2 多环境配置文件
通常开发一个应用会有多个环境,常见如 dev/prod,也会有 test,甚至其他一些自定义的环境,SpringBoot 支持配置文件的灵活切换。
定义新配置文件需要遵循以下格式:application-{profile}.properties
或者application-{profile}.yml
比如现在有 dev 和 prod 两个环境,我需要在 application.yml 文件之外新建两个文件:
application-dev.yml
server: port: 8080
application-prod.yml
server: port: 8081
然后在 application.yml 中通过 application.profiles.active={profile}
指明启用那个配置:
application:
profiles:
active: dev
除了在 application.yml 中指定配置文件外,还可以通过启动命令指定:java -jar xxx.jar --spring.profiles.active=dev
2.2 自定义配置项并获取它
主要介绍两种方式,获取单个配置项和获取多个配置项。
举例:
eknown:
email: eknown@163.com
uri: http://www.eknown.cn
2.2.1 使用 @Value 注解获取单个配置项
@Value("${eknown.email}")
private String email;
@Value("${eknown.uri}")
private String url;
注意:使用 @Value 注解的时候,所在类必须被 Spring 容器管理,也就是被 @Component、@Controller、@Service 等注解定义的类。
2.2.2 获取多个配置项
第一种,定义一个 bean 类,通过 @Value 获取多个配置项:
@Component
public class MyConfigBean {}
然后我们通过 get 方法来获取这些值:
@RestController
public class BasicAction {
@Autowired
private MyConfigBean myConfigBean;
}
第二种,使用注解 @ConfigurationProperties:
@Component
@ConfigurationProperties(perfix="eknown")
public class MyConfigBean {
private String email;
private String uri;
}
这里只需要通过 prefix 指定前缀即可,后面的值自动匹配。
这里我们还使用了 @Component 注解来让 spring 容器管理这个 MyConfigBean。
此外,我们可以不需要引入 @Component,转而在 Application 启动类上加上 @EnableConfigurationProperties({MyConfigBean.class})来启动这个配置。
注意:我们这里是从主配置文件,也就是 SpringBoot 默认的 application-profile 文件中获取配置数据的。
而从自定义的配置文件,比如 test.yml 这种形式中获取配置项时,情况是有点不大一样的。
三、自定义配置文件
上面介绍的配置文件都是 springboot 默认的 application 开头的文件。如果要自定义一个配置文件呢,比如 test.yml 或 test.properties,怎么获取其中的配置项呢?
使用 @PageResource 注解即可。
首先我们来看一下读取自定义的 properties 文件里的内容:
test.properties
hello.time=2019.11.19
hello.name=eknown
定义 Configuration 类:
@Configuration
@PropertySource("classpath:test.properties")
//@PropertySource("classpath:test.yml") // 注意,yml 文件不能直接这样写,会读不出数据
@ConfigurationProperties(prefix = "hello")
public class TestConfiguration {
private String name;
private String time;
// hide get and set methods
}
测试一下:
@RestController
@RequestMapping(value = "test")
public class TestAction {
@Autowired
private TestConfiguration testConfiguration;
@GetMapping(value = "config")
public String test() {return testConfiguration.getName() + "<br/>" + testConfiguration.getTime();}
}
如果将 properties 文件换成 yml 文件呢?
我们尝试一下,发现:
读不出数据?
分析一下 @PropertySource 注解,发现其使用的 PropertySourceFactory 是 DefaultPropertySourceFactory.
这个类的源码如下:
public class DefaultPropertySourceFactory implements PropertySourceFactory {public DefaultPropertySourceFactory() { }
public PropertySource<?> createPropertySource(@Nullable String name, EncodedResource resource) throws IOException {return name != null ? new ResourcePropertySource(name, resource) : new ResourcePropertySource(resource);
}
}
这个类只能处理 properties 文件,无法处理 yml 文件。所以我们需要自定义一个 YmlSourceFactory。
public class YamlSourceFactory extends DefaultPropertySourceFactory {
@Override
public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {return new YamlPropertySourceLoader().load(resource.getResource().getFilename()
, resource.getResource()).get(0);
}
}
然后定义 test.yml 文件的 config 类:
@Configuration
@PropertySource(value = "classpath:test.yml", encoding = "utf-8", factory = YamlSourceFactory.class)
@ConfigurationProperties(prefix = "yml.hello")
public class TestYamlConfiguration {
private String name;
private String time;
// hide get and set methods
}
注:为了区分 test.properties 和 test.yml,这里的 test.yml 中的属性以 yml.hello 开头。
编写一下测试:
@Autowired
private TestYamlConfiguration ymlConfiguration;
@GetMapping(value = "yml")
public String testYml() {return "yml config: <br/>" + ymlConfiguration.getName() + "<br/>" + ymlConfiguration.getTime();}
访问:
四、补充 @ConfigurationProperties
网上一些资料中,为配合使用 @ConfigurationProperties,还使用了 @EnableConfigurationProperties 注解。
经过测试发现:
- 从 SpringBoot 默认配置文件读取配置信息,使用 @ConfigurationProperties + @Component/@Configuration,或者 @ConfigurationProperties + 在启动类添加 @EnableConfigurationProperties({class})。这两种方式都能解决问题
- 从非默认配置文件读取配置信息,需要利用 @PropertySource 注解。同样两种方式:
2.1 @PropertySource + @ConfigurationProperties + @Component/@Configuration
2.2 @PropertySource + @ConfigurationProperties + @Component/@Configuration + @EnableConfigurationProperties,第二种方式存在一个问题,即还是必须要使用 @Component 注解,如果不使用,则会导致读取配置信息为 null,但程序不会报错;而如果采用了,则会导致 bean 类的 set 方法被执行两次(也就是生成了两个同样类型的 bean 类)。这种方式不建议!
交流学习
个人网站:http://www.eknown.cn
GitHub:https://github.com/laolunsi
公众号:猿生物语,” 分享技术,也感悟人生 ”,欢迎关注!