配置文件读取、实体注入

配置文件

配置文件

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

  • application.properties
  • application.yml

YAML语法

基本语法

k:(空格)v:表示一对键值对(空格必须有)

空格的缩进来控制层级关系;只要是左对齐的一列数据,都是同一层级的

server:
    port: 8081
    path: /hello

属性和值是大小写敏感

值的写法

字面量:普通值(数字,字符串,布尔)

k: v:字面直接来写

字符串默认不用加上单引号或者双引号

  • “”:双引号;不会转义字符串里面的特殊字符;特殊字符会作为本身想表示的意思

    name: “zhangsan \n lisi”:输出;zhangsan 换行 lisi

  • ‘’:单引号;会转义特殊字符,特殊字符最终只是一个普通的字符串数据

    name: ‘zhangsan \n lisi’:输出;zhangsan \n lisi

对象、Map(属性和值)(键值对):

​ k: v:在下一行来写对象的属性和值的关系;注意缩进

​ 对象还是k: v的方式

dog:
    name: Tom
    age: 12
maps: {k1: v1,k2: v2}
数组(List、Set):

用- 值表示数组中的一个元素:

lists:
    - lisi
    - zhaoliu
lists: [list,zhaoliu]

Properties语法

使用小细节

logo.location=/image/logo/  
mail.host=webmaster@zlex.org  
site.name=zlex中文网站  
welcome=欢迎您,{0}!  
ClassPathResource resource = new ClassPathResource("abc.properties");
Properties properties = new Properties();
properties.load(resource.getInputStream());
properties.forEach((k, v) -> System.out.println(k + "=" + v));

解决中文乱码问题: 使用Reader读取

ClassPathResource resource = new ClassPathResource("abc.properties");
Properties properties = new Properties();
BufferedReader reader = new BufferedReader(new InputStreamReader(resource.getInputStream(), StandardCharsets.UTF_8));
properties.load(reader);
properties.forEach((k, v) -> System.out.println(k + "=" + v));

Properties 文件中可议使用:吗?

logo.location:/image/logo/  
mail.host:webmaster@zlex.org  
site.name:zlex中文网站  
welcome:欢迎您,{0}!  

=/:中间可以有N个空格吗?

logo.location:     /image/logo/  
mail.host      :webmaster@zlex.org  
site.name     :   zlex中文网站  
welcome:欢迎您,{0}!  

发现打印的结果一模一样。结论:中间有N个空格,都是无所谓的

头、尾有空格呢?

    logo.location:/image/logo/
  mail.host:webmaster@zlex.org    
site.name:zlex中文网站
welcome:欢迎您,{0}!

头部N个空格都没关系,但是尾部的空格是会当作值的一部分的。这个特别注意,很多人在这里踩过坑,因为这个错误还非常的不好找~

值注入

可以导入配置文件处理器,以后编写配置就有提示

<!--导入配置文件处理器,配置文件进行绑定就会有提示-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>

yaml写法:

person:
  lastName: 王锐
  age: 18
  boss: false
  birth: 2017/12/12
  maps: {k1: v1,k2: v2}
  lists:
    - lisi
    - zhaoliu
  dog:
    name: Tom
    age: 12

property写法:

person.last-name=王锐
person.age=18
person.birth=2017/12/15
person.boss=false
person.maps.k1=v1
person.maps.k2=v2
person.lists=a,b,c
person.dog.name=Tom
person.dog.age=15

@ConfigurationProperties

ConfigurationPropertiesBindingPostProcessor会对标注@ConfigurationProperties注解的Bean进行属性值的配置

@ConfigurationProperties把同类的配置信息自动封装成实体类

  1. 加在类上,和@Component注解结合使用。代码如下

    @Component
    @ConfigurationProperties(prefix = "person")
    public class Person {
      private String lastName;
      private Integer age;
      private Boolean boss;
      private Date birth;
    
      private Map<String,Object> maps;
      private List<Object> lists;
      private Dog dog;
    }
    
    public class Dog {
      private String name;
      private Integer age;
    }
    
  2. 通过@Bean的方式进行声明,加在配置类即可,代码如下

    @Bean
    @ConfigurationProperties(prefix = "person")
    public Person person() {
      return new Person();
    }
    

@Value

@Value注解的注入非常强大,可以借助配置文件的注入、也可以直接注入

${ properties }#{ SpEL }的语法区别

  • ${ property : default_value }
  • #{ obj.property? : default_value } 表示SpEl表达式通常用来获取bean的属性,或者调用bean的某个方法。当然还可以表示常量

二者组合使用:#{ ‘${}’ }

两者结合使用,可以利用SpEL的特性,写出一些较为复杂的表达式,如:

@Value("#{'${os.name}' + '_' +  person.name}")
private String age;  // Windows 10_wangrui
  1. 注入普通字符串

    @Value("true")
    private Boolean boss;
    @Value("normal")
    private String normal;
    
  2. 注入操作系统属性

    @Value("#{systemProperties['os.name']}")
    private String systemPropertiesName; 
    
    @Value("${os.name}")
    private String systemPropertiesName;
    
  3. 注入配置文件值

    @Value("${person.last-name}")
    private String lastName;
    
  4. 注入表达式结果

    @Value("#{11*2}")
    private Integer age;
    
    @Value("#{ T(java.lang.Math).random() * 100.0 }")
    private double randomNumber; //41.29185128620939
    
  5. 注入其它Bean的属性:Person类的name属性

    @Bean
    public Person person() {
      Person person = new Person();
      person.setName("fangshixiang");
      return person;
    }
    
    //注入属性
    @Value("#{person.name}")
    private String personName;
    
    //如果age22这个key根本就不存在,启动肯定会报错的
    @Value("#{person.age22?:20}")
    private Integer age;
    
  6. 直接注入容器内对象

    发现这个很强大,可以直接把容器的里的一个对象直接注入进来。可是一般不这么做

    @Value("#{person}")
    private Person person;
    
  7. 获取级联属性

    @Value("#{person.parent.name}")
    private String parentName1;
    
    @Value("#{person['parent.name']}")
    private String parentName2;
    
  8. 注入文件资源

    在resources下放置一个jdbc.properties配置文件。然后可以直接注入

    @Value("classpath:jdbc.properties")
    private Resource resourceFile; // 注入文件资源
    
  9. 注入Url资源

    @Value("http://www.baidu.com")
    private Resource testUrl;
    

@Value获取值和@ConfigurationProperties获取值比较

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

配置文件注入值数据校验

@Component
@ConfigurationProperties(prefix = "person")
@Validated
public class Person {
  @Email
  private String lastName;
}

@PropertySource&@ImportResource

@PropertySource@ImportResource很多人都用过,但若真拿它两比较,却有点傻傻分不清楚了

他俩都是向容器中导入Bean/属性信息,但是使用起来还是有很大区别的

在讲解之前,可以记住一个通用的的结论:

  1. @PropertySource用于导入.properties的属性配置文件(能导入yaml吗,且继续往下看吧)
  2. @ImportResource用于导入.xml的Bean信息的配置文件(能导入,properties吗,且继续看~)
@PropertySource

此注解也是非常的强大,用好了,可以很好的实现配置文件的分离关注,大大提高开发的效率,实现集中化管理

属性介绍:

  • value:数组。指定配置文件的位置。支持classpath:file:等前缀

    如果是classpath开头最终使用Resource的子类ClassPathResource

    如果是file开头最终使用的类是FileSystemResource

  • ignoreResourceNotFound:默认值false。表示如果没有找到文件就报错,若改为true就不报错。建议保留false

  • encoding:加载进来的编码。一般不用设置,可以设置为UTF-8等等

  • factory:默认的值为DefaultPropertySourceFactory

加载指定的配置文件;

// 加载的就是根路径下的person.properties文件
@PropertySource(value = {"classpath:person.properties"})
@Component
// 这个不能省略,它是用来指定前缀的,只是默认从全局配置文件中取值
@ConfigurationProperties(prefix = "person")
// @Validated
public class Person {
  private String lastName;
  private Integer age;
  private Boolean boss;
  private Date birth;

  private Map<String,Object> maps;
  private List<Object> lists;
  private Dog dog;
}

通过@PropertySource把配置文件加载进来,然后使用@Value获取

@Configuration
@PropertySource("classpath:jdbc.properties")
public class PropertySourceConfig {
  @Value("${db.url}")
  private String dbUrl;
}
多环境配置以及表达式使用(spring.profiles.active)

可以这么配置@PropertySource(“classpath:jdbc-${spring.profiles.active}.properties”) ,程序员在开发时不需要关心生产环境数据库的地址、账号等信息,一次构建即可在不同环境中运行

@ImportResource

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

SpringBoot里面没有Spring的配置文件,自己编写的配置文件,也不能自动识别,想让Spring的配置文件生效、加载进来。需要将@ImportResource标注在一个配置类上

指示包含要导入的bean定义的一个或多个资源。它的功能比较像@Import注解,就是向容器内导入Bean。只是@ImportResource它导入的是一个xml配置文件,然后通过解析xml文件的方式再把解析好的Bean信息导入到Spring容器内

beans.xml文件

<?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.example.demo.service.HelloService"></bean>
</beans>

将它在主配置类上引入或者在配置类上引入

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

@ImportResource(locations = {"classpath:beans.xml"})
@Configuration
public class MyConfig {
}
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBoot02ConfigApplicationTests {
	@Autowired
	ApplicationContext ioc;
	@Test
	public void testHelloService(){
         System.out.println("注入一个组件");
		boolean b = ioc.containsBean("helloService02");
		System.out.println(b);
	}
}

5、配置文件占位符

1、随机数
${random.value}、${random.int}、${random.long}
${random.int(10)}、${random.int[1024,65536]}
2、占位符获取之前配置的值,如果没有可以是用:指定默认值
person.last-name=张三${random.uuid}
person.age=${random.int}
person.birth=2017/12/15
person.boss=false
person.maps.k1=v1
person.maps.k2=14
person.lists=a,b,c
person.dog.name=${person.hello:hello}_dog
person.dog.age=15

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

①笶侕濄

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值