使用配置文件初探
(一).最简单的配置
文件类型支持两种,yml和properties,springboot使用配置文件很简单,只需在resources目录下创建application.properties文件,编码最好选择utf-8,统一编码格式,
创建一个测试配置项
test.value=test
使用@vaule注解在程序中引用test.value的值
@Value("${test.value}")
private String testValue;
这样项目运行后,”test”就自动注入给了testValue
(二).使用Bean来管理多个配置项
如果我们的配置项有多个,springboot官方推荐使用java bean来进行管理。
再增加一个配置项
test.value1=test1
@Value("${test.value1}")
private String testValue1;
创建一个java bean 里面做配置项的注入
ConfigBean.java
package com.my.webapp.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 配置文件中的Bean管理
*/
@Component
@ConfigurationProperties(prefix = "test")
public class ConfigBean {
private String value;
private String value1;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getValue1() {
return value1;
}
public void setValue1(String value1) {
this.value1 = value1;
}
}
使用@ConfigurationProperties注解,同时可以加上前缀”test”,这样test.value,test.value1分别注入给了value和value1
在代码中使用
@Autowired
private ConfigBean configBean;
logger.info("test.value: "+configBean.getValue());
(三).创建多环境配置文件
在实际企业开发中我们的环境有多种,不可能仅仅application.properies就能满足使用,比如开发,测试,生产。不同环境下需要切换不同的配置文件,因此可以配合maven进行配置文件的切换
创建三套配置文件,并分别在三个文件设置test.value和test.value1不同的值
application-test.properties
test.value=test
test.value1=test1
application-dev.properties
test.value=dev
test.value1=dev1
application-prod.properties
test.value=prod
test.value1=prod1
再通过maven选配指定配置参数
web项目module对应pom文件下进行修改
pom.xml
<!--maven定义生效的配置
三种环境 test dev prod
激活方式 1.<activeByDefault>
2.mvn命令 -P test|dev|prod
-->
<profiles>
<profile>
<id>test</id>
<properties>
<profileActive>test</profileActive>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
</profiles>
<build>
<finalName>webapp-controller</finalName>
<!--设置资源文件-->
<resources>
<resource>
<directory>src/main/resources</directory>
<!--排除的资源文件-->
<excludes>
<exclude>application.properties</exclude>
<exclude>application-*.properties</exclude>
</excludes>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<!--包含的资源文件-->
<includes>
<include>application.properties</include>
<include>application-${profileActive}.properties</include>
</includes>
</resource>
</resources>
设置属性配置三种环境 profile的选择可以在执行maven命令时进行指定,当我们编译打包时
Mvn -f clean package -P dev -Dmaven.test.skip=true;
-P参数即可指定,当前选择的是dev。则id为dev的配置生效
如果我们不指定则默认使用指定了为true的配置。
最后我们还需要在application.properties文件中配置一项
spring.profiles.active=@profileActive@
该文件可以获取到maven中配置的的属性值,使用方式为@属性名@,springboot根据application-@profileActive@.properties加载具体的配置文件,maven中默认是test 则默认加载application-test.properties文件了。
(四).对配置文件中的指定配置项进行加密
参考链接:spring、spring-boot配置文件属性内容加解密
由于配置文件中的配置项包含很多敏感数据,比如数据库用户密码。如果我们需要对该属性进行加密,并且程序能够正常解析。
这里需要用到国外大牛写的一个java实现的安全框架:jaspyt
在pom文件中加入该依赖
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>1.14</version>
</dependency>
这样我们程序就具有了对配置文件进行加密解密的功能了,具体怎么使用请参考以上别人的链接该框架默认使用的加密算法为PBEWithMD5AndDES,我们可以自定义加密算法进行加密解密
这里使用了DES加密算法
DESUtil.java
package com.cdvcredit.common.utils;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.security.SecureRandom;
import java.util.Base64;
public class DESUtil {
public static String encrypt(String plainText, String privateKey) {
try {
KeyGenerator keygen = KeyGenerator.getInstance("DES");
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
secureRandom.setSeed(privateKey.getBytes());
keygen.init(56, secureRandom);
SecretKey secretKey = keygen.generateKey();
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] cipherBytes = cipher.doFinal(plainText.getBytes("utf-8"));
byte[] plainTextBytes = Base64.getEncoder().encode(cipherBytes);
return new String(plainTextBytes, "utf-8");
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static String decrypt(String cipherText, String privateKey) {
try {
KeyGenerator keygen = KeyGenerator.getInstance("DES");
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
secureRandom.setSeed(privateKey.getBytes());
keygen.init(56, secureRandom);
SecretKey secretKey = keygen.generateKey();
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
byte[] cipherTextBytes = Base64.getDecoder().decode(cipherText.getBytes("utf-8"));
byte[] cipherBytes = cipher.doFinal(cipherTextBytes);
return new String(cipherBytes, "utf-8");
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
接下来则是用自定义加密算法替换默认加密解密算法
jaspyt默认通过StringEncryptor进行加密解密,我们只需要覆盖该实现即可
编写一个实现StringEncryptor接口的类,覆写encrypt()和decrypt()方法
PropertiesEncryptor.java
package com.cdvcredit.api.app.component;
import com.cdvcredit.common.utils.DESUtil;
import com.cdvcredit.common.utils.FileUtil;
import org.jasypt.encryption.StringEncryptor;
import java.net.URL;
public class PropertiesEncryptor implements StringEncryptor {
private String privateKey;
private static String privateKeyFileName = "properties_key.txt";
public PropertiesEncryptor() {
super();
this.privateKey = getPrivateKeyString();
}
@Override
public String encrypt(String s) {
return DESUtil.encrypt(s, privateKey);
}
@Override
public String decrypt(String s) {
return DESUtil.decrypt(s, privateKey);
}
private String getPrivateKeyString() {
ClassLoader classLoader = getClass().getClassLoader();
URL url = classLoader.getResource(privateKeyFileName);
if (url == null) {
return null;
}
System.out.println(url.getFile());
return FileUtil.readToString(url.getFile());
}
}
在这里加解密所需要的密钥暂时是存放在一个本地文件”properties_key.txt”中,getPrivateKeyString()方法是从该文件中取出该密钥
FileUtil.java
package com.cdvcredit.common.utils;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
public class FileUtil {
public static String readToString(String pathName) {
File file = new File(pathName);
StringBuilder result = new StringBuilder();
try {
BufferedReader br = new BufferedReader(new FileReader(file));
String s = null;
while ((s = br.readLine()) != null) {
result.append(s);
}
br.close();
} catch (Exception e) {
e.printStackTrace();
return null;
}
return result.toString();
}
}
最后通过java config让spring启动加载我们覆盖后的加解密类PropertiesEncryptor
PropertiesEncryptorConfig.java
package com.cdvcredit.api.app.component;
import org.jasypt.encryption.StringEncryptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class PropertiesEncryptorConfig {
@Bean(name = "jasyptStringEncryptor")
public StringEncryptor stringEncryptor() {
return new PropertiesEncryptor();
}
}
这里需要注意jaspyt根据bean名”jasyptStringEncryptor”去查找加解密工具
对明文如何进行加密?
我们可以编写一个测试方法
@Autowired
private StringEncryptor jasyptStringEncryptor;
@Test
public void encryptTest(){
System.out.println(jasyptStringEncryptor.encrypt("dev"));
}
执行后得到KbYBe+WcTEM=
我们在配置文件中加上该属性值,格式为ENC(‘密文’),这样的格式才会被jaspyt框架识别并解密
application-dev.properties
test.value=ENC(KbYBe+WcTEM=)
test.value1=dev1
然后在代码中使用该test.value属性,即可正确解析到。
参考:
spring、spring-boot配置文件属性内容加解密