Spring Boot 2+Thymeleaf企业应用实战
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

3.1 配置文件

Spring Boot会按顺序读取各种配置,例如命令行参数、系统参数等。这一节我们讲述配置文件的读取。新建一个名称为“config-file-test”的Web项目,加入以下依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

对配置文件的测试,会在项目中进行,其只是一个使用Spring Boot构建的Web项目。

3.1.1 默认配置文件

Spring Boot会读取名称为application.properties或者application.yml的文件。在默认情况下,会按照以下顺序读取application.properties(yml)配置文件(如图3-1所示):

1 项目根目录的config目录

2 项目根目录

3 项目classpath下的config目录

4 项目classpath根目录

图3-1 配置文件读取顺序

既然Spring Boot会按顺序读取这4份配置文件,那么如果同一个配置项出现在多份配置文件中,后读取的值是否会覆盖前面读取的值呢?经笔者测试,是不会覆盖的。我们在4份application.yml文件里面,加入测试的配置项:

user:
  test:
    name: 1  # 按读取的顺序来配置属性值

加入的配置项的key为user.test.name,属性值分别是4份配置文件的读取顺序。编写启动类和控制器,读取这个配置项,见代码清单3-1。

代码清单3-1:codes\03\3.1\config-file-test\src\main\java\org\crazyit\boot\FileApp.java

@SpringBootApplication
@RestController
public class FileApp {

    public static void main(String[] args) {
      new SpringApplicationBuilder(FileApp.class).run(args);
    }

    @Autowired
    private Environment env;

    @GetMapping("/ua")
    public String getProp() {
      System.out.println(env.getProperty("user.test.name"));
      return "";
    }
}

代码清单3-1将应用启动类和控制器放到一起,并注入了Environment实例,这是Spring框架的环境类,可以使用它来读取配置项。运行FileApp后,打开浏览器访问http://localhost:8080/ua,可以看到控制台输出为1,这表示config-file-test/config/application.yml(第1顺位的配置文件)的user.test.name属性被读取,其他配置文件的user.test.name属性值并没有覆盖第1顺位配置文件的属性值。

3.1.2 指定配置文件

如果想让Spring Boot加载我们自已的配置文件,则可以在Spring Boot的启动命令中加入参数,见代码清单3-2。

代码清单3-2:codes\03\3.1\config-file-test\src\main\java\org\crazyit\boot\SpecFileApp.java

new SpringApplicationBuilder(SpecFileApp.class)
    .properties(
      "spring.config.location=classpath:/test-folder/my-config.properties")
    .run(args);

启动类在配置SpringApplicationBuilder时,使用了spring.config.location属性来指定配置文件的位置。除了可以指定配置文件的位置外,还可以使用spring.config.name属性来指定配置文件的名称,例如以下代码片断:

new SpringApplicationBuilder(FileName.class).properties(
    "spring.config.name=abc").run(args);

以上代码片断指定了配置文件的名称为abc,那么Spring Boot将会到classpath下寻找abc.properties(.yml)文件。一般情况下我们不需要特别指定配置文件,笔者习惯于在项目的src/main/resources下使用application.properties(.yml)文件来进行配置。

3.1.3 yml文件

YAML语言可使用一种方便的格式进行数据配置,通过配置分层、缩进等格式,来增强配置文件的可读性。使用YAML语言的配置文件以“.yml”作为后缀,代码清单3-3即是一个yml配置文件示例。

代码清单3-3:codes\03\3.1\config-file-test\src\main\resources\my-config.yml

jdbc:
  user:
    root
  passwd:
    123456
  driver:
    com.mysql.jdbc.Driver

需要特别注意的是,每一行配置的缩进要使用空格,不能使用Tab键进行缩进。代码清单3-3对应的properties文件内容如下:

jdbc.user=root
jdbc.passwd=123456
jdbc.driver=com.mysql.jdbc.Driver

注意:如无特别说明,本书的大部分项目会使用yml文件进行配置。

3.1.4 使用profile指定配置

在实际应用中,有时我们可能需要根据特定的环境来激活不同的配置,针对这样的情况,可以考虑使用profile特性。在代码清单3-4的yml文件中定义了两个profile。

代码清单3-4:codes\03\3.1\config-file-test\src\main\resources\test-profile.yml

spring:
  profiles: mysql
jdbc:
  driver:
    com.mysql.jdbc.Driver
---
spring:
  profiles: oracle
jdbc:
  driver:
    oracle.jdbc.driver.OracleDriver

两个profile之间使用“---”进行分隔。接下来,编写启动类来设置激活的profile,见代码清单3-5。

代码清单3-5:codes\03\3.1\config-file-test\src\main\java\org\crazyit\boot\TestProfile.java

@SpringBootApplication
@RestController
public class TestProfile {

    public static void main(String[] args) {
      // 读取控制台输入
      Scanner scan = new Scanner(System.in);
      String profile = scan.nextLine();
      new SpringApplicationBuilder(
              TestProfile.class)
              .properties(
                    "spring.config.location=classpath:/test-profile.yml")
              .profiles(profile).run(args);
    }

    @Autowired
    private Environment env;

    @GetMapping("/tp")
    public String getProp() {
      System.out.println(env.getProperty("jdbc.driver"));
      return "";
    }
}

在代码清单3-5中,先读取控制台的输入,再调用profiles方法来设置需要激活的profile。在启动应用时,在控制台中输入mysql,打开浏览器访问http://localhost:8080/tp,可以看到控制台输出为:com.mysql.jdbc.Driver。除了使用profiles方法外,还可以通过设置spring.profiles.active属性来设置激活的profile,效果与使用profiles方法一致。

除此之外,还可以通过配置文件的名称来设置profile,例如在classpath下有两份文件:application-mysql.yml和application-oracle.yml,这实际上就等于定义了mysql和oracle两个profile。在启动应用时,只需要输入相应的文件名称即可激活它,而且在配置文件中,也不再需要设置spring.profiles属性。