前言
张星, 之前在一线名企工作多年, 级别 P8, 是企业的核心技术开发人员, 目前有十三年的开发经验. 从事于 Java 后端开发, 对分布式架构, spring 微服务, MySQL, 框架, Netty,JVM, 性能优化, 等技术都有较深的研究 30K 的薪资, 有人说这只能是大企业或者互联网企业工程师才能拿到. 是的, 小公司或者非互联网企业 30K 的不太可能是码农了.
正文
Spring Boot 使用了一个全局的配置文件 application.properties, 放在 src/main/resources 目录下或者类路径的 / config 下. Sping Boot 的全局配置文件的作用是对一些默认配置的配置值进行修改.
接下来, 让我们一起来解开配置文件的面纱.
注: 如果你工程没有这个 application.properties, 那就在 src/main/java/resources 目录下新建一个.
自定义属性
application.properties 提供自定义属性的支持, 这样我们就可以把一些常量配置在这里:
- com.dudu.name="嘟嘟 MD"
- com.dudu.want="祝大家鸡年大吉吧"
然后直接在要使用的地方通过注解 @Value(value="${config.name}")就可以绑定到你想要的属性上面
- @RestController
- public class UserController {
- @Value("${com.dudu.name}")
- private String name;
- @Value("${com.dudu.want}")
- private String want;
- @RequestMapping("/")
- public String hexo(){
- return name+","+want;
- }
- }
我们启动工程输入 http://localhost:8080 就可以看到打印了 "嘟嘟 MD 祝大家鸡年大吉吧".
有时候属性太多了, 一个个绑定到属性字段上太累, 官方提倡绑定一个对象的 bean, 这里我们建一个 ConfigBean.java 类, 顶部需要使用注解 @ConfigurationProperties(prefix = "com.dudu")来指明使用哪个
- @ConfigurationProperties(prefix = "com.dudu")
- public class ConfigBean {
- private String name;
- private String want;
- // 省略 getter 和 setter
- }
这里配置完还需要在 spring Boot 入口类加上 @EnableConfigurationProperties 并指明要加载哪个 bean, 如果不写 ConfigBean.class, 在 bean 类那边添加
- @SpringBootApplication
- @EnableConfigurationProperties({ConfigBean.class})
- public class Chapter2Application {
- public static void main(String[] args) {
- SpringApplication.run(Chapter2Application.class, args);
- }
- }
最后在 Controller 中引入 ConfigBean 使用即可, 如下:
- @RestController
- public class UserController {
- @Autowired
- ConfigBean configBean;
- @RequestMapping("/")
- public String hexo(){
- return configBean.getName()+configBean.getWant();
- }
- }
参数间引用
在 application.properties 中的各个参数之间也可以直接引用来使用, 就像下面的设置:
- com.dudu.name="嘟嘟 MD"
- com.dudu.want="祝大家鸡年大吉吧"
com.dudu.yearhope=${com.dudu.name}在此 ${com.dudu.want}
这样我们就可以只是用 yearhope 这个属性就好
使用自定义配置文件
有时候我们不希望把所有配置都放在 application.properties 里面, 这时候我们可以另外定义一个, 这里我明取名为 test.properties, 路径跟也放在 src/main/resources 下面.
- com.md.name="哟西~"
- com.md.want="祝大家鸡年, 大吉吧"
我们新建一个 bean 类, 如下:
- @Configuration
- @ConfigurationProperties(prefix = "com.md")
- @PropertySource("classpath:test.properties")
- public class ConfigTestBean {
- private String name;
- private String want;
- // 省略 getter 和 setter
- }
这里要注意哦, 有一个问题, 如果你使用的是 1.5 以前的版本, 那么可以通过 locations 指定 properties 文件的位置, 这样:
@ConfigurationProperties(prefix = "config2",locations="classpath:test.properties")
但是 1.5 版本后就没有这个属性了, 找了半天发现添加 @Configuration 和 @PropertySource("classpath:test.properties")后才可以读取.
随机值配置
配置文件中 ${random} 可以用来生成各种不同类型的随机值, 从而简化了代码生成的麻烦, 例如 生成 int 值, long 值或者 string 字符串.
- dudu.secret=${random.value}
- dudu.number=${random.int}
- dudu.bignumber=${random.long}
- dudu.uuid=${random.uuid}
- dudu.number.less.than.ten=${random.int(10)}
- dudu.number.in.range=${random.int[1024,65536]}
外部配置 - 命令行参数配置
Spring Boot 是基于 jar 包运行的, 打成 jar 包的程序可以直接通过下面命令运行:
java -jar xx.jar
可以以下命令修改 tomcat 端口号:
java -jar xx.jar --server.port=9090
可以看出, 命令行中连续的两个减号 -- 就是对 application.properties 中的属性值进行赋值的标识.
所以 java -jar xx.jar --server.port=9090 等价于在 application.properties 中添加属性 server.port=9090.
如果你怕命令行有风险, 可以使用 SpringApplication.setAddCommandLineProperties(false)禁用它.
实际上, Spring Boot 应用程序有多种设置途径, Spring Boot 能从多重属性源获得属性, 包括如下几种:
根目录下的开发工具全局设置属性(当开发工具激活时为~/.spring-boot-devtools.properties).
测试中的 @TestPropertySource 注解.
测试中的 @SpringBootTest#properties 注解特性.
命令行参数
SPRING_APPLICATION_JSON 中的属性(环境变量或系统属性中的内联 JSON 嵌入).
ServletConfig 初始化参数.
ServletContext 初始化参数.
java:comp/env 里的 JNDI 属性
JVM 系统属性
操作系统环境变量
随机生成的带 random.* 前缀的属性(在设置其他属性时, 可以应用他们, 比如 ${random.long})
应用程序以外的 application.properties 或者 appliaction.yml 文件
打包在应用程序内的 application.properties 或者 appliaction.yml 文件
通过 @PropertySource 标注的属性源
默认属性(通过 SpringApplication.setDefaultProperties 指定).
这里列表按组优先级排序, 也就是说, 任何在高优先级属性源里设置的属性都会覆盖低优先级的相同属性, 列如我们上面提到的命令行属性就覆盖了 application.properties 的属性.
配置文件的优先级
application.properties 和 application.yml 文件可以放在以下四个位置:
外置, 在相对于应用程序运行目录的 / congfig 子目录里.
外置, 在应用程序运行的目录里
内置, 在 config 包内
内置, 在 Classpath 根目录
同样, 这个列表按照优先级排序, 也就是说, src/main/resources/config 下 application.properties 覆盖 src/main/resources 下 application.properties 中相同的属性, 如图:
此外, 如果你在相同优先级位置同时有 application.properties 和 application.yml, 那么 application.properties 里的属性里面的属性就会覆盖 application.yml.
Profile - 多环境配置
当应用程序需要部署到不同运行环境时, 一些配置细节通常会有所不同, 最简单的比如日志, 生产日志会将日志级别设置为 WARN 或更高级别, 并将日志写入日志文件, 而开发的时候需要日志级别为 DEBUG, 日志输出到控制台即可.
如果按照以前的做法, 就是每次发布的时候替换掉配置文件, 这样太麻烦了, Spring Boot 的 Profile 就给我们提供了解决方案, 命令带上参数就搞定.
这里我们来模拟一下, 只是简单的修改端口来测试
在 Spring Boot 中多环境配置文件名需要满足 application-{profile}.properties 的格式, 其中 {profile} 对应你的环境标识, 比如:
application-dev.properties: 开发环境
application-prod.properties: 生产环境
想要使用对应的环境, 只需要在 application.properties 中使用 spring.profiles.active 属性来设置, 值对应上面提到的{profile}, 这里就是指 dev,prod 这 2 个.
当然你也可以用命令行启动的时候带上参数:
java -jar xxx.jar --spring.profiles.active=dev
我给不同的环境添加不同的端口属性 server.port, 然后根据指定不同的 spring.profiles.active 来切换使用. 各位可以自己试试. 这里就不贴代码了.
除了可以用 profile 的配置文件来分区配置我们的环境变量, 在代码里, 我们还可以直接用 @Profile 注解来进行配置, 例如数据库配置, 这里我们先定义一个接口
public interface DBConnector { public void configure(); }
分别定义俩个实现类来实现它
- /**
- * 测试数据库
- */
- @Component
- @Profile("testdb")
- public class TestDBConnector implements DBConnector {
- @Override
- public void configure() {
- System.out.println("testdb");
- }
- }
- /**
- * 生产数据库
- */
- @Component
- @Profile("devdb")
- public class DevDBConnector implements DBConnector {
- @Override
- public void configure() {
- System.out.println("devdb");
- }
- }
通过在配置文件激活具体使用哪个实现类
spring.profiles.active=testdb
然后就可以这么用了
- @RestController
- @RequestMapping("/task")
- public class TaskController {
- @Autowired DBConnector connector ;
- @RequestMapping(value = {"/",""})
- public String hellTask(){
- connector.configure(); // 最终打印 testdb
- return "hello task !! myage is" + myage;
- }
- }
除了 spring.profiles.active 来激活一个或者多个 profile 之外, 还可以用 spring.profiles.include 来叠加 profile
- spring.profiles.active: testdb
- spring.profiles.include: proddb,prodmq
总结
这次对 Spring Boot 中 application.properties 配置文件做的整理总结希望对大家有所帮助, 最后贴上 Spring Boot 中常用的配置属性, 需要的时候可打开查找.
来源: http://blog.51cto.com/13941961/2170048