我们通常会将一些配置,比如数据库连接信息,ftp连接信息等一些配置信息存储在 properties中,那么我们如何通过代码获得这些配置呢?
获取项目内 properties 配置内容
普通获取单个properties
properties 路径位置:
使用 classLoader
public static void main(String[] args) throws IOException {
// 1、初始化一个 properties ,注意导包是 util
Properties properties = new Properties();
// 2、读取 对应properties 中的数据,注意这里的地址是直接在resources下,
// 如果再resources下的目录中,那么下面的 路径前也要加上该目录
properties.load(PropertiesLoader.class.getClassLoader().getResourceAsStream("datasource.dev.properties"));
// 3、获取对应数据
String ftp_url = properties.getProperty("ftp_url");
String ftp_name = properties.getProperty("ftp_name");
String ftp_password = properties.getProperty("ftp_password");
System.out.println("ftp_url:"+ftp_url);
System.out.println("ftp_name:"+ftp_name);
System.out.println("ftp_password:"+ftp_password);
}
console ---》
简单的获取单个 properties 的数据上述方法是完全可行的
那么假如我们现在 在 resources/ds/ 目录下 有多个配置文件,
针对不同的业务场景,使用不同的配置
该如何呢,比如在 UAT 环境在使用一套数据库配置,在 准生产环境下使用一套配置, 在 生产环境又使用另外一套配置该如何呢。
properties 路径 ( enable
首先引入依赖,使用 google 帮我们封装好的工具
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>19.0-rc1</version>
</dependency>
@Test
public void getProperties() throws IOException {
// 0、定义一个文件夹名,需要loader的文件夹名
String path = "ds";
List<String> fileNames = new ArrayList<>();
// 1、 获得 classLoader
ClassLoader classLoader = PropertiesLoader.class.getClassLoader();
// 2、 获取 classpath 下的所有文件 ,注意导包是google的
ImmutableSet<ResourceInfo> resources = ClassPath.from(classLoader).getResources();
// 3、遍历 截取出我们需要的 ds 文件下的配置文件
for (ResourceInfo info : resources) {
if (info.getResourceName().startsWith(path)) {
fileNames.add(info.getResourceName());
}
}
Properties activeProperties = null;
// 4、遍历 ds 文件夹下的配置文件,找到 enable 为true 的配置文件
for (String fileName : fileNames) {
if (fileName.endsWith(".properties")) {
// 获得数据流
InputStream stream = getClass().getClassLoader().getResourceAsStream(fileName);
// 将数据流封装到 properties 对象中
Properties properties = new Properties();
properties.load(stream);
String enable = properties.getProperty("enable");
if (enable.equalsIgnoreCase("true")) {
activeProperties = properties;
}
}
}
if (activeProperties == null) {
throw new IllegalArgumentException("No active datasource config found");
}
// 5、获取对应数据
String ftp_url = activeProperties.getProperty("ftp_url");
String ftp_name = activeProperties.getProperty("ftp_name");
String ftp_password = activeProperties.getProperty("ftp_password");
System.out.println("ftp_url:" + ftp_url);
System.out.println("ftp_name:" + ftp_name);
System.out.println("ftp_password:" + ftp_password);
}
console--->
这样我们还是不满足,不想把指定数据源 enable 写死在程序中,
想通过 jvm 启动参数来指定使用哪个数据源
properties 还是跟上述一样
三个针对不同业务场景的配置的名字都不一样,那么我们只需要在启动项目的时候,指定一下 jvm 参数,比如我在 用户测试环境下,想使用 uat 的配置
首先指定 jvm 参数 ,在 idea 中直接加上
-Dsell.activeDataSource=prod
代码如下
package com.cdsn.sell.conf;
import com.google.common.collect.ImmutableSet;
import com.google.common.reflect.ClassPath;
import com.google.common.reflect.ClassPath.ResourceInfo;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
/**
* 加载ftp配置项
*
* @author ch
* @version 1.0.0
* @since 1.0.0
*
* Created at 2019-09-07 09:07
*/
@Component
public class ConnectionProducer {
@Bean
public void connect() throws IOException {
Properties properties = getProperties();
// 获取对应数据
String ftp_url = properties.getProperty("ftp_url");
String ftp_name = properties.getProperty("ftp_name");
String ftp_password = properties.getProperty("ftp_password");
System.out.println("ftp_url:" + ftp_url);
System.out.println("ftp_name:" + ftp_name);
System.out.println("ftp_password:" + ftp_password);
}
public Properties getProperties() throws IOException {
// 0、获取 jvm 参数
String active = System.getProperty("sell.activeDataSource");
// 1、获取所有对应目录下的配置文件
List<String> files = getResourceFiles("ds");
Properties activeProperties = null;
// 2、遍历 ds 文件夹下的配置文件
for (String fileName : files) {
// 3、如果有jvm参数指定了配置文件名,就使用指定的
// 如果没有jvm参数,则找到 enable 为true 的配置文件
if (fileName.endsWith(active == null ? ".properties" : active + ".properties")) {
// 获得数据流
InputStream stream = getClass().getClassLoader().getResourceAsStream(fileName);
// 将数据流封装到 properties 对象中
Properties properties = new Properties();
properties.load(stream);
// 如果 active 不存在,那么 找到 enable 为true的配置文件
if (active == null || active.equalsIgnoreCase("")) {
String enable = properties.getProperty("enable");
if (enable.equalsIgnoreCase("true")) {
activeProperties = properties;
}
} else {
// 存在 jvm 参数指定的文件
activeProperties = properties;
}
}
}
if (activeProperties == null) {
throw new IllegalArgumentException("No active datasource config found");
}
return activeProperties;
}
public List<String> getResourceFiles(String path) throws IOException {
List<String> fileNames = new ArrayList<>();
// 1、 获得 classLoader
ClassLoader classLoader = ConnectionProducer.class.getClassLoader();
// 2、 获取 classpath 下的所有文件 ,注意导包是google的
ImmutableSet<ResourceInfo> resources = ClassPath.from(classLoader).getResources();
// 3、判断当前是否在jar中运行,如果是的话,springboot 会自己在外面有 BOOT-INF 目录
URL url = ConnectionProducer.class.getResource("");
String protocol = url.getProtocol();
if ("jar".equals(protocol)) {
// jar
path = "BOOT-INF/classes/" + path;
}
// 4、遍历 截取出我们需要的 ds 文件下的配置文件
for (ResourceInfo info : resources) {
if (info.getResourceName().startsWith(path)) {
fileNames.add(info.getResourceName());
}
}
return fileNames;
}
}
测试结果如下
不加 jvm 参数,寻找 enable 为 true 的配置文件
加上 jvm 参数,寻找 jvm 参数对应的配置文件
=================================================
使用 java -jar 命令的时候 添加 jvm 参数
java -Dsell.activeDataSource=prod -jar sell-0.0.1-SNAPSHOT.jar
获取项目外部的 properties 配置内容
首先我们需要定义一个 jvm 参数,这里设置为 sell.externalDataSource
然后在代码外部写一个 配置文件,我这里在桌面新建了一个 external.properties
java 代码如下:
@Before
public void setUp() throws IOException {
// 设置 jvm 参数
Properties p = new Properties();
// 这里为 外部配置文件 全路径
p.setProperty("sell.externalDataSource", "/Users/chenhao/Desktop/external.properties");
System.setProperties(p);
}
@Test
public void loadExternalDataSource() throws IOException {
// 1、有没有 jvm 参数为读取外部参数
String extDs = System.getProperty("sell.externalDataSource");
Properties properties = null;
// 2、load 外部配置文件
if (extDs != null) {
File f = new File(extDs);
if (!f.exists()) {
throw new RuntimeException("外部配置文件不存在");
}
// 3、写入 properties 对象
properties = new Properties();
properties.load(new FileInputStream(f));
}
// 4、获取对应数据
String ftp_url = properties.getProperty("ftp_url");
String ftp_name = properties.getProperty("ftp_name");
String ftp_password = properties.getProperty("ftp_password");
System.out.println("ftp_url:" + ftp_url);
System.out.println("ftp_name:" + ftp_name);
System.out.println("ftp_password:" + ftp_password);
}
console -->
综上所述, 需求为 设置配置信息的优先级为
外部配置文件 > 指定的内部配置文件 > 内部配置文件 enable 为 true 的配置文件
package com.cdsn.sell.conf;
import com.google.common.collect.ImmutableSet;
import com.google.common.reflect.ClassPath;
import com.google.common.reflect.ClassPath.ResourceInfo;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
/**
* 加载ftp配置项
*
* @author ch
* @version 1.0.0
* @since 1.0.0
*
* Created at 2019-09-07 09:07
*/
@Component
public class ConnectionProducer {
@Bean
public void connect() throws IOException {
Properties properties = getProperties();
// 获取对应数据
String ftp_url = properties.getProperty("ftp_url");
String ftp_name = properties.getProperty("ftp_name");
String ftp_password = properties.getProperty("ftp_password");
System.out.println("ftp_url:" + ftp_url);
System.out.println("ftp_name:" + ftp_name);
System.out.println("ftp_password:" + ftp_password);
}
public Properties getProperties() throws IOException {
Properties activeProperties = null;
// 1、首先获取 优先级 最高的外部配置文件
String extDs = System.getProperty("sell.externalDataSource");
if (extDs != null) {
// 如果 jvm 参数中存在指定配置文件为外部,则读取外部配置文件
File dataSourceFile = new File(extDs);
if (!dataSourceFile.exists()) {
throw new RuntimeException("外部配置文件不存在,请重新检查路径!");
}
activeProperties = new Properties();
activeProperties.load(new FileInputStream(dataSourceFile));
} else {
// 2、其次获取优先级为2 的 jvm 参数
String active = System.getProperty("sell.activeDataSource");
// 3、获取所有对应目录下的配置文件
List<String> files = getResourceFiles("ds");
// 4、遍历 ds 文件夹下的配置文件
for (String fileName : files) {
// 5、如果有jvm参数指定了配置文件名,就使用指定的
// 如果没有jvm参数,则找到 enable 为true 的配置文件
if (fileName.endsWith(active == null ? ".properties" : active + ".properties")) {
// 获得数据流
InputStream stream = getClass().getClassLoader().getResourceAsStream(fileName);
// 将数据流封装到 properties 对象中
Properties properties = new Properties();
properties.load(stream);
// 如果 active 不存在,那么 找到 enable 为true的配置文件
if (active == null || active.equalsIgnoreCase("")) {
String enable = properties.getProperty("enable");
if (enable.equalsIgnoreCase("true")) {
activeProperties = properties;
}
} else {
// 存在 jvm 参数指定的文件
activeProperties = properties;
}
}
}
}
if (activeProperties == null) {
throw new IllegalArgumentException("No active datasource config found");
}
return activeProperties;
}
public List<String> getResourceFiles(String path) throws IOException {
List<String> fileNames = new ArrayList<>();
// 1、 获得 classLoader
ClassLoader classLoader = ConnectionProducer.class.getClassLoader();
// 2、 获取 classpath 下的所有文件 ,注意导包是google的
ImmutableSet<ResourceInfo> resources = ClassPath.from(classLoader).getResources();
// 3、判断当前是否在jar中运行,如果是的话,springboot 会自己在外面有 BOOT-INF 目录
URL url = ConnectionProducer.class.getResource("");
// 获取协议
String protocol = url.getProtocol();
System.out.println(protocol);
if ("jar".equals(protocol)) {
// jar
path = "BOOT-INF/classes/" + path;
}
// 4、遍历 截取出我们需要的 ds 文件下的配置文件
for (ResourceInfo info : resources) {
if (info.getResourceName().startsWith(path)) {
fileNames.add(info.getResourceName());
}
}
return fileNames;
}
}