SpringBoot教程&笔记|Demo03-配置文件 有更新!

  heardfate

SpringBoot 是为了简化 Spring 应用的创建、运行、调试、部署等一系列问题而诞生的产物,自动装配的特性让我们可以更好的关注业务本身而不是外部的XML配置,我们只需遵循规范,引入相关的依赖就可以轻易的搭建出一个 WEB 工程

SpringBoot 虽然干掉了 XML 但未做到 零配置,它体现出了一种 约定优于配置,也称作按约定编程,是一种软件设计范式,旨在减少软件开发人员需做决定的数量,获得简单的好处,而又不失灵活性。 一般情况下默认的配置足够满足日常开发所需,但在特殊的情况下,我们往往需要用到自定义属性配置、自定义文件配置、多环境配置、外部命令引导等一系列功能。不用担心,这些 SpringBoot 都替我们考虑好了,我们只需要遵循它的规则配置即可

准备前提

本教程在Demo02基础上添加配置信息

构建项目的时候,自动创建的是application.properties文件,我们重命名改成application.yml

为了让 Spring Boot 更好的生成配置元数据文件,我们需要添加如下依赖(该依赖可以不添加,但是在 IDEA 和 STS 中不会有属性提示,但是引入这个包会有相应提示),该依赖只会在编译时调用,所以不用担心会对生产造成影响…

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

添加依赖

自定义属性配置

application.yml 写入如下配置内容

test:
    age: 22
    name: testUser

自定义属性配置

其次定义 src/main/java/com/heardfate/springboot/demo/properties/MyTestProperties1.java 文件,用来映射我们在 application.yml 中的内容,这样一来我们就可以通过操作对象的方式来获得配置文件的内容了

package com.heardfate.springboot.demo.properties;

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

/**
 * @since: 2018/10/21
 * @author: Mr.HeardFate
 */
@Component
@ConfigurationProperties(prefix = "test")
public class MyTestProperties1 {
 private int age;
 private String name;

 public int getAge() {
     return age;
  }

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

 public String getName() {
     return name;
  }

 public void setName(String name) {
     this.name = name;
  }

 @Override
 public String toString() {
     return "MyTestProperties1{" +
             "age=" + age +
             ", name='" + name + '\'' +
             '}';
  }
}

自定义属性配置

接下来我们通过 HelloController 用来注入 MyTestProperties1 测试我们编写的代码,值得注意的是 Spring4.x 以后,推荐使用构造函数的形式注入属性…

package com.heardfate.springboot.demo.controller;

import com.heardfate.springboot.demo.properties.MyTestProperties1;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @since: 2018/10/18
 * @author: Mr.HeardFate
 */
@RestController
@EnableConfigurationProperties({MyTestProperties1.class})
public class HelloController {
  @Autowired
  private MyTestProperties1 myTestProperties1;

  @RequestMapping("/")
  public String index() {
     return "Greetings from Spring Boot!";
  }

  @RequestMapping("/pro1")
  public MyTestProperties1 myProperties1() {
     System.out.println("=====================MyTestProperties1=====================");
     System.out.println(myTestProperties1.toString());
     System.out.println("=====================MyTestProperties1=====================");
     return myTestProperties1;
  }
}

启动项目,打开浏览器,输入如下地址: http://localhost:8080/pro1,观察控制台,监听到如下内容则表示程序正确

=====================MyTestProperties1=====================
MyTestProperties1{age=22, name='testUser'}
=====================MyTestProperties1=====================

自定义属性配置

自定义文件配置

YML的缺点:不能通过@PropertySource注解加载! 如果需要使用@PropertySource注解的方式加载值,那就要使用properties文件!
YML的缺点:不能通过@PropertySource注解加载! 如果需要使用@PropertySource注解的方式加载值,那就要使用properties文件!
YML的缺点:不能通过@PropertySource注解加载! 如果需要使用@PropertySource注解的方式加载值,那就要使用properties文件!

定义一个名为 testProperties.properties 的资源文件,自定义配置文件的命名不强制 application 开头

com.heardfate.name=heardfate
com.heardfate.age=18
com.heardfate.email=admin@heardfate.com

自定义文件配置

其次定义 src/main/java/com/heardfate/springboot/demo/properties/MyTestProperties2.java 文件,用来映射我们在 testProperties.properties 中的内容。

package com.heardfate.springboot.demo.properties;

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

/**
 * @since: 2018/10/21
 * @author: Mr.HeardFate
 */
@Component
@PropertySource("classpath:testProperties.properties")
@ConfigurationProperties(prefix = "com.heardfate")
public class MyTestProperties2 {
 private int age;
 private String name;
 private String email;

 public int getAge() {
     return age;
  }

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

 public String getName() {
     return name;
  }

 public void setName(String name) {
     this.name = name;
  }

 public String getEmail() {
     return email;
  }

 public void setEmail(String email) {
     this.email = email;
  }

 @Override
 public String toString() {
     return "MyTestProperties2{" +
             "age=" + age +
             ", name='" + name + '\'' +
             ", email='" + email + '\'' +
             '}';
  }
}
![自定义文件配置](https://img.heardfate.com:442/springboot/demo/01/17.jpeg)

接下来在 HelloController 用来注入 MyTestProperties2 测试我们编写的代码

@Autowired
private MyTestProperties2 myTestProperties2;

@RequestMapping("/pro2")
public MyTestProperties2 myProperties2() {
  System.out.println("=====================MyTestProperties2=====================");
  System.out.println(myTestProperties2.toString());
  System.out.println("=====================MyTestProperties2=====================");
  return myTestProperties2;
}

打开浏览器,输入如下地址: http://localhost:8080/pro2,观察控制台,监听到如下内容则表示程序正确

=====================MyTestProperties2=====================
MyTestProperties2{age=18, name='heardfate', email='admin@heardfate.com'}
=====================MyTestProperties2=====================

自定义文件配置

随机值配置

配置文件中${random} 可以用来生成各种不同类型的随机值,从而简化了代码生成的麻烦,例如 生成 int 值、long 值或者 string 字符串。

#随机值
com:
    heardfate:
        random:
		  # 随机字符串
		  secret: ${random.value}
		  # 随机int
		  number: ${random.int}
		  # 随机long
		  bignumber: ${random.long}
		  # UUID值
		  uuid: ${random.uuid}
		  # 10以内的随机数
		  lessThan: ${random.int(10)}
		  # 10-100的随机数
		  inRange: ${random.int[10,100]}
		  # 100-1000的随机数,100前面和1000后面可以是 -,(,[ 等任意字符 int.inRange: ${random.int-100,1000-}
		  inRange2: ${random.int(100,1000)}

随机值配置

其次定义 src/main/java/com/heardfate/springboot/demo/properties/MyTestRandomProperties.java 文件,用来映射我们在 application.ymlcom.heardfate.random的内容。

package com.heardfate.springboot.demo.properties;

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

/**
 * @since: 2018/10/21
 * @author: Mr.HeardFate
 */
@Component
@ConfigurationProperties(prefix = "com.heardfate.random")
public class MyTestRandomProperties {
 // # 随机字符串
 private String secret;
 // # 随机int
 private int number;
 // # 随机long
 private long bignumber;
 // # UUID值
 private String uuid;
 // # 10以内的随机数
 private int lessThan;
 // # 10-100的随机数
 private int inRange;
 // # 100前面和1000后面可以是 -,(,[ 等任意字符 int.inRange: ${random.int-100,1000-}
 private int inRange2;

 public String getSecret() {
     return secret;
  }

 public void setSecret(String secret) {
     this.secret = secret;
  }

 public int getNumber() {
     return number;
  }

 public void setNumber(int number) {
     this.number = number;
  }

 public long getBignumber() {
     return bignumber;
  }

 public void setBignumber(long bignumber) {
     this.bignumber = bignumber;
  }

 public String getUuid() {
     return uuid;
  }

 public void setUuid(String uuid) {
     this.uuid = uuid;
  }

 public int getLessThan() {
     return lessThan;
  }

 public void setLessThan(int lessThan) {
     this.lessThan = lessThan;
  }

 public int getInRange() {
     return inRange;
  }

 public void setInRange(int inRange) {
     this.inRange = inRange;
  }

 public int getInRange2() {
     return inRange2;
  }

 public void setInRange2(int inRange2) {
     this.inRange2 = inRange2;
  }

 @Override
 public String toString() {
     return "MyTestRandomProperties{" +
             "secret='" + secret + '\'' +
             ", number=" + number +
             ", bignumber=" + bignumber +
             ", uuid='" + uuid + '\'' +
             ", lessThan=" + lessThan +
             ", inRange=" + inRange +
             ", inRange2=" + inRange2 +
             '}';
  }
}

随机值配置
接下来在 HelloController 用来注入 myTestRandomProperties 测试我们编写的代码

@Autowired
private MyTestRandomProperties myTestRandomProperties;

@RequestMapping("/random")
public MyTestRandomProperties myTestRandomProperties() {
  System.out.println("=====================MyTestRandomProperties=====================");
  System.out.println(myTestRandomProperties.toString());
  System.out.println("=====================MyTestRandomProperties=====================");
  return myTestRandomProperties;
}

打开浏览器,输入如下地址: http://localhost:8080/random,观察控制台,监听到如下内容则表示程序正确

=====================MyTestRandomProperties=====================
MyTestRandomProperties{secret='3a1720de4c4b2ca95762fa48ccbbdd78', number=19380060, bignumber=-3053795025857769306, uuid='4e440c8c-0e9c-42c6-a445-dc2497d946bb', lessThan=7, inRange=40, inRange2=884}
=====================MyTestRandomProperties=====================

随机值配置

多环境化配置

在真实的应用中,常常会有多个环境(如:开发,测试,生产等),不同的环境数据库连接都不一样,这个时候就需要用到spring.profile.active 的强大功能了,它的格式为 application-{profile}.properties,这里的 application 为前缀不能改,{profile} 是我们自己定义的。

创建 application-dev.ymlapplication-test.ymlapplication-prod.yml,内容分别如下

application-dev.yml

server:
  port: 8082

application-test.yml

server:
  port: 8083

application-prod.yml

server:
  port: 8084

多环境化配置

application.yml 配置文件中写入

spring:
    profiles:
        active: dev

这个时候我们再次访问 http://localhost:8080/pro1 就没用了,因为我们设置了它的server: port: 8082,所以新的端口是8082,新的访问路径:http://localhost:8082/pro1由此可以看出我们激活不同的配置读取的端口或属性值是不一样的
多环境化配置

外部命令引导

前面三种方式都是基于配置文件层面的,那么有没有办法外部引导呢,假设这样的场景,我们对已经开发完成的代码打包发布,期间在测试环境测试通过了,那么即可发布上生产,这个时候是修改application.properties的配置方便还是直接在命令参数配置方便呢,毫无疑问是后者更有说服力。默认情况下,SpringApplication 会将命令行选项参数(即:–property,如–server.port=9000)添加到Environment,命令行属性始终优先于其他属性源。

如何测试?

  • 通过IDEA打包项目,双击package即可
    外部命令引导

  • 打包完毕后进入到:~/IdeaProjects/springboot-demo/demo01/target 目录中去,我们可以发现一个名为 demo01-0.0.1-SNAPSHOT.jar 的包

  • 接着在打开 命令行 程序,输入:java -jar demo01-0.0.1-SNAPSHOT.jar --spring.profiles.active=test --test.age=12。仔细观察**spring.profiles.active=testtest.age=12** 这俩配置的键值是不是似曾相识(不认识的请从开头认真阅读)
    外部命令引导
  • 最后输入测试地址:http://localhost:8083/pro1 我们可以发现打印的变成了 MyTestProperties1{age=12, name='testUser'}
    外部命令引导

配置文件的优先级

application.properties和application.yml文件可以放在一下四个位置:

  • 外置,在相对于应用程序运行目录的/congfig子目录里。
  • 外置,在应用程序运行的目录里
  • 内置,在config包内
  • 内置,在Classpath根目录

同样,这个列表按照优先级排序,也就是说,src/main/resources/config下application.properties覆盖src/main/resources下application.properties中相同的属性,如图:
配置文件的优先级

此外,如果你在相同优先级位置同时有application.properties和application.yml,那么application.yml里面的属性就会覆盖application.properties里的属性。