您的位置:首页 > 编程语言 > Java开发

spring boot 配置文件properties,yml语法学习及属性获取@ConfigurationProperties和@Value

2019-03-29 13:47 841 查看

1 概述
SpringBoot使用一个全局的配置文件,配置文件名是固定的;当我们创建一个项目时会在resource目录下出现一个默认的配置文件application.properties 我们可以在里面进行一些参数的配置,当然还有另外一种方式yml文件application.yml(YAML Ain’t Markup Language),他们之间写法不同,作用都是一样的,下面我们就来进行学习,可以根据自己的爱好进行选择。

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

我们写一个简单的例子看看它们之间的区别:配置端口号

  • application.properties
[code]server.port=8081
  • application.yaml
[code]server:
port: 8081
  • 以前的xml呢?
[code]<server>
<port>8081</port>
</server>

以前的配置文件;大多都使用的是 xxxx.xml文件;而YAML:以数据为中心,比json、xml等更适合做配置文件;但是刚开始使用的时候一定要注意语法问题,一不小心少个空格就会报错哈。

 

2 YML语法

1、基本语法

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

空格的缩进来控制层级关系;只要是左对齐的一列数据,都是同一个层级的,空格可以是一个或者多个,但是同一层级一定要对齐。

[code]server:
port: 8081
path: /hello

属性和值也是大小写敏感;

2、值的写法
字面量:普通的值(数字,字符串,布尔)
​    k: v:字面直接来写;

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

“”:双引号;不会转义字符串里面的特殊字符;特殊字符会作为本身想表示的意思
​name: “zhangsan \n lisi”:输出;zhangsan 换行 lisi

‘’:单引号;会转义特殊字符,特殊字符最终只是一个普通的字符串数据
name: ‘zhangsan \n lisi’:输出;zhangsan \n lisi

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

​    对象还是k: v的方式

[code]friends:
name: zhangsan
age: 20

行内写法:

[code]friends: {name: zhangsan,age: 18}

数组(List、Set):

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

[code]pets:
- cat
- dog
- pig

行内写法

[code]pets: [cat,dog,pig]

3 通过配置文件注入属性 @ConfigurationProperties

  • person实体类
[code]package cn.zhangyu.bean;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;

/**
* 将配置文件中配置的每一个属性的值,映射到这个组件中
* @ConfigurationProperties:告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定;
*      prefix = "person":配置文件中哪个下面的所有属性进行一一映射
*
* 只有这个组件是容器中的组件,才能容器提供的@ConfigurationProperties功能;
* 所以配置@Component注解
*/
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
//人的属性
private String name;

private int age;

private String sex;

//map
private Map<String , Object> maps;

//list
private List<Dog> list;

private Dog dog;

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

public String getSex() {
return sex;
}

public void setSex(String sex) {
this.sex = sex;
}

public Map<String, Object> getMaps() {
return maps;
}

public void setMaps(Map<String, Object> maps) {
this.maps = maps;
}

public List<Dog> getList() {
return list;
}

public void setList(List<Dog> list) {
this.list = list;
}

public Dog getDog() {
return dog;
}

public void setDog(Dog dog) {
this.dog = dog;
}

@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", sex='" + sex + '\'' +
", maps=" + maps +
", list=" + list +
", dog=" + dog +
'}';
}
}
  • Dog实体类
[code]package cn.zhangyu.bean;

public class Dog {

private String name;

private int 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;
}

@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
  • yml配置属性
[code]person:
name: zhangsan
age: 20
sex: male
maps: {k1: v1,k2: v2}
list:
- {name: 小黑, age: 22}
- name: 小白
- age: 33
dog:
name: 大黄
age: 12
  • 下面通过test类进行测试结果
[code]package cn.zhangyu;

import cn.zhangyu.bean.Person;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class Springboot1ApplicationTests {

@Autowired
private Person person;

@Test
public void contextLoads() {
System.out.println(person);
}

}

结果 :

[code]Person{name='zhangsan', age=20, sex='male', maps={k1=v1, k2=v2}, list=[Dog{name='小黑', age=22}, Dog{name='小白', age=0}, Dog{name='null', age=33}], dog=Dog{name='大黄', age=12}}

其中list中放入的是dog类,我们看看结果是什么样的:list张放入了三只狗,dog中如果有多个属性就要用{ }括起来。

  • properties配置文件
[code]person.name=小明
person.age=20
person.sex=male

person.maps.k1=v1
person.maps.k2=v2

person.list[0].name=小顾
person.list[0].age=22

person.list[1].name=旺财
person.list[1].age=10

person.dog.name=旺旺
person.dog.age=30

 

  • 结果:
[code]Person{name='小明', age=20, sex='male', maps={k1=v1, k2=v2}, list=[Dog{name='小顾', age=22}, Dog{name='旺财', age=10}], dog=Dog{name='旺旺', age=30}}

注意: 这里大家可能出现乱码问题因为properties配置文件在idea中默认utf-8可能会乱码,但是我们idea的默认设置是gbk,所以要进行修改,如下图所示:

3 @Value 属性注入

我们写个简单的controller进行测试@Value属性,@Value属性可以说增加了属性注入的灵活性可以单个属性进行配置。

  • HelloController
[code]package cn.zhangyu.bean.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

@Value("${person.name}")
//@Value("#{person.name}")
private String name;

//计算表达式
@Value("#{11*2}")
private int age;

//引入一个对象
@Value("#{person}")
private Person person;

@RequestMapping(method = RequestMethod.GET ,path = "/sayHello")
public String sayHello(){
return "hello "+ name+" 我的年龄是: "+age+"\n" + person;
}
}

 

  • yml中加一个name属性
[code]person.name: 小雨

看看结果
访问页面http://localhost:8081/sayHello我这里端口号配置的是8081
结果:hello 小明 我的年龄是: 22
这里@Value注解是支持SpEL的。

什么是SpEL?
Spring 表达式语言(简称SpEL):是一个支持运行时查询和操作对象图的强大的表达式语言。

语法类似于 EL:SpEL 使用 #{…} 作为定界符 , 所有在大括号中的字符都将被认为是 SpEL , SpEL 为 bean 的属性进行动态赋值提供了便利。

通过 SpEL 可以实现:

[code]通过 bean 的 id 对 bean 进行引用。
调用方式以及引用对象中的属性。
计算表达式的值
正则表达式的匹配。

1SpEL 实现:

[code]整数:#{8}
小数:#{8.8}
科学计数法:#{1e4}
String:可以使用单引号或者双引号作为字符串的定界符号。
Boolean:#{true}
SpEL引用bean , 属性和方法:

引用其他对象:#{car}
引用其他对象的属性:#{car.brand}
调用其它方法 , 还可以链式操作:#{car.toString()}
调用静态方法静态属性:#{T(java.lang.Math).PI}
SpEL支持的运算符号:

算术运算符:+,-,*,/,%,^(加号还可以用作字符串连接)
比较运算符:< , > , == , >= , <= , lt , gt , eg , le , ge
逻辑运算符:and , or , not , |
if-else 运算符(类似三目运算符):?:(temary), ?:(Elvis)
正则表达式:#{admin.email matches '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,4}'}

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

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

 

松散绑定 :如果使用@ConfigurationProperties注解一个类其中一个属性为

private String myName;

我们通过yml进行配置如果我写成这样是否可以呢?

[code]person:
my-name: zhangsan

答案是可以的,这就是松散绑定 ,我可以写成my-name也可以myName
@ConfigurationProperties支持而@Vlaue不支持

JSR303数据校验:
通过一个例子来看看什么是JSR303数据校验

我们在person类中加入:@Validated和@Email两个注解

[code]package cn.zhangyu.bean;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;

import javax.validation.constraints.Email;
import java.util.List;
import java.util.Map;

@Component
@ConfigurationProperties(prefix = "person")
@Validated
public class Person {
//人的属性
@Email
private String myName;

private int age;

private String sex;

//map
private Map<String , Object> maps;

//list
private List<Dog> list;

private Dog dog;

public String getMyName() {
return myName;
}

public void setMyName(String myName) {
this.myName = myName;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public String getSex() {
return sex;
}

public void setSex(String sex) {
this.sex = sex;
}

public Map<String, Object> getMaps() {
return maps;
}

public void setMaps(Map<String, Object> maps) {
this.maps = maps;
}

public List<Dog> getList() {
return list;
}

public void setList(List<Dog> list) {
this.list = list;
}

public Dog getDog() {
return dog;
}

public void setDog(Dog dog) {
this.dog = dog;
}

@Override
public String toString() {
return "Person{" +
"myName='" + myName + '\'' +
", age=" + age +
", sex='" + sex + '\'' +
", maps=" + maps +
", list=" + list +
", dog=" + dog +
'}';
}
}

启动后发现报错:
 

[code]Binding to target org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'person' to cn.zhangyu.bean.Person failed:

Property: person.myName
Value: zhangsan
Origin: class path resource [application.yml]:6:12
Reason: 不是一个合法的电子邮件地址

这也就是JSR303数据校验。填写正确的电子邮件。而@Vlaue是不支持的。

复杂类型:
我们上面知道了@ConfigurationProperties是支持复杂类型的list、map等。 现在我们测试@Value是否支持

[code]@Value("${person.maps}")
private Map<String , Object> maps;

把person中map属性加上@Value注解启动发现报错;
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'person.maps' in value "${person.maps}".
所以@ConfigurationProperties是支持复杂类型的list、map等而@Value是不支持的,这是非常重要的一点。*
 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐