springboot jar启动读取配置问题

150 阅读2分钟

spring默认会加载application.properties配置文件

默认加载application.properties and application.yaml路径

From the classpath

1.  The classpath root
1.  The classpath `/config` package

From the current directory

1.  The current directory
1.  The `config/` subdirectory in the current directory
1.  Immediate child directories of the `config/` subdirectory

加载配置顺序如下

Config data files are considered in the following order:

  1. Application properties packaged inside your jar (application.properties and YAML variants).
  2. Profile-specific application properties packaged inside your jar (application-{profile}.properties and YAML variants).
  3. Application properties outside of your packaged jar (application.properties and YAML variants).
  4. Profile-specific application properties outside of your packaged jar (application-{profile}.properties and YAML variants).

可以通过spring.config.namespring.config.location, and spring.config.additional-location三种方式修改spring默认加载配置的选项

spring.config.name 修改默认名称(application.properties),比如改为加载aaaa.properties spring.config.location  replace the default locations. For example,if spring.config.location is configured with the value optional:classpath:/custom-config/,optional:file:./custom-config/, the complete set of locations considered is:

  1. optional:classpath:custom-config/
  2. optional:file:./custom-config/

spring.config.additional-location is configured with the value optional:classpath:/custom-config/,optional:file:./custom-config/, the complete set of locations considered is:

  1. optional:classpath:/;optional:classpath:/config/
  2. optional:file:./;optional:file:./config/;optional:file:./config/*/
  3. optional:classpath:custom-config/
  4. optional:file:./custom-config/

spring加载额外配置

通过注解

通过@ImportResource加载xml文件,通过@PropertySource加载其他properties配置

@SpringBootApplication(scanBasePackages={"com.xxx.management","com.xxx.service.cache"},exclude = {
        JpaRepositoriesAutoConfiguration.class,
        HibernateJpaAutoConfiguration.class
})
@EnableRetry
@EnableCaching
@ImportResource({"classpath:*Context.xml", "classpath:*Source.xml", "classpath:*context.xml", "classpath:*aop*.xml"})
@PropertySources({
      @PropertySource("classpath:applicationConfigurations/allowedHeaders.properties"),
        @PropertySource("classpath:applicationConfigurations/xxx.properties")
})
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);

    }
}

手动加载

ConfigurableEnvironment可通过实现ApplicationContextAware等方式获取,可以看springorg.springframework.core.env包下相关类

ConfigurableEnvironment environment = (ConfigurableEnvironment)applicationContext.getEnvironment();
MutablePropertySources propertySources = environment.getPropertySources();
Properties properties = new Properties();
FileInputStream fis = new FileInputStream(new File("/user/temp/test.properties"))
properties.load(fis);
propertySources.addFirst(new PropertySource("external files: test.properties", properties));

java -jar启动时读取jar包中文件

直接使用File读取是报错信息如下

jar:nested:/Users/workspace/xxx-service-dev/target/xxx-service-10.20.0.jar/!BOOT-INF/classes/!/applicationConfigurations

 Properties file/folder [nested:/Users/xxx-service-dev/target/xxx-service-dev-10.20.0.jar/!BOOT-INF/classes/!/applicationConfigurations] does not exist!

可以通过以下两种方式解决 1,直接读取流,仅适用于单文件读取

InputStream inputStream = this.class.getClassLoader().getResourceAsStream("test.properties");

2,通过spring工具类加载,可以加载制定文件夹下所有配置

public static PropertiesPropertySource buildPropertySource(String name, String location){
    Resource[] resources = null;
    try {
        //applicationConfigurations/*  读取applicationConfigurations文件夹下所有配置文件
        resources = new PathMatchingResourcePatternResolver().getResources(location);
        Optional<Properties> reduce = Arrays.stream(resources).map(r -> {
            try {
                return PropertiesLoaderUtils.loadProperties(r);
            } catch (IOException e) {
                LOGGER.error("Unexpected IOException while buildPropertySource.", e);
                throw new RuntimeException(e);
            }
        }).reduce(PropertiesFolderPropertySource::accumulateProperties);
        return reduce.map(properties -> new PropertiesPropertySource(name, properties)).orElseGet(() -> new PropertiesPropertySource(name, new Properties()));
    } catch (IOException e) {
        LOGGER.error("Unexpected IOException while buildPropertySource.", e);
        throw new RuntimeException(e);
    }
}

//合并properties
private static Properties accumulateProperties(Properties left, Properties right) {
    Collection<String> intersection = CollectionUtils.<String>intersection(left.keySet(), right.keySet());

    if(!intersection.isEmpty()){
        throw new IllegalStateException("Found repeat Keys: "
                + intersection.toString());
    }

    left.putAll(right);
    return left;
}