1.简介
在使用SpringBoot的时候肯定听说过SpringBoot可以做到零配置,其实创建SpringBoot确实可以做到零配置,它在内部其实帮你默认配置基础的参数,但是它确实配置方便,所以集成的配置参数都可以在SpringBoot提供的配置文件中自己设置,除了在SpringBoot提供的配置文件中配置以为还可以做到使用java文件的方式去注册bean,这就可以做到了SpringBoot的简化配置,不需要集成第三方功能的时候去单独写xml的bean。
SpringBoot之所以能简化开发,其配置文件起到了很重要的作用,常见的有:
- 核心配置文件分为:
- application.properties文件
- application.yml文件
- 命令行参数
- OS环境变量
- Dev属性
2.properties文件
(1)语法
格式:key-value
演示:
server.port=8080
logging.level.root=error
(2)优先级
默认的配置文件加载优先级顺序是:
- file:./config/(项目部署包所在目录的同级config目录下的application-[profile].[properties,yml]文件)
- file:./config/*/(项目部署包所在目录的同级config目录下的任意子目录中的application-[profile].[properties,yml]文件)
- file:./(项目部署包所在目录的application-[profile].[properties,yml]文件)
- classpath:/config/(项目部署包内类路径下的config目录下的application-[profile].[properties,yml]文件)
- classpath:/(项目部署包内类路径下的application-[profile].[properties,yml]文件)
在项目中的resources目录下添加的配置文件的加载优先级是最低的(打包后相当于第5条)。可以通过spring.config.location属性覆盖上面的顺序,如spring.config.location=classpath:/,classpath:/config/,一般不建议改变默认的配置顺序,除非有特殊的使用场景。
优先级图如下:
也可以通过spring.config.additional-location属性指定额外附加的搜索配置文件的路径,并且优先级比默认的配置顺序要高,假如只配置了spring.config.additional-location=classpath:/root-config/,file:./root-config/。
那么配置文件加载优先级顺序就会变成如下:
- file:./root-config/(项目部署包所在目录的同级custom-config目录下的application-[profile].[properties,yml]文件)
- classpath:root-config/(项目部署包内类路径下的custom-config目录下的application-[profile].[properties,yml]文件)
- file:./config/(项目部署包所在目录的同级config目录下的application-[profile].[properties,yml]文件)
- file:./config/*/(项目部署包所在目录的同级config目录下的任意子目录中的application-[profile].[properties,yml]文件)
- file:./(项目部署包所在目录的application-[profile].[properties,yaml]文件)
- classpath:/config/(项目部署包内类路径下的config目录下的application-[profile].[properties,yml]文件)
- classpath:/(项目部署包内类路径下的application-[profile].[properties,yml]文件)
按照这个优先级,SpringBoot启动的时候会扫描这些包,然后将配置植入Spring环境中,如果遇到相同的配置,优先级高的会覆盖优先级低的配置,比如说你有四个文件,四个文件里面都配置了项目启动端口,那么这个端口的配置只会用优先级最高的那个文件的配置。遇到不同的配置,这些配置就会互补,形成最大化的配置。
(3)配置属性
(1)默认配置属性
在配置文件中可以修改默认配置属性的参数。使用IDEA开发工具,其内置插件可自动提示并识别《默认属性列表》,免除查阅资料的烦恼。
示例如下:
spring.datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
(2)自定义配置属性
在配置文件中除了能修改原本默认的属性,还能自定义属性。
可以把一些常量加入到配置文件中,示例如下:
##id
paypal.selectId=22222
##手续费
paypal.money=12
(4)获取配置属性
(1)@ConfigurationProperties注解
使用@ConfigurationProperties注解,需要加入以下依赖,不然会提示错误。
<!-- 配置文件自动映射 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
只需要指定@ConfigurationProperties即可,他就会加载我们properties、yml配置前置为paypal的属性,示例如下:
package com.example.bean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "paypal")
public class Paypal {
private int selectId;
private int money;
public int getSelectId() {
return selectId;
}
public void setSelectId(int selectId) {
this.selectId = selectId;
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
}
(2)@Value注解
使用@Value注解来获取属性使用方式示例如下:
@Component
public class Paypal {
@Value("${paypal.selectId}")
private int selectId;
@Value("${paypal.money}")
private int money;
public int getSelectId() {
return selectId;
}
public void setSelectId(int selectId) {
this.selectId = selectId;
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
}
这种方式需要我们对实体类的每个属性一一对应,比较麻烦。当只需要为某个值提供注入时,推荐使用@Value方式。当需要对整个对象的整体进行赋值时,使用@ConfigurationProperties。
(3)加载外部配置文件
将所有的配置信息都写在application-[profile].[properties,yaml]文件中,文件会变得非常庞大,不太方便进行维护。可以对配置中的内容进行拆分,拆分到多个文件中。这样就提高了配置的可维护性。
引入外部配置文件的方式有如下几种:
- @PropertySource(value={"classpath:student.properties"}):需要注入的类的前面使用该注解。
- @ImportResource(locations={"classpath:spring.xml"}):首先添加一个spring的配置文件,在里面添加需要映射的类。在启动的SpringBootApplication前面使用该注解。
- @Configuration和@Bean方式(SpringBoot推荐方式):添加一个自定义配置类。
3.yml文件
(1)语法
YML是JSON的一个超集,是一种可轻松定义层次结构的数据格式。
格式:key空格:空格value
演示:
server:
port: 8080
利用缩进代表层级关系,只要是缩进一样就代表是一级的。
(2)优先级
既有yaml文件也有properties文件的时候(其实还有一种yml,和yaml差不多的),yml加载顺序是先于properties的,所以优先级是properties大于yaml,然后其他的情况下的优先级和properties文件是一样的。
(3)配置属性
yaml文件配置属性和properties文件差不多。写法上稍微有点差异,但是它的功能相对来说比较强大,代码简洁,可读性高。
示例如下:
#对象 paypal: selectId: 22222 money: 12 #对象集合 users: - name: 大李 age: 100 - name: 小刘 age: 200 #map集合 maps: {k1: v1,k2: 12}
(4)获取配置属性
获取配置属性的方式和properties文件一样。
4.多环境配置
在项目的实际开发中,我们一般都会有多个应用环境,开发环境、测试环境、生产环境,各个环境的配置会略有不同,我可以根据这个创建多份配置文件,由主配置文件来控制读取那个子配置。
分别创建三个应用环境的配置和一个主配置
在application.yml文件中加入指定使用哪个文件的标识
#指定运行环境
spring:
profiles:
active: dev
完成配置后,当我们需要发布到生成环境的时候,只要将spring.profiles.active的值修改为release,就可以了,避免了上线时用错配置的问题。当然还可以结合maven在打包的时候动态指定spring.profiles.active的值。
5.使用jasypt进行配置项加密
(1)使用默认加密规则
SpringBoot配置文件中的内容通常情况下是明文显示,安全性比较低。在application.properties、application.yml,比如mysql登陆密码,redis登陆密码以及第三方的密钥等等一览无余,我们可以使用springBoot下的jasypt工具包,提高一些属性配置的安全性。
需要加入maven依赖如下:
<dependency> <groupId>com.github.ulisesbocchio</groupId> <artifactId>jasypt-spring-boot-starter</artifactId> <version>2.1.0</version> </dependency>
查看版本可以到:https://github.com/ulisesbocchio/jasypt-spring-boot
在测试用例中生成加密后的数据,示例如下:
public class Encryptor { private static String key = "EbfYkitulv73I2p0mXI50JMXoaxZTKJ0";//salt(盐)值 public static void main(String[] args) { BasicTextEncryptor textEncryptor = new BasicTextEncryptor(); textEncryptor.setPassword(key); String url = textEncryptor.encrypt("jdbc:mysql://192.168.3.35:3306/test?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true"); String name = textEncryptor.encrypt("root"); String password = textEncryptor.encrypt("123456"); String password2 = textEncryptor.encrypt("123456"); //加密内容 System.out.println(url); System.out.println(name); System.out.println(password); System.out.println(password2); //解密内容 System.out.println(textEncryptor.decrypt(url)); System.out.println(textEncryptor.decrypt(name)); System.out.println(textEncryptor.decrypt(password)); System.out.println(textEncryptor.decrypt(password2)); } }
注意:同一个字符串加密多次结果可能会不相同,但是解密出来的数据都是一样的。
将配置文件中的原始明文密码替换成上一步对应的结果即可并且加上salt(盐)值,示例如下:
jasypt: encryptor: password: EbfYkitulv73I2p0mXI50JMXoaxZTKJ0 spring: datasource: url: ENC(SSvZWg68LxOSKrlA0L9wB7j+8Svoi6njtC0EyRfRGWvJiKF/YN0fbsVVEO/pzSU/6QHilTj4ihtv0RtNrpJyJA8/sKzkSdJxXsXOLmbPo28lNxXH8ruWH5lktaqMFZy8iYoEknD99D0=) username: ENC(+pZ4I69kNPcOxriKSSY8IQ==) password: ENC(n+MnagXDXVErm7oXubE/hA==)
测试获取数据示例如下:
@SpringBootTest public class Test { @Value("${spring.datasource.password}") private String password; @Test public void get() { System.out.println("连接数据库密码:" + password); } }
jasypt默认提供的ENC来标记加密字段,完全可以换成自定义的前后缀标记,比如我想换成CodePassword()来标记加密字段,此时只需要在配置文件里配置一下前后缀即可:
jasypt:
encryptor:
password: EbfYkitulv73I2p0mXI50JMXoaxZTKJ0
property:
prefix: CodePassword(
suffix: )
上文中的加密,涉及信息安全的配置项肯定会变得更安全,这个毋庸置疑!但是配置文件里的自定义加密密钥jasypt.encryptor.password=EbfYkitulv73I2p0mXI50JMXoaxZTKJ0泄露了,那么加密字段也还是有可能被别人解密,为此,不建议这种方式。
(1)使用自定义加密规则
没找到相关资料,后续在补上。
(2)读取外部配置文件
在磁盘中创建一个jasypt.properties文件,例如本地位置:D:/Desktop/jasypt.properties,文件内容如下
##jasypt的salt(盐)值
jasypt.encryptor.password=EbfYkitulv73I2p0mXI50JMXoaxZTKJ0
新建一个Java类LocalSettingsEnvironmentPostProcessor
/**读取本地配置文件jasypt加密salt值 */ public class LocalSettingsEnvironmentPostProcessor implements EnvironmentPostProcessor { /** * 第一个配置文件路径为部署环境路径,用于部署环境加载配置文件里的值(Linux服务器) * 第二个配置文件路径为本地打包环境路径,解决打包时报错问题(本地路径) * 这样配置的目的就是可以在不更改的情况下直接在本地和服务器上去运行 */ private static final String LOCATIONS [] = {"d:/Desktop/jasypt.properties","d:/Desktop/jasypt.properties"}; @Override public void postProcessEnvironment(ConfigurableEnvironment configurableEnvironment, SpringApplication springApplication) { for(String fileLocation : LOCATIONS){ File file = new File(fileLocation); if (file.exists()) { MutablePropertySources propertySources = configurableEnvironment.getPropertySources(); Properties properties = loadProperties(file); propertySources.addFirst(new PropertiesPropertySource("Config", properties)); return ; } } } private Properties loadProperties(File f) { FileSystemResource resource = new FileSystemResource(f); try { return PropertiesLoaderUtils.loadProperties(resource); } catch (IOException ex) { throw new IllegalStateException("Failed to load local settings from " + f.getAbsolutePath(), ex); } } }
在resources文件夹下创建一个META-INF文件夹,在里面创建一个spring.factories的文件,文件内容如下:
##注意后面的类的位置不要写错了
org.springframework.boot.env.EnvironmentPostProcessor=com.example.method.LocalSettingsEnvironmentPostProcessor
这个文件的作用就是设置SpringBoot服务启动的时候调用我们刚才写的那个Java类。至此,你的war包在使用tomcat启动的时候就应该可以读取制定位置的外部文件了。测试过在本地启动和放到服务器上启动均正常。
(3)设置系统环境变量
在系统环境变量中新增环境变量,过程:右键我的电脑->属性->高级系统设置->环境变量->新建系统变量名jasypt_password,值EbfYkitulv73I2p0mXI50JMXoaxZTKJ0
修改配置文件,内容如下:
jasypt:
encryptor:
password: ${jasypt_password}
注意:需要重启电脑环境变量才能生效。