配置引用
@ConfigurationProperties
- 可以从配置文件中批量注入属性;
- 支持获取复杂的数据类型;
- 对属性名匹配的要求较低,比如
user-name ,user_name,userName,USER_NAME 都可以取值; - 支持
Java 的JSR303 数据校验; - 缺点是不支持强大的
SpEL 表达式;
Properties
/**
* 用户信息
* @ConfigurationProperties : 被修饰类中的所有属性会和配置文件中的指定值(该值通过prefix找到)进行绑定
*/
@Component
@ConfigurationProperties(prefix = "userInfo")
public class UserInfo {
private String account;
private Integer age;
private Boolean active;
private Date createdDate;
private Map<String, Object> map;
private List<Object> list;
private Position position;
// 省略getter,setter,toString方法
}
配置文件占位符
在
book.name=SpringCloud
book.author=Test
book.desc=${book.author} is writing《${book.name}》
在一些特殊情况下,有些参数我们希望它每次加载的时候不是一个固定的值,比如:密钥、服务端口等。在
ran: # 这里的prefix不能是random,
ran-value: ${random.value}
ran-int: ${random.int}
ran-long: ${random.long}
ran-int-num: ${random.int(10)}
ran-int-range: ${random.int[10,20]}
ran-placeholder: placeholder_${ran.ran-value:此处不能有空格,且key为完整路径}
其对应的
/**
* 随机数和占位符语法类
*/
@Component
@ConfigurationProperties(prefix = "ran")
public class RandomEntity {
private String ranValue; // 随机生成一个字符串
private Integer ranInt; // 随机生成一个整数
private Long ranLong; // 随机生成一个长整数
private Integer ranIntNum; // 在指定范围内随机生成一个整数
private Integer ranIntRange; // 在指定区间内随机生成一个整数
private String ranPlaceholder; // 占位符
// 省略getter,setter,toString方法e
}
属性校验
@NotBlank
private String hostName;
@Length(max = 4, min = 1)
private String authMethod;
@Min(1025)
@Max(65536)
private int port;
@Pattern(regexp = "^[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,6}$")
private String from;
@Value
wx:
nick-name: wx
email: aa@aa
iphone: 1234567890
abilities: [java, sql, html]
created_date: 2010/03/31 15:27:30
其对应的
/**
* Value 注解语法类
* 第一步:在属性上添加注解Value注入参数
* 第二步:把Value注解修饰的类添加到Spring的IOC容器中;
* 第三步:添加数据校验注解,检查是否支持数据校验;
*
* 注意点:
* 一、nickName 和 createdDate 在 yml 配置文件中,对应参数分别是中划线和下划线,用于测试其对属性名匹配的松散性
* 二、email和iphone 测试其支持JSR303数据校验
* 三、abilities 测试其支持复杂的数据结构
*
* 结论:
* 一、createDate取值必须和yml配置文件中的参数保持一致,
* 二、既是在iphone上添加邮箱验证注解依然可以通过测试,
* 三、不支持复杂的数据结构,提示错误和第一条相同:IllegalArgumentException: Could not resolve placeholder 'wx.abilities' in value "${wx.abilities}"
*/
@Component
@Validated
public class ValueEntity {
@Value("${wx.nick-name}")
private String nickName;
@Value("${wx.email}")
private String email;
@Email
@Value("${wx.iphone}") // 解析成功,并不支持数据校验
private String iphone;
// @Value("${wx.abilities}") // 解析错误,并不支持复杂的数据结构
private List<String> abilities;
// @Value("${wx.ceatredDate}") // 解析错误,并不支持松散匹配属性,必须严格一致
private Date createdDate;
// Value注解的强大一面:支持SpEL表达式
@Value("#{(1+2-3)/4*5}") // 算术运算
private String operator;
@Value("#{1>2 || 2 <= 3}") // 关系运算
private Boolean comparison;
@Value("#{systemProperties['java.version']}") // 系统配置:os.name
private String systemProperties;
@Value("#{T(java.lang.Math).abs(-18)}") // 表达式
private String mapExpression;
// 省略getter,setter,toString方法
}
@PropertySource
<context:property-placeholader/>
配置,加载
@PropertySource("classpath:foo.properties")
@PropertySource("classpath:bar.properties")
public class PropertiesWithJavaConfig {
//...
}
@PropertySources({
@PropertySource("classpath:foo.properties"),
@PropertySource("classpath:bar.properties")
})
public class PropertiesWithJavaConfig {
//...
}
@Value( "${jdbc.url}" )
private String jdbcUrl;
@Value( "${jdbc.url:aDefaultUrl}" )
private String jdbcUrl;
Binder
在wx.foo=bar
。我们为它创建对应的配置类:
@Data
@ConfigurationProperties(prefix = "wx")
public class FooProperties {
private String foo;
}
接下来,通过最新的
@SpringBootApplication
public class Application {
public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(Application.class, args);
Binder binder = Binder.get(context.getEnvironment());
// 绑定简单配置
FooProperties foo = binder
.bind("wx", Bindable.of(FooProperties.class))
.get();
System.out.println(foo.getFoo());
}
}
对于复杂的
wx.post[0]=Why Spring Boot
wx.post[1]=Why Spring Cloud
wx.posts[0].title=Why Spring Boot
wx.posts[0].content=It is perfect!
wx.posts[1].title=Why Spring Cloud
wx.posts[1].content=It is perfect too!
要获取这些配置依然很简单,可以这样实现:
ApplicationContext context = SpringApplication.run(Application.class, args);
Binder binder = Binder.get(context.getEnvironment());
// 绑定List配置
List<String> post = binder.bind("wx.post", Bindable.listOf(String.class)).get();
System.out.println(post);
List<PostInfo> posts = binder.bind("wx.posts", Bindable.listOf(PostInfo.class)).get();
System.out.println(posts);