SpringBoot教程&笔记|Demo03-配置文件 有更新!
SpringBoot
是为了简化Spring
应用的创建、运行、调试、部署等一系列问题而诞生的产物,自动装配的特性让我们可以更好的关注业务本身而不是外部的XML配置,我们只需遵循规范,引入相关的依赖就可以轻易的搭建出一个 WEB 工程
SpringBoot
虽然干掉了 XML 但未做到 零配置,它体现出了一种 约定优于配置,也称作按约定编程,是一种软件设计范式,旨在减少软件开发人员需做决定的数量,获得简单的好处,而又不失灵活性。 一般情况下默认的配置足够满足日常开发所需,但在特殊的情况下,我们往往需要用到自定义属性配置、自定义文件配置、多环境配置、外部命令引导等一系列功能。不用担心,这些 SpringBoot
都替我们考虑好了,我们只需要遵循它的规则配置即可
准备前提
本教程在Demo02基础上添加配置信息
构建项目的时候,自动创建的是application.properties
文件,我们重命名改成application.yml
为了让 Spring Boot
更好的生成配置元数据文件,我们需要添加如下依赖(该依赖可以不添加,但是在 IDEA 和 STS 中不会有属性提示,但是引入这个包会有相应提示),该依赖只会在编译时调用,所以不用担心会对生产造成影响…
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
自定义属性配置
在 application.yml
写入如下配置内容
test:
age: 22
name: testUser
其次定义 src/main/java/com/heardfate/springboot/demo/properties/MyTestProperties1.java
文件,用来映射我们在 application.yml
中的内容,这样一来我们就可以通过操作对象的方式来获得配置文件的内容了
package com.heardfate.springboot.demo.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* @since: 2018/10/21
* @author: Mr.HeardFate
*/
@Component
@ConfigurationProperties(prefix = "test")
public class MyTestProperties1 {
private int age;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "MyTestProperties1{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
}
接下来我们通过 HelloController
用来注入 MyTestProperties1
测试我们编写的代码,值得注意的是 Spring4.x
以后,推荐使用构造函数的形式注入属性…
package com.heardfate.springboot.demo.controller;
import com.heardfate.springboot.demo.properties.MyTestProperties1;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @since: 2018/10/18
* @author: Mr.HeardFate
*/
@RestController
@EnableConfigurationProperties({MyTestProperties1.class})
public class HelloController {
@Autowired
private MyTestProperties1 myTestProperties1;
@RequestMapping("/")
public String index() {
return "Greetings from Spring Boot!";
}
@RequestMapping("/pro1")
public MyTestProperties1 myProperties1() {
System.out.println("=====================MyTestProperties1=====================");
System.out.println(myTestProperties1.toString());
System.out.println("=====================MyTestProperties1=====================");
return myTestProperties1;
}
}
启动项目,打开浏览器,输入如下地址: http://localhost:8080/pro1,观察控制台,监听到如下内容则表示程序正确
=====================MyTestProperties1=====================
MyTestProperties1{age=22, name='testUser'}
=====================MyTestProperties1=====================
自定义文件配置
YML的缺点:不能通过@PropertySource注解加载! 如果需要使用@PropertySource注解的方式加载值,那就要使用properties文件!
YML的缺点:不能通过@PropertySource注解加载! 如果需要使用@PropertySource注解的方式加载值,那就要使用properties文件!
YML的缺点:不能通过@PropertySource注解加载! 如果需要使用@PropertySource注解的方式加载值,那就要使用properties文件!
定义一个名为 testProperties.properties
的资源文件,自定义配置文件的命名不强制 application
开头
com.heardfate.name=heardfate
com.heardfate.age=18
com.heardfate.email=admin@heardfate.com
其次定义 src/main/java/com/heardfate/springboot/demo/properties/MyTestProperties2.java
文件,用来映射我们在 testProperties.properties
中的内容。
package com.heardfate.springboot.demo.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
/**
* @since: 2018/10/21
* @author: Mr.HeardFate
*/
@Component
@PropertySource("classpath:testProperties.properties")
@ConfigurationProperties(prefix = "com.heardfate")
public class MyTestProperties2 {
private int age;
private String name;
private String email;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Override
public String toString() {
return "MyTestProperties2{" +
"age=" + age +
", name='" + name + '\'' +
", email='" + email + '\'' +
'}';
}
}
![自定义文件配置](https://img.heardfate.com:442/springboot/demo/01/17.jpeg)
接下来在 HelloController
用来注入 MyTestProperties2
测试我们编写的代码
@Autowired
private MyTestProperties2 myTestProperties2;
@RequestMapping("/pro2")
public MyTestProperties2 myProperties2() {
System.out.println("=====================MyTestProperties2=====================");
System.out.println(myTestProperties2.toString());
System.out.println("=====================MyTestProperties2=====================");
return myTestProperties2;
}
打开浏览器,输入如下地址: http://localhost:8080/pro2,观察控制台,监听到如下内容则表示程序正确
=====================MyTestProperties2=====================
MyTestProperties2{age=18, name='heardfate', email='admin@heardfate.com'}
=====================MyTestProperties2=====================
随机值配置
配置文件中${random} 可以用来生成各种不同类型的随机值,从而简化了代码生成的麻烦,例如 生成 int 值、long 值或者 string 字符串。
#随机值
com:
heardfate:
random:
# 随机字符串
secret: ${random.value}
# 随机int
number: ${random.int}
# 随机long
bignumber: ${random.long}
# UUID值
uuid: ${random.uuid}
# 10以内的随机数
lessThan: ${random.int(10)}
# 10-100的随机数
inRange: ${random.int[10,100]}
# 100-1000的随机数,100前面和1000后面可以是 -,(,[ 等任意字符 int.inRange: ${random.int-100,1000-}
inRange2: ${random.int(100,1000)}
其次定义 src/main/java/com/heardfate/springboot/demo/properties/MyTestRandomProperties.java
文件,用来映射我们在 application.yml
中com.heardfate.random
的内容。
package com.heardfate.springboot.demo.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* @since: 2018/10/21
* @author: Mr.HeardFate
*/
@Component
@ConfigurationProperties(prefix = "com.heardfate.random")
public class MyTestRandomProperties {
// # 随机字符串
private String secret;
// # 随机int
private int number;
// # 随机long
private long bignumber;
// # UUID值
private String uuid;
// # 10以内的随机数
private int lessThan;
// # 10-100的随机数
private int inRange;
// # 100前面和1000后面可以是 -,(,[ 等任意字符 int.inRange: ${random.int-100,1000-}
private int inRange2;
public String getSecret() {
return secret;
}
public void setSecret(String secret) {
this.secret = secret;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public long getBignumber() {
return bignumber;
}
public void setBignumber(long bignumber) {
this.bignumber = bignumber;
}
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public int getLessThan() {
return lessThan;
}
public void setLessThan(int lessThan) {
this.lessThan = lessThan;
}
public int getInRange() {
return inRange;
}
public void setInRange(int inRange) {
this.inRange = inRange;
}
public int getInRange2() {
return inRange2;
}
public void setInRange2(int inRange2) {
this.inRange2 = inRange2;
}
@Override
public String toString() {
return "MyTestRandomProperties{" +
"secret='" + secret + '\'' +
", number=" + number +
", bignumber=" + bignumber +
", uuid='" + uuid + '\'' +
", lessThan=" + lessThan +
", inRange=" + inRange +
", inRange2=" + inRange2 +
'}';
}
}
接下来在 HelloController
用来注入 myTestRandomProperties
测试我们编写的代码
@Autowired
private MyTestRandomProperties myTestRandomProperties;
@RequestMapping("/random")
public MyTestRandomProperties myTestRandomProperties() {
System.out.println("=====================MyTestRandomProperties=====================");
System.out.println(myTestRandomProperties.toString());
System.out.println("=====================MyTestRandomProperties=====================");
return myTestRandomProperties;
}
打开浏览器,输入如下地址: http://localhost:8080/random,观察控制台,监听到如下内容则表示程序正确
=====================MyTestRandomProperties=====================
MyTestRandomProperties{secret='3a1720de4c4b2ca95762fa48ccbbdd78', number=19380060, bignumber=-3053795025857769306, uuid='4e440c8c-0e9c-42c6-a445-dc2497d946bb', lessThan=7, inRange=40, inRange2=884}
=====================MyTestRandomProperties=====================
多环境化配置
在真实的应用中,常常会有多个环境(如:开发,测试,生产等),不同的环境数据库连接都不一样,这个时候就需要用到spring.profile.active
的强大功能了,它的格式为 application-{profile}.properties
,这里的 application
为前缀不能改,{profile}
是我们自己定义的。
创建 application-dev.yml
、application-test.yml
、application-prod.yml
,内容分别如下
application-dev.yml
server:
port: 8082
application-test.yml
server:
port: 8083
application-prod.yml
server:
port: 8084
在 application.yml
配置文件中写入
spring:
profiles:
active: dev
这个时候我们再次访问 http://localhost:8080/pro1 就没用了,因为我们设置了它的server: port: 8082
,所以新的端口是8082
,新的访问路径:http://localhost:8082/pro1 ,由此可以看出我们激活不同的配置读取的端口或属性值是不一样的
外部命令引导
前面三种方式都是基于配置文件层面的,那么有没有办法外部引导呢,假设这样的场景,我们对已经开发完成的代码打包发布,期间在测试环境测试通过了,那么即可发布上生产,这个时候是修改application.properties
的配置方便还是直接在命令参数配置方便呢,毫无疑问是后者更有说服力。默认情况下,SpringApplication
会将命令行选项参数(即:–property,如–server.port=9000)添加到Environment,命令行属性始终优先于其他属性源。
如何测试?
-
通过IDEA打包项目,双击package即可
-
打包完毕后进入到:
~/IdeaProjects/springboot-demo/demo01/target
目录中去,我们可以发现一个名为demo01-0.0.1-SNAPSHOT.jar
的包 - 接着在打开
命令行
程序,输入:java -jar demo01-0.0.1-SNAPSHOT.jar --spring.profiles.active=test --test.age=12
。仔细观察**spring.profiles.active=test
、test.age=12
** 这俩配置的键值是不是似曾相识(不认识的请从开头认真阅读)
- 最后输入测试地址:http://localhost:8083/pro1 我们可以发现打印的变成了
MyTestProperties1{age=12, name='testUser'}
配置文件的优先级
application.properties和application.yml文件可以放在一下四个位置:
- 外置,在相对于应用程序运行目录的/congfig子目录里。
- 外置,在应用程序运行的目录里
- 内置,在config包内
- 内置,在Classpath根目录
同样,这个列表按照优先级排序,也就是说,src/main/resources/config下application.properties覆盖src/main/resources下application.properties中相同的属性,如图:
此外,如果你在相同优先级位置同时有application.properties和application.yml,那么application.yml里面的属性就会覆盖application.properties里的属性。