我们通常会将一些配置,比如数据库连接信息,ftp连接信息等一些配置信息存储在 properties中,那么我们如何通过代码获得这些配置呢?


获取项目内 properties 配置内容

普通获取单个properties

 properties 路径位置:

java读jar内的配置文件 java读取外部配置文件_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 ---》

java读jar内的配置文件 java读取外部配置文件_java读jar内的配置文件_02


简单的获取单个 properties 的数据上述方法是完全可行的

那么假如我们现在 在 resources/ds/ 目录下 有多个配置文件,

针对不同的业务场景,使用不同的配置

该如何呢,比如在 UAT 环境在使用一套数据库配置,在 准生产环境下使用一套配置, 在 生产环境又使用另外一套配置该如何呢。

properties 路径 ( enable

java读jar内的配置文件 java读取外部配置文件_java_03

首先引入依赖,使用 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--->

java读jar内的配置文件 java读取外部配置文件_properties_04


这样我们还是不满足,不想把指定数据源 enable 写死在程序中,

想通过 jvm 启动参数来指定使用哪个数据源

properties 还是跟上述一样

java读jar内的配置文件 java读取外部配置文件_java_03

三个针对不同业务场景的配置的名字都不一样,那么我们只需要在启动项目的时候,指定一下 jvm 参数,比如我在 用户测试环境下,想使用 uat 的配置

首先指定 jvm 参数 ,在 idea 中直接加上

-Dsell.activeDataSource=prod

java读jar内的配置文件 java读取外部配置文件_System_06

代码如下

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 的配置文件

java读jar内的配置文件 java读取外部配置文件_java读jar内的配置文件_07

加上 jvm 参数,寻找 jvm 参数对应的配置文件

java读jar内的配置文件 java读取外部配置文件_java_08

=================================================

使用 java -jar 命令的时候 添加 jvm 参数

java -Dsell.activeDataSource=prod -jar sell-0.0.1-SNAPSHOT.jar

 


获取项目外部的 properties 配置内容

首先我们需要定义一个 jvm 参数,这里设置为  sell.externalDataSource 

然后在代码外部写一个 配置文件,我这里在桌面新建了一个 external.properties

java读jar内的配置文件 java读取外部配置文件_System_09

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 -->

java读jar内的配置文件 java读取外部配置文件_System_10


综上所述, 需求为 设置配置信息的优先级为

外部配置文件 > 指定的内部配置文件 > 内部配置文件 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;
  }
}