项目地址:https://github.com/snjl/springboot.config_test.git
Spring Boot使用了一个全局的配置文件application.properties,放在src/main/resources目录下或者类路径的/config下。Sping Boot的全局配置文件的作用是对一些默认配置的配置值进行修改。
自定义属性
application.properties提供自定义属性的支持,这样我们就可以把一些常量配置在这里:1
2com.example.myproject.customer.id = 001
com.example.myproject.customer.name = jl
在类中引入可以用@Value(“${….}”)的注解形式,也可以如下引用:1
2
3
4
5
6
7
8
9
10
11
12
13package com.example.myproject.domain;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
"com.example.myproject.customer") (prefix =
public class Customer {
private String id;
private String name;
//getter,setter,toString
}
需要在springboot入口类上加上@EnableConfigurationProperties({Customer.class})注解,指明使用了配置文件的类。
1 | package com.example.myproject; |
参数间引用
在application.properties中的各个参数之间也可以直接引用来使用,就像下面的设置:1
2
3com.example.myproject.customer.id = 001
com.example.myproject.customer.name = jl
com.example.myproject.customer.title = 序号${com.example.myproject.customer.id},姓名${com.example.myproject.customer.name}
运行测试,如果出现中文乱码,则进行以下步骤:
java开发工具Idea下解决方案:
File -> Settings -> Editor -> File Encodings
将Properties Files (*.properties)下的Default encoding for properties files设置为UTF-8,将Transparent native-to-ascii conversion前的勾选上。
注意:做了上面操作后,一定要重新创建application.properties,才有效。
输出效果:1
Customer{id='001', name='jl', title='序号001,姓名jl'}
使用自定义配置文件
有时候我们不希望把所有配置都放在application.properties里面,这时候我们可以另外定义一个,这里我明取名为test.properties,路径跟也放在src/main/resources下面。1
2
3com.example.myproject.customer2.id = 0011
com.example.myproject.customer2.name = jlsdf
com.example.myproject.customer2.title = 序号${com.example.myproject.customer2.id},姓名${com.example.myproject.customer2.name}
注意,这里的自定义配置名字不能与之前相同,不然会读取不到(踩坑贼开心)。
我们新建一个bean类,如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16package com.example.myproject.domain;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
"classpath:test.properties") (value =
"com.example.myproject.customer2") (prefix =
public class Customer2 {
private String id;
private String name;
private String title;
//getter,setter,toString
}
其中使用@PropertySource(value = “classpath:test.properties”)指向了properties文件,使用@ConfigurationProperties(prefix = “com.example.myproject.customer2”)指向了前缀。
在CustomerService和CustomerController中增加函数与调用:1
2
3
4
5
6
7
8
9
10
11
12
13
14CustomerService.java
public Customer2 getCustomer2(){
return customer2;
}
CustomerController.java
"/customer") (
public String customer(ModelMap map) {
// Customer customer = customerService.getCustomer();
Customer2 customer = customerService.getCustomer2();
map.addAttribute("customer", customer);
return "index";
}
也可以在Test中进行输出测试。
注:出现错误Spring Boot Configuration Annotion Processor not found in classpath。
在pom.xml中引入:1
2
3
4
5<dependency>
<groupId> org.springframework.boot </groupId>
<artifactId> spring-boot-configuration-processor </artifactId>
<optional> true </optional>
</dependency>
重启idea,会出现Re-run Spring Boot Configuration Annotation Processor to update generated metadata,这个问题可以忽略,不影响代码执行。只是提醒用户,进行必要的重新编译。
随机值配置
配置文件中${random} 可以用来生成各种不同类型的随机值,从而简化了代码生成的麻烦,例如 生成 int 值、long 值或者 string 字符串。
range.properties写入:1
2
3
4
5
6range.secret=${random.value}
range.number=${random.int}
range.bignumber=${random.long}
range.uuid=${random.uuid}
range.number.less.than.ten=${random.int(10)}
range.number.in.range=${random.int[1024,65536]}
使用java接收,Range.java1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23package com.example.myproject.domain;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
"classpath:range.properties") (value =
"range") (prefix =
public class Range {
private String secret;
private int number;
private long bignumber;
private String uuid;
"${range.number.less.than.ten}") (
private int lessThanTen;
"${range.number.in.range}") (
private int rangeNumber;
//setter,getter,toString
}
配置相应的service和controller。
显示效果如下:
注意,不重启springboot应用,这些值不会改变。
外部配置-命令行参数配置
Spring Boot是基于jar包运行的,打成jar包的程序可以直接通过下面命令运行:1
java -jar xx.jar
可以以下命令修改tomcat端口号:1
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.yml里面的属性就会覆盖application.properties里的属性。
当应用程序需要部署到不同运行环境时,一些配置细节通常会有所不同,最简单的比如日志,生产日志会将日志级别设置为WARN或更高级别,并将日志写入日志文件,而开发的时候需要日志级别为DEBUG,日志输出到控制台即可。
如果按照以前的做法,就是每次发布的时候替换掉配置文件,这样太麻烦了,Spring Boot的Profile就给我们提供了解决方案,命令带上参数就搞定。
- application-dev.properties:开发环境
- application-prod.properties:生产环境
想要使用对应的环境,只需要在application.properties中使用spring.profiles.active属性来设置,值对应上面提到的{profile},这里就是指dev、prod这2个。
当然你也可以用命令行启动的时候带上参数:1
java -jar xxx.jar --spring.profiles.active=dev
给不同的环境添加不同的端口属性server.port,然后根据指定不同的spring.profiles.active来切换使用。
除了可以用profile的配置文件来分区配置我们的环境变量,在代码里,还可以直接用@Profile注解来进行配置,例如数据库配置,这里我们先定义一个接口:1
public interface DBConnector { public void configure(); }
定义2个类实现:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
"devDb") (
public class DevDBConnector implements DBConnector {
public void configure() {
System.out.println("devdb");
}
}
"testDb") (
public class TestDBConnector implements DBConnector {
public void configure() {
System.out.println("testdb");
}
}
在application.properties配置,激活其中一个类:1
spring.profiles.active=testDb
PS:这里一定要写对,如果写成testdb就会报错。
因为这里用的是thyemleaf模版,使用@RestController注解,应该是作为接口,所以可以用postman做测试,可以看到输出了testdb。
除了spring.profiles.active来激活一个或者多个profile之外,还可以用spring.profiles.include来叠加profile
1 | spring.profiles.active: testdb |