配置引用

@ConfigurationProperties

Spring Boot 通过 ConfigurationProperties 注解从配置文件中获取属性,可以通过设置 prefix 指定需要批量导入的数据。支持获取字面值,集合,Map,对象等复杂数据。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方法
}

配置文件占位符

在 application.properties 中的各个参数之间,我们也可以直接通过使用 PlaceHolder 的方式来进行引用,就像下面的设置:

book.name=SpringCloud
book.author=Test
book.desc=${book.author}  is writing《${book.name}》

在一些特殊情况下,有些参数我们希望它每次加载的时候不是一个固定的值,比如:密钥、服务端口等。在 Spring Boot 的属性配置文件中,我们可以通过使用 ${random}配置来产生随机的 int 值、long 值或者 string 字符串,这样我们就可以容易的通过配置来属性的随机生成,而不是在程序中通过编码来实现这些逻辑。

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为完整路径}

其对应的 Java 代码类似于:

/**
 * 随机数和占位符语法类
 */
@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
}

属性校验

@ConfigurationProperties 使用 JSR-303 格式提供属性验证。这允许各种各样的事情,例如,让 hostName 属性成为强制性的:

@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

Value 注解的优缺点与 @ConfigurationProperties 正好相反,它只能一个个配置注入值;不支持数组、集合等复杂的数据类型;不支持数据校验;对属性名匹配有严格的要求。最大的特点是支持 SpEL 表达式,使其拥有更丰富的功能。@Value 的使用方式,对于如下的 YAML 定义文件:

wx:
  nick-name: wx
  email: aa@aa
  iphone: 1234567890
  abilities: [java, sql, html]
  created_date: 2010/03/31 15:27:30

其对应的 Java 类使用如下:

/**
 * 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

@PropertySource 注解,用于代替 <context:property-placeholader/> 配置,加载 properties 配置文件。有时候我们需要去加载非默认的 profile 文件中的属性,此时就可以用 @PropertySource 将配置文件加载到上下文中,并且通过 @Value 进行注入:

@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

在 Spring Boot 2.0 中增加了新的绑定 API 来帮助我们更容易的获取配置信息。假设在 propertes 配置中有这样一个配置:wx.foo=bar。我们为它创建对应的配置类:

@Data
@ConfigurationProperties(prefix = "wx")
public class FooProperties {
  private String foo;
}

接下来,通过最新的 Binder 就可以这样来拿配置信息了:

@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());
  }
}

对于复杂的 List 类型:

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);
上一页