标签分类
技术文章
当前位置:主页 > 计算机编程 > java > Springboot引用外部配置文件的步骤

Springboot引用外部配置文件的实例方法

  • 发布时间:
  • 作者:码农之家原创
  • 点击:115

Springboot引用外部配置文件的步骤

这篇文章主要知识点是关于Springboot,外部配置文件,springboot配置文件,Springboot引用外部配置文件的步骤,Spring boot外部配置(配置中心化)详解 的内容,如果大家想对相关知识点有系统深入的学习,可以参阅以下电子书

深入浅出Spring Boot 2.x
  • 类型:Spring大小:257.67 MB格式:PDF出版:人民邮电出版社作者:杨开振
立即下载

现在的项目越来越多的都是打包成jar运行尤其是springboot项目,这时候配置文件如果一直放在项目中,每次进行简单的修改时总会有些不方便,这里我们看下打包成jar之后,从外部配置文件中读取配置信息。

首先想到的是通过java代码读取外边某个路径下的文件,但是开始做之后发现好多问题。后来又找其它解决方案,正好搜到一种简单的解决方式:

java -jar demo.jar --Dspring.config.location=myapplication.properties

这样就可以通过@value注解读取myapplication.properties中的配置信息了。(上边的大写D好像可以不写的)

后来想着直接把spring.config.location写到application.properties配置文件中,然后指定一个固定的外部配置文件来获取信息,这样启动的时候就可以不用加最后一行了。

spring.config.location=C:\\Users\\Administrator\\git\\Display\\host.properties

可是这种方式是行不通的,比如我配置文件中有下面信息:

myname=hellopangkunkun

代码:

myname=hellopangkunkun

我在启动的时候直接报这个地方的错误,说是无法找到myname,导致整个项目出异常。

后来搜了下文章,对比官网文档,又得到了一些信息:

24.3 Application property files
SpringApplication will load properties from application.properties files in the following locations and add them to the Spring Environment:

A /config subdirectory of the current directory.
The current directory
A classpath /config package
The classpath root
The list is ordered by precedence (properties defined in locations higher in the list override those defined in lower locations).

这里说了四种方式可以把配置文件放到外部的。
第一种是在jar包的同一目录下建一个config文件夹,然后把配置文件放到这个文件夹下;
第二种是直接把配置文件放到jar包的同级目录;
第三种在classpath下建一个config文件夹,然后把配置文件放进去;
第四种是在classpath下直接放配置文件。

这四种方式的优先级是从一到四一次降低的。

注: 一二两种方案其实不是jar包的同级目录,而是(执行启动指令的)同级目录。为了便于理解我把上面的当前目录说成jar包的同级目录,这种说法并不对。如果是刚开始接触或者调试这块,还是在jar包同级目录方便。

由于我们是要从外部读取文件,所以直接说前两种。

看下文件目录结构:

Springboot引用外部配置文件的方法步骤

这里的application.properties是我们的配置文件,config是创建的另外一个目录,放的也是application.properties。

Display-1.0-SNAPSHOT.jar中可以包含application.properties配置文件也可以不包含。

为了验证可以在config中设置myname=name1,jar同级目录中设置myname=name2,如果jar中包含配置文件,将其中设置成myname=name3。

直接使用指令启动:

java -jar Display-1.0-SNAPSHOT.jar

之后验证可得知,我们通过@Value(“${myname}”)获取到的myname的值是name1,把config下的配置文件删除后获取的结果是name2,都删除后才会获取jar包中配置文件的数据name3。

另外如果我们想要想配置测试、开发、生产环境一样使用另外一个配置文件怎么来实现呢?

下面继续,我把application.properties的信息修改如下:

spring.profiles.active=dev,host

配置文件目录结构:

Springboot引用外部配置文件的方法步骤

我又新增了一个名为application-host.properties的配置文件,同理也可以把这个文件考出来放到jar包外面,同级目录或者config下。

这样项目启动之后dev配置文件和host配置文件都会生效。

Springboot引用外部配置文件的方法步骤

这里为了突出其他的配置文件我只把host的拷出来了,dev的还是在jar包里,application.properties配置文件放在jar中也一样,我们需要的主要是host的配置文件。

这样每次修改的时候只需要修改配置文件信息,然后重启项目就好,不需要重新打包。

如果想要只修改配置文件,不重启项目就能生效,可以考虑用java来读取配置文件中的数据,把它当作一个普通文件来读取,或者写到其他数据库中也行。上面这些方案已经能够满足我的需求了,所以其他的不在做了。

最后提个问题,也是我没弄明白的,希望知道的各位能够给个答案:

我把spring.config.location这个配置写到配置文件中为什么没有生效?

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持码农之家。

Spring boot外部配置(配置中心化)详解

前言

在项目中为了灵活配置,我们常采用配置文件,常见的配置文件就比如xml和properties,springboot允许使用properties和yaml文件作为外部配置。现在编译器对于yaml语言的支持还不够好,目前还是使用properties文件作为外部配置。

在Spring cloud config出来之前, 自己实现了基于ZK的配置中心, 杜绝了本地properties配置文件, 原理很简单, 只是重载了PropertyPlaceholderConfigurer的mergeProperties() :

/**
 * 重载合并属性实现
 * 先加载file properties, 然后并入ZK配置中心读取的properties
 *
 * @return 合并后的属性集合
 * @throws IOException 异常
 */
@Override
protected Properties mergeProperties() throws IOException {
 Properties result = new Properties();
 // 加载父类的配置
 Properties mergeProperties = super.mergeProperties();
 result.putAll(mergeProperties);
 // 加载从zk中读取到的配置
 Map<String, String> configs = loadZkConfigs();
 result.putAll(configs);
 return result;
}

这个实现在spring项目里用起来还是挺顺手的, 但是近期部分spring-boot项目里发现这种placeholder的实现跟spring boot的@ConfigurationProperties(prefix = "xxx") 不能很好的配合工作,

也就是属性没有被resolve处理, 用@Value的方式确可以读到, 但是@Value配置起来如果属性多的话还是挺繁琐的, 还是倾向用@ConfigurationProperties的prefix, 于是看了下spring boot的文档发现 PropertySource

order:

* Devtools global settings properties on your home directory (~/.spring-boot-devtools.properties when devtools is active).

* @TestPropertySource annotations on your tests.

* @SpringBootTest#properties annotation attribute on your tests.

* Command line arguments.

* Properties from SPRING_APPLICATION_JSON (inline JSON embedded in an environment variable or system property)

* ServletConfig init parameters.

* ServletContext init parameters.

* JNDI attributes from java:comp/env.

* Java System properties (System.getProperties()).

* OS environment variables.

* A RandomValuePropertySource that only has properties in random.*.

* Profile-specific application properties outside of your packaged jar (application-{profile}.properties and YAML variants)

* Profile-specific application properties packaged inside your jar (application-{profile}.properties and YAML variants)

* Application properties outside of your packaged jar (application.properties and YAML variants).

* Application properties packaged inside your jar (application.properties and YAML variants).

* @PropertySource annotations on your @Configuration classes.

* Default properties (specified using SpringApplication.setDefaultProperties).

不难发现其会检查Java system propeties里的属性, 也就是说, 只要把mergerProperties读到的属性写入Java system props里即可, 看了下源码, 找到个切入点

/**
 * 重载处理属性实现
 * 根据选项, 决定是否将合并后的props写入系统属性, Spring boot需要
 *
 * @param beanFactoryToProcess
 * @param props    合并后的属性
 * @throws BeansException
 */
@Override
protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess, Properties props) throws BeansException {
 // 原有逻辑
  super.processProperties(beanFactoryToProcess, props);
 // 写入到系统属性
 if (writePropsToSystem) {
  // write all properties to system for spring boot
  Enumeration<?> propertyNames = props.propertyNames();
  while (propertyNames.hasMoreElements()) {
    String propertyName = (String) propertyNames.nextElement();
    String propertyValue = props.getProperty(propertyName);
    System.setProperty(propertyName, propertyValue);
  }
 }
}

为避免影响过大, 设置了个开关, 是否写入系统属性, 如果是spring boot的项目, 就开启, 这样对线上非spring boot项目做到影响最小, 然后spring boot的@ConfigurationProperties完美读到属性;

具体代码见: org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor

@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
  throws BeansException {
 ConfigurationProperties annotation = AnnotationUtils
   .findAnnotation(bean.getClass(), ConfigurationProperties.class);
 if (annotation != null) {
  postProcessBeforeInitialization(bean, beanName, annotation);
 }
 annotation = this.beans.findFactoryAnnotation(beanName,
 ConfigurationProperties.class);
 if (annotation != null) {
  postProcessBeforeInitialization(bean, beanName, annotation);
 }
 return bean;
}

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对码农之家的支持。

以上就是本次给大家分享的全部知识点内容总结,大家还可以在下方相关文章里找到儿童python编程入门书籍推、 vue项目中使用md5加密以及、 解决axios.interceptors.respon、 等java文章进一步学习,感谢大家的阅读和支持。

上一篇:java对synchronized的优化知识点总结

下一篇:springboot写一个自己的starter源码实例详解

展开 +

收起 -

学习笔记
网友NO.139770

SpringBoot配置SwaggerUI访问404错误的解决方法

SpringBoot 配置SwaggerUI 访问404的小坑。 在学习SpringBoot构建Restful API的时候遇到了一个小坑,配置Swagger UI的时候无法访问。 首先在自己的pom文件中加入Swagger的依赖,如下所示: dependency groupIdio.springfox/groupId artifactIdspringfox-swagger-ui/artifactId version2.2.2/version /dependency dependency groupIdio.springfox/groupId artifactIdspringfox-swagger2/artifactId version2.2.2/version/dependency 然后在新建一个SwaggerConfig类: Configuration@EnableSwagger2public class SwaggerConfig { @Bean public Docket createRestApi() { return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .select() .apis(RequestHandlerSelectors.basePackage("com.nightowl")) .paths(PathSelectors.any()) .build(); } private ApiInfo apiInfo() { return new ApiInfoBuilder() .title("NightOwl RESTful APIs") .description("关注我 http://hwangfantasy.github.io/") .termsOfServiceUrl("http://hwangfantasy.github.io/") .contact("颜艺学长") .version("1.0") .build(); }} 最后在自己的Controller中加上一系列的API注解即可,其实不需要加上API注解也可以正常使用。 最后在localhost:8080/swagger-ui.html 访问即可看到swagger页面了。 但是关键来了,我第一次按照这样的方法配置却提示如下错误: Whitelabel Error PageThis application has no explicit mapping for /error, so you are seeing this as a fallback.Thu Nov 24 19:57:13 CST 2016There was an unexpected error (type=Not Found, status=404……

网友NO.877969

Spring Boot打包部署和环境配置详解

执行命令 yum -y list java* 查看可安装java版本。 Failed to set locale, defaulting to CLoaded plugins: fastestmirrorbase | 3.6 kB 00:00:00extras | 3.4 kB 00:00:00updates | 3.4 kB 00:00:00(1/4): base/7/x86_64/group_gz | 166 kB 00:00:00(2/4): extras/7/x86_64/primary_db | 201 kB 00:00:00(3/4): updates/7/x86_64/primary_db | 5.0 MB 00:00:00(4/4): base/7/x86_64/primary_db | 6.0 MB 00:00:00Determining fastest mirrors * base: ftpmirror.your.org * extras: mirror.fileplanet.com * updates: centos.mirror.constant.comAvailable Packagesjava-1.6.0-openjdk.x86_64 1:1.6.0.41-1.13.13.1.el7_3 basejava-1.6.0-openjdk-demo.x86_64 1:1.6.0.41-1.13.13.1.el7_3 basejava-1.6.0-openjdk-devel.x86_64 1:1.6.0.41-1.13.13.1.el7_3 basejava-1.6.0-openjdk-javadoc.x86_64 1:1.6.0.41-1.13.13.1.el7_3 basejava-1.6.0-openjdk-src.x86_64 1:1.6.0.41-1.13.13.1.el7_3 basejava-1.7.0-openjdk.x86_64 1:1.7.0.221-2.6.18.0.el7_6 updatesjava-1.7.0-openjdk-accessibility.x86_64 1:1.7.0.221-2.6.18.0.el7_6 updatesjava-1.7.0-openjdk-demo.x86_64 1:1.7.0.221-2.6.18.0.el7_6 updatesjava-1.7.0-openjdk-devel.x86_64 1:1.7.0.221-2.6.18.0.el7_6 updatesjava-1.7.0-openjdk-headless.x86_64 1:1.7.0.221-2.6.18.0.el7_6 updatesjava-1.7.0-openjdk-javadoc.noarch 1:1.7.0.221-2.6.18.0.el7_6 updatesjava-1.7.0-openjdk-src.x86_64 1:1.7.0.221-2.6.18.0.el7_6 updatesjava-1.8.0-openjdk.i686 1:1.8.0.212.b04-0.el7_6 updatesjava-1.8.0-openjdk.x86_64 1:1.8.0.212.b04-0.el7_6 updatesjava-1.8.0-openjdk-accessibility.i686 1:1.8.0.212.b04-0.el7_6 updatesjava-1.……

网友NO.870800

Spring Boot 配置和使用多线程池的实现

某些情况下,我们需要在项目中对多种任务分配不同的线程池进行执行。从而通过监控不同的线程池来控制不同的任务。为了达到这个目的,需要在项目中配置多线程池。 spring boot 提供了简单高效的线程池配置和使用方案。 配置 首先是配置线程池的bean交给spring 管理: @Configurationpublic class TaskExecutePool { @Bean(name ="threadPoolA")public ThreadPoolTaskExecutormyTaskAsyncPool() {ThreadPoolTaskExecutor executor =new ThreadPoolTaskExecutor(); executor.setCorePoolSize(4); executor.setMaxPoolSize(8); executor.setQueueCapacity(100); executor.setKeepAliveSeconds(60); executor.setThreadNamePrefix("Pool-A"); executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); executor.initialize(); return executor; }@Bean(name ="ThreadPoolB")public ThreadPoolTaskExecutorAsyncPoolB() {ThreadPoolTaskExecutor executor =new ThreadPoolTaskExecutor(); executor.setCorePoolSize(2); executor.setMaxPoolSize(4); executor.setQueueCapacity(8); executor.setKeepAliveSeconds(60); executor.setThreadNamePrefix("Pool-B"); //当任务数量超过MaxPoolSize和QueueCapacity时使用的策略,该策略是又调用任务的线程执行 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); executor.initialize(); return executor; }} 使用 使用线程只需要在执行方法上加上注释,同时该方法的类必须被定义为bean,交由spring管理。 可以在类上使……

<
1
>

Copyright 2018-2019 xz577.com 码农之家

版权责任说明