2019独角兽企业重金招聘Python工程师标准>>> hot3.png

简介

springboot使用一个全局配置文件,配置文件名是固定的:

  • application.properties
  • application.yml

配置文件的作用:修改springboot自动配置的默认值。springboot在底层都给我们自动配置好了;

配置文件位于src/resources下面。

YAML

yaml a markup language 是一个标记语言,以数据为中心,比其他类型的标记语言更适合作为配置文件。 标记语言:以前的配置文件大多都使用XXX.xml文件,

不同文件配置方式

YAML:

server:port: 8081

XML:

<server><port>8081</port>
</server>

properties:

server.port = 8081

例子:配置文件实现值的注入

编写配置文件

person:lastName: zhaoyilist:- list1- list2maps:k1: v1k2: v2age: 25boss: falsedog:name: xiaohuangage: 30

配置组件

// person类
@Component
@ConfigurationProperties(prefix = "person")
public class Person {private String lastName;private List<Object> list;private Map<String, Object> maps;private Integer age;private Boolean boss;private Dog dog;@Overridepublic String toString() {return "Person{" +"lastName='" + lastName + '\'' +", list=" + list +", maps=" + maps +", age=" + age +", boss=" + boss +", dog=" + dog +'}';}public String getLastName() {return lastName;}public void setLastName(String lastName) {this.lastName = lastName;}public List<Object> getList() {return list;}public void setList(List<Object> list) {this.list = list;}public Map<String, Object> getMaps() {return maps;}public void setMaps(Map<String, Object> maps) {this.maps = maps;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public Boolean getBoss() {return boss;}public void setBoss(Boolean boss) {this.boss = boss;}public Dog getDog() {return dog;}public void setDog(Dog dog) {this.dog = dog;}
}// dog类
package com.zhaoyi.hello1.com.zhaoyi.hello1.bean;public class Dog {private String name;private int age;@Overridepublic String toString() {return "Dog{" +"name='" + name + '\'' +", age=" + age +'}';}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}
}

使配置拥有提示

导入配置文件处理器,这样就会有提示编写资源的信息;

  <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional></dependency>

只有组件是容器中的组件,才能使用ConfigurationProperties提供的功能;

编写测试类

springboot单元测试:可以在测试期间很方便的类似编码一样进行自动注入等容器功能;

@RunWith(SpringRunner.class)
@SpringBootTest
public class Hello1ApplicationTests {@AutowiredPerson person;@Testpublic void contextLoads() {System.out.println(person);}
}

properties配置文件的编码问题

使用properties配置文件

注释掉application.yml的配置文件信息,新建一个application.properties文件,写入和applicatio.yml相同功能的配置

person.age=14
person.last-name=张三
person.boss=false
person.maps.k1=v1
person.maps.k2=v2
person.list=a,b,c
person.dog.name=小狗
person.dog.age=5

运行测试后发现有关中文部分的输出是乱码。

解决方法

idea使用的是utf-8编码,在setting处查询file encoding,设置为utf-8,并选择在运行时转化为ascll(勾选)

@configurationProperties和@Value

Spring中配置一个Bean:

<bean class="person"><property name="lastName" value="zhangsan"></property>
</bean>

其中,value可以:

  • 字面量
  • ${key} 从环境变量或者配置文件中提取变量值
  • #{SPEL}

而@Value其实效果和其一样,比如,在类属性上写

@Value("person.lastName")
private String lastName
@Value("#{11*2}")
private Integer age

区别

||@ConfigurationProperties|@Value| |-|-|-| |功能|批量注入配置文件中的属性|一个个指定| ||支持松散绑定|不支持松散绑定| |SpEL|不支持|支持| |JSR303数据校验|支持|不支持| |复杂类型封装|支持|不支持| 注:

  • 松散绑定例如: 配置文件填写的是last-name,而@Value必须写一模一样的,否则会报错。而使用@ConfigurationProperties则可以使用驼峰式(其实就是类的属性名)
  • @Validation 在类上加入此配置之后,开启jsr303校验,例如在某字段上加上@Email,则配置文件对应字段必须符合邮箱格式。相反,如果此处我们使用@Value注入值,可以看到,可以正常的注入,即便提供的不符合邮箱格式,也不会报错。

选择

从上面的说明我们可以知道,两者在配置上基本可以相互替换,彼此功能也大体一致,那么,我们在业务场景中,该选用哪一种进行编码呢?

  1. 如果说,我们只是在某个业务逻辑中需要获取一下配置文件的某项值,考虑使用@Value.
@RestController
public class HelloController {@Value("${person.last-name}")private String name;@RequestMapping("/")public String hello(){return "hello world, " + name;}
}
  1. 但是,如果我们专门去写一个java bean来和配置文件进行映射,那么毫无疑问,我们应该使用@ConfigurationProperties

@PopertySource注解

@PropertySource 加载指定的配置文件。

我们知道,@ConfigurationProperties默认从全局配置文件(application.properties)中获取值,但通常我们会将相关的配置文件放到某个配置文件中,例如,我们将有关person的配置信息放到person.properties中去。为了使组件类Person能够找到配置文件的配置信息,需要使用增加新的注解@PropertySource指定从哪里加载配置等相关信息。

@PropertySource("classpath:person.properties")
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
}

@ImportResource注解

@ImportResource 导入Spring的配置文件,让配置文件里面的内容生效。

  1. 添加新的服务类HelloService
package com.zhaoyi.hello1.service;
public class HelloService {
}
  1. 在类目录下创建一个bean.xml,即spring的配置文件,其中配置了一个service的bean.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="helloService" class="com.zhaoyi.hello1.service.HelloService"></bean>
</beans>

那么问题来了,在spring-boot中显然是不会加载此bean的,我们测试一下。

  1. 编写测试类
@RunWith(SpringRunner.class)
@SpringBootTest
public class Hello1ApplicationTests {@AutowiredApplicationContext ioc;@Testpublic void testBean(){System.out.println("Is have helloService bean? " + ioc.containsBean("helloService"));}
}

测试结果:

Is have helloService bean? false

Spring boot里面是没有Spring的配置文件,我们自己编写的配置文件,也不能自动识别,想让Spring的配置文件生效,则需要手动指示将其加载进行,使用@ImportResource标注在一个配置类(例如应用程序启动类,他也是一个配置类)上:

@ImportResource(locations = {"classpath:bean.xml"})
@SpringBootApplication
public class Hello1Application {public static void main(String[] args) {SpringApplication.run(Hello1Application.class, args);}
}

这时候运行测试用例就会发现,bean已经出现在容器中了。

@Bean注解

@ImportResource(locations = {"classpath:bean.xml"})

一般我们不会使用6中所提到的这种方式,因为xml配置方式实在是写了太多的无用代码,如果xml的标签声明,以及头部的域名空间导致。因此,SpringBoot推荐给容器中添加组件的方式:全注解方式。也就是用配置类来充当bean配置文件。如下,即为一个配置类:

/*** @Configuration 指明当前类是一个配置类*/
@Configuration
public class MyConfig {// 将方法的返回值添加到容器中:容器中这个组件的id就是方法名@Beanpublic HelloService helloService(){return new HelloService();}
}

通过该配置类,可以为容器中添加了一个名为helloService的bean。

配置文件占位符

无论是使用yaml还是properties都自持文件占位符配置方式

随机数

${random.value}

${random.int}

${random.long}

${random.int(10)}

${random.int[1024,65536]}

属性占位符

  • 可以在配置文件中引用前面配置过的属性;
  • ${app.name:默认值} 若找不到属性时,则取默认值处填写的值;

例子

  1. 在person.properties中写入如下配置
person.age=14
person.last-name=张三${random.uuid}
person.boss=false
person.maps.k1={person.xxx:novalue}
person.maps.k2=v2
person.list=a,b,c
person.dog.name=${person.last-name}_小狗狗
person.dog.age=${random.int}
  1. 测试输出
Person{lastName='张三1b9fbbb1-6c58-4a35-8165-ad23800d7456', list=[a, b, c], maps={k2=v2, k1=novalue}, age=14, boss=false, dog=Dog{name='张三b3a355d7-54ce-4afd-9ae6-d3be4aeb4165_小狗狗', age=-122850975}}

注意:留意默认值那一项设置,我们如愿的成功设置了默认值novalue。在实际项目中,这种情况比较常用,稍微留意一下。如果没有默认值,则会将${xxx}这一段作为值,这显然是错误的。

9 Profile

profile一般是spring用来做多环境支持的,可以通过激活指定参数等方式快速的切换当前环境。

9.1 多Profile文件

我们在主配置文件编写的时候,文件名可以是 application-{profile}.properties(yml) 例如: application-dev.properties、application-prod.properties等。

激活指定profile

  1. 在application.properties中指定:
spring.profiles.active=dev
  1. 命令行方式激活,此配置的优先级高于配置文件处的配置。
--spring.profiles.active=dev
  • 方式一 点击编译环境右上角的下拉框,选择第一项edit configuration,在environment配置节中的Program arguments写入spring.profiles.active=dev即可。
  • 方式二 将当前的项目打包生成jar包,然后执行java -jar your-jar-name.jar --spring.profiles.active=dev即可。
  1. 虚拟机参数方式激活 在步骤2的老地方,Program arguments上一项即为虚拟机参数激活,不过填写的内容为-Dspring.profiles.active=dev,即多了一个-D而已。

yml多文档配置文件

若我们使用properties,则需要编写多个不同的配置文件,但如果我们使用yml的话,则可以通过多文档配置节实现单文件管理。注:有关yml相关的知识参考此文档的前半部分

可以看到,我们通过---三个横线实现文档分割,同时在每一个文档块处指定了各个profile的不同配置信息,即dev环境下启动服务使用8082端口,prod环境下使用8083端口。而指定哪一个profile则是通过默认的文档块(即第一块)中的spring.profiles.active进行配置。完成如上配置之后我们启动服务,显然此时是以激活的prod环境所配置的端口8083运行的,如下启动日志所示:

com.zhaoyi.hello1.Hello1Application      : The following profiles are active: prod
o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8083 (http)

也就说,当我们选定一个profile后,对应的文档块的配置就会全部生效。

9 配置文件的加载位置

SpringBoot启动会扫描以下位置的application.properties或者application.yml文件作为SpringBoot的默认配置文件:

  • file:./config/
  • file:./
  • classpath:/config/
  • classpath:/

以上是按照优先级顺序从高到低,所有位置的文件都会被加载,但对于相同配置:高优先级配置内容会覆盖低优先级配置的内容,其他的则互补。

我们也可以通过spring.config.location参数来设置默认的配置文件位置。项目打包好以后,使用命令行参数形式来指定配置文件的新位置,指定的配置文件和默认加载的配置互补起作用。并且我们指定的该配置文件优先级是最高的。

外部配置的加载顺序

SpringBoot支持多种外部配置方式,他可以从以下位置加载配置,按优先级从高到低排列如下(高优先级配置覆盖低优先级配置,所有配置会形成互补配置):

  1. 命令行参数
java -jar package_name_version.jar --server-port=8080 --server.context-path=/hello

多个参数之间用空格分开,用--parameter_name=value进行配置。

  1. 来自java:comp/env的JNDI属性
  2. java系统属性(System.getProperties())
  3. 操作系统环境变量
  4. RandomValuePropertySource配置的random.*属性值

都是由jar包外向jar包内进行寻找,高优先级的配置覆盖低优先级的配置。然后 优先加载带profile的:

  1. jar包外部的application-{profile}.properties或application.yml(带spring.profile)配置文件

在jar文件的同级目录放一个application.properties文件,其配置内容会被加载;

  1. jar包内部的application-{profile}.properties或application.yml(带spring.profile)配置文件

再来加载不带profile的:

  1. jar包外部的application.properties或application.yml(不带spring.profile)配置文件
  2. jar包内部的application.properties或application.yml(不带spring.profile)配置文件
  3. @Configuration注解类上的@PropertySource
  4. 通过SpringApplication.setDefaultProperties指定的默认属性。

官方文档列出了比这里更多的配置文档,请参考,版本更迭地址会经常变动,可自行前往官方网站进行查看。

自动配置原理

配置文件的配置属性可以参照官方文档:前往

自动配置原理

  1. springboot启动的时候加载主配置类,开起了自动配置功能@EnableAutoConfiguration
  2. @EnableAutoConfiguration作用:利用EnableAutoConfigurationImportSelector给容器中导入一些组件,可以查看selectImport()方法的内容:
    public String[] selectImports(AnnotationMetadata annotationMetadata) {if (!this.isEnabled(annotationMetadata)) {return NO_IMPORTS;} else {AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata);return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());}}

扫描所有jar包类路径下META-INF/spring.factories文件,吧扫描到的这些文件的内容包装成properties对象;从properties中获取到EnableAutoConfiguration.class类对应的值,然后把他们添加在容器中;

说到底,就是将类路径下META-INF/spring.factories里面配置的所有EnableAutoConfiguration的值加入到了容器中。

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.cloud.CloudServiceConnectorsAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
...(more)

每一个这样的xxxAutoConfiguration类都会是容器中的一个组件,都加入到了容器中,用他们来做自动配置。

  1. 每一个自动配置类进行自动配置功能。 以org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration为例:

@Configuration
@EnableConfigurationProperties({HttpProperties.class})
@ConditionalOnWebApplication(type = Type.SERVLET
)
@ConditionalOnClass({CharacterEncodingFilter.class})
@ConditionalOnProperty(prefix = "spring.http.encoding",value = {"enabled"},matchIfMissing = true
)
public class HttpEncodingAutoConfiguration {@Bean@ConditionalOnMissingBeanpublic CharacterEncodingFilter characterEncodingFilter() {CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();filter.setEncoding(this.properties.getCharset().name());filter.setForceRequestEncoding(this.properties.shouldForce(org.springframework.boot.autoconfigure.http.HttpProperties.Encoding.Type.REQUEST));filter.setForceResponseEncoding(this.properties.shouldForce(org.springframework.boot.autoconfigure.http.HttpProperties.Encoding.Type.RESPONSE));return filter;}...
}

我们可以看到该类的注解如下:

  • @Configuration 毫无疑问,表明这是一个配置类,和我们要自定义一个配置文件一样,实现给容器中添加组件;
  • @EnableConfigurationProperties 启动指定类的ConfigurationPropertiesg功能,这样就可以将配置文件中对应的值和HttpEncodingProperties绑定起来;并把HttpEncodingProperties加入到ioc容器中;
  • @ConditionalOnWebApplication Spring底层@Conditional注解,根据不同的条件,如果满足指定的条件,整个配置类里面的配置就会生效;此处判断的就是当前应用是不是Web应用;否则配置不生效;
  • @ConditionalOnClass 判断当前项目有没有类(CharacterEncodingFilter),这是SpringMVC中进行乱码解决的过滤器;
  • @ConditionalOnProperty 判断配置文件中是否存在某个配置 spring.http.encoding.enabled;如果不存在,则判断成立,如果没有配置,则此处将其设置为true
  • @Bean 给容器中添加Bean组件,该组件的某些值需要从properties中获取,此处即为HttpEncodingProperies,显然此刻他的取值已经和springboot的properties文件进行注入了;

根据不同的条件进行判断当前这个配置类是否生效。一单这个配置类生效,这个配置类就会给容器中添加各种组件;这些组件的属性均来自于其对应的Properties类的,这些Properties类里面的每一个属性,又是和配置文件绑定的。

  1. 所有在配置文件中能配置的属性都是在xxxProperties类中的封装者;配置文件能配置什么就可以查看对应的属性类。如上面的这个配置类我们就可以参考他的注解@EnableConfigurationProperties指定的properties类HttpProperties
@ConfigurationProperties(prefix = "spring.http"
)
public class HttpProperties {

配置精髓

  1. springboot启动会加载大量的自动配置类;
  2. 我们看我们需要的功能有没有springboot默认写好的自动配置类;
  3. 我们再来看这个自动配置类中到底配了那些组件,倘若已经有了,我们就不需要再编写配置文件进行配置了。
  4. 给容器中自动配置类添加组件的时候,会从对应的Properties类中获取某些属性。我们就可以在配置文件中指定这些属性的值(其已经通过注解进行了绑定);

总结

xxxAutoConfiguration 这种类就是用来做自动配置的,他会给容器中添加相关的组件,其对应的Properties则对应了配置的各种属性;也就是说,通过这些配置类,我们以前需要在SpringMVC中写配置类、文件实现的东西,现在,只需要在Properites配置文件中加入相关的配置即可,不再那么麻烦了。

当然,一些特殊的配置还是得自己写组件的哦。

@Conditional*相关注解

@Conditinal派生注解

只有其指定的条件成立,配置类的所有类型才会生效,更小范围的,例如注释在某个Bean组件上面的相关条件注解成立,才会生成该Bean。

常用派生注解一览

@Conditional扩展注解|作用(判断是否满足当前指定条件) -|- @ConditionalOnJava|系统的java版本是否符合要求 @ConditionalOnBean| 容器中存在指定Bean @ConditionalOnMissingBean |容器中不存在指定Bean @ConditionalOnExpression| 满足SpEL表达式指定 @ConditionalOnClass |系统中有指定的类 @ConditionalOnMissingClass |系统中没有指定的类 @ConditionalOnSingleCandidate |容器中只有一个指定的Bean,或者这个Bean是首选Bean @ConditionalOnProperty |系统中指定的属性是否有指定的值 @ConditionalOnResource |类路径下是否存在指定资源文件 @ConditionalOnWebApplication |当前是web环境 @ConditionalOnNotWebApplication |当前不是web环境 @ConditionalOnJndi |JNDI存在指定项

我们可以发现,尽管我们拥有许多的自动配置类,其还是得必须满足一定条件才会生效,该机制就是有@Conditinal派生注解等控制的,常见的是@ConditionalOnClass,即判断当前系统具不具备相关的类。

debug模式

配置文件application.properties中添加配置,开启Debug模式:

debug=true

默认情况下debug的值为false,通过启用debug=true属性,让控制台打印相关的报告,例如那些自动配置类启用(positive matches)、没启用(negative matches)等。

转载于:https://my.oschina.net/u/3091870/blog/2993890

【Spring Boot】3.Spring Boot的配置相关推荐

  1. Spring Boot 面试杀手锏:自动配置原理

    欢迎关注方志朋的博客,回复"666"获面试宝典 不论在工作中,亦或是求职面试,Spring Boot已经成为我们必知必会的技能项.除了某些老旧的政府项目或金融项目持有观望态度外,如 ...

  2. 徒手解密 Spring Boot 中的 Starter自动化配置黑魔法

    我们使用 Spring Boot,基本上都是沉醉在它 Stater 的方便之中.Starter 为我们带来了众多的自动化配置,有了这些自动化配置,我们可以不费吹灰之力就能搭建一个生产级开发环境,有的小 ...

  3. spring boot +spring data jpa +druid 多数据源配置

    一.首先pom.xml新增如下依赖 <dependencies><dependency><groupId>org.springframework.boot</ ...

  4. 关于Spring Boot WebSocket整合以及nginx配置详解

    这篇文章主要给大家介绍了关于Spring Boot WebSocket整合以及nginx配置的相关资料,文中通过示例代码给大家介绍的非常详细,相信对大家的学习或者工作具有一定的参考学习价值,需要的朋友 ...

  5. Spring Boot是如何实现自动配置的?

    原文:sylvanassun.github.io/2018/01/08/2018-01-08-spring_boot_auto_configure/ Spring Boot 是 Spring 旗下众多 ...

  6. Spring boot的Spring MVC自动配置

    自动配置 参考官网 https://docs.spring.io/spring-boot/docs/1.5.10.RELEASE/reference/htmlsingle/#boot-features ...

  7. Spring Boot中的一些常用配置介绍!

    这篇教程将为你介绍Spring Boot 中的一些常用配置,比如:自定义 Banner.配置日志.关闭特定的自动配置等. 自定义Banner 在 Spring Boot 启动的时候会有一个默认的启动图 ...

  8. springboot生成包含特定数字_面试必问 —— Spring Boot 是如何实现自动配置的?

    什么是@Conditional? AutoConfigure源码分析 自动配置类中的条件注解 <Netty 实现原理与源码解析 -- 精品合集> <Spring 实现原理与源码解析 ...

  9. 13、Spring Boot 2.x 多数据源配置

    1.13 Spring Boot 2.x 多数据源配置 完整源码: Spring-Boot-Demos 转载于:https://www.cnblogs.com/Grand-Jon/p/9999779. ...

  10. datav本地部署 java,Spring Boot对Spring Data JPA的自动配置

    一 点睛 Spring Boot对Spring Data JPA的自动配置放置在如下路径: 二 源码分析 1 JpaRepositoriesAutoConfiguration类分析 @Configur ...

最新文章

  1. 高铁转地铁不想重复安检?多地已有举措
  2. gcc编译自定义头文件
  3. 鸿蒙 github harmony,鸿蒙HarmonyOS三方件开发指南-SwipeLayout侧滑删除
  4. v8学习笔记(四) 对象机制
  5. AWS Lambda事件源映射:使您的触发器混乱无序
  6. 漫步最优化四十四——基本拟牛顿法
  7. 从零开始学keras之多分类问题
  8. poj 1160 dp
  9. 如何将js加入到HTML中
  10. 关于对DataTable进行操作的几个例子总结
  11. 计算机信息的应用安全中心在哪,怎么通过windows安全中心扫描出当前具有威胁的应用...
  12. Multi-Task 多任务学习, 那些你不知道的事
  13. 中远通在创业板IPO过会:前三季度收入11亿元,罗厚斌为董事长
  14. php音乐相册怎么打开,手机如何制作相册 手机音乐相册的制作方法
  15. 如何去掉图片上的水印 图片水印怎么去掉
  16. 一个或多个页边距被设置到可打印区域之外,是否继续?
  17. abs和pc混在一起怎么解决_PC/ABS常见问题及解决方案
  18. [免费参加] 2015微软社区大课堂Community Camp开放报名啦!
  19. redis key过期通知
  20. CF1005A Tanya and Stairways

热门文章

  1. H3C V7版本的系统默认权限
  2. 牛客网Java刷题知识点之表达式类型的自动提升
  3. 不越狱 继续逆向 微信运动
  4. 开始开发HoloLens应用吧 Start Developing HoloLens Apps Today
  5. 一篇不错的讲解Java异常的文章
  6. C#l操作Exce知识点
  7. 【Data guard】Failover切换
  8. Swift 枚举简单使用
  9. spring-boot+spring-session集成
  10. Laravel教程 四:数据库和Eloquent