上一节:springboot开发笔记-(7)-Profile多环境配置文件加载


8.1 配置文件的优先级

server.servlet.context-path=/appserver.port=8888spring.config.location=xxx/xxx/application.properties

上面本文中说到"级别高"意思就是会替换其余的, 以它为首选, 它最终会起作用, 其余的会被笼罩;

本节要答复的问题:springboot利用部署后, 配置文件以哪个为准? 如果利用打包成可执行app.jar后有以下这几个配置文件:

  1. jar同目录的 _application.properties_; ->官网称此为: file:./config/
  2. jar同目录的 _config/application.properties_; ->官网称此为: file:./config/
  3. jar外部jar包中的 _classes/application.properties_; ->官网称此为: classpath:/
  4. jar外部jar包中的 _classes/config/application.properties_; ->官网称此为: classpath:/config/
  5. 启动参数时间接笼罩某个单项配置, 比方改端口号: java -jar app.jar --server.port=9999来指定;
  6. 轻易指定一个地址搁置 application.properties , 应用 启动参数spring.config.location=xxx来指定; (留神: 这个配置实测会互补生效--即: 只有它本人起作用)

--let's guess:

咱们先来做一个猜想, 如果是让咱们本人设计, 设想实际上线的场景, 咱们会冀望哪个优先级最高(最终会笼罩其余配置的)?

如果我在线上部署了一个app.jar文件, 执行java -jar app.jar 启动利用; 启动之后线上如果有问题了, 比方端口被占用, 比方数据库配置批改, 我须要马上调整一个参数, 最快的形式是什么?

  1. 首先: 间接重启, java -jar app.jar --some.prop=new_value 必定是这个最快, 或者罗唆本人指定一个配置文件的地址, --参数加命令行前面; (下面5/6)
  2. 除了执行带参数, 不便批改的必定是 jar平级目录下了, 那么, 应该轮到 app.jar平级目录下的配置了:

    是设置哪个级别高呢? 间接读取application.properties? 还是 config/application.properties?

    有的人认为 config很直观, 就把它上面的设为高级别---没错---springboot的设计者就是这类的(下面2);

  3. 当然 紧接着就是平级的了(下面1)
  4. 所以jar包外面的两处, 应该是低级别的了, 依照第2点的逻辑, 应该是 classpath:/config/application.properties 级别高于 classpath:application.properties;

所以咱们就大略进去一个思路, 配置起作用优先级别顺次是:

  1. 启动时指定某些参数

    java -jar app.jar --server.port=9999
  2. 启动时指定配置文件(有坑~)

    java -jar app.jar -spring.config.location=/mydir/application.properties
  3. jar同目录的config/application.properties

    app.jar 同级别目录下的 ./config/application.properties
  4. jar同目录的application.properties

    app.jar同级别目录下的 application.properties
  5. jar外部 classpath目录下的 ./config/application.properties

    app.jar/BOOT-INF/classes/config/application.properties
  6. jar外部classpath目录下的 application.properties

    app.jar/BOOT-INF/classes/application.properties

留神: 2处之所以说有坑是因为:

  1. 其余的配置文件只是优先级不同, 所有的配置文件还都是能够加载互补的, 只是优先级更高的会笼罩优先级低的
  2. 然而2处这个怂配置则不然: 如果你指定了 -spring.config.location=xxx , 你要小心了, 这相当于是个渣男: 他只顾本人, 不和其余的互补, 别的都被忽略了!!!

8.2 配置文件的优先级-代码证实

8.2.1 代码外围文件

  1. idea里新建一个springboot的module: springboot-02-config, 创立了4个配置文件, 配置对应关系如图:

  1. pom.xml

    <?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">    <modelVersion>4.0.0</modelVersion>    <parent>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-parent</artifactId>        <version>2.2.2.RELEASE</version>        <relativePath/> <!-- lookup parent from repository -->    </parent>    <groupId>com.niewj</groupId>    <artifactId>springboot-02-config</artifactId>    <version>0.0.1-SNAPSHOT</version>    <name>springboot-02-config</name>    <description>springboot-2-config</description>    <properties>        <java.version>1.8</java.version>    </properties>    <dependencies>        <dependency>            <groupId>com.google.code.gson</groupId>            <artifactId>gson</artifactId>            <version>2.8.6</version>        </dependency>        <dependency>            <groupId>junit</groupId>            <artifactId>junit</artifactId>            <version>4.10</version>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-web</artifactId>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-configuration-processor</artifactId>            <optional>true</optional>        </dependency>        <dependency>            <groupId>org.projectlombok</groupId>            <artifactId>lombok</artifactId>            <optional>true</optional>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-test</artifactId>            <scope>test</scope>            <exclusions>                <exclusion>                    <groupId>org.junit.vintage</groupId>                    <artifactId>junit-vintage-engine</artifactId>                </exclusion>            </exclusions>        </dependency>    </dependencies>    <build>        <finalName>app</finalName>        <plugins>            <plugin>                <groupId>org.springframework.boot</groupId>                <artifactId>spring-boot-maven-plugin</artifactId>            </plugin>        </plugins>    </build></project>
  2. person.java

    package com.niewj.springboot.model;import lombok.Data;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.stereotype.Component;import java.util.List;/**
*/

@Data
@Component
@ConfigurationProperties(prefix = "person")
public class Person {

   private Integer age;   private String lastName;   private boolean student;   private String location;   private List<String> hobbies;

}

4. controller:

package com.niewj.springboot.controller;

import com.niewj.springboot.model.Person;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**

* Created by niewj on 2020/8/5 23:17*/

@RestController
public class HelloController {

   @Autowired   private Person person;   @RequestMapping("/hello")   public Object hello(){       return person;   }

}

### 8.2.2 执行流程1. 编译打包> mvn clean install -Dmaven.test.skip=true2. 打包后生成一个 `app.jar`可执行文件3. `show in explore` 进入 app.jar所在目录, 咱们抉择把jar包复制到其余目录, 比方: E:/deploy/app.jar4. 目录下`shift+右键->在此处关上命令行窗口`>config(目录下有application.properties)>app.jar>application.properties5. 在命令行`java -jar app.jar`

PS E:deploy> java -jar .app.jar

 .   ____          _            __ _ _/\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \

( ( )__ | ' | '_| | '_ / _` | \

\\/  ___)| |_)| | | | | || (_| |  ) ) ) ) '  |____| .__|_| |_|_| |_\__, | / / / /=========|_|==============|___/=/_/_/_/:: Spring Boot ::        (v2.2.2.RELEASE)

2020-08-06 13:23:53.011 INFO 20304 --- [ main] com.niewj.springboot.ConfigApplication : Starting ConfigApplication v0.0.1-SNAPSHOT on LAPTOP-7EINAF4M with PID 20304 (E:deployapp.jar started by niewj in E:deploy)
2020-08-06 13:23:53.015 INFO 20304 --- [ main] com.niewj.springboot.ConfigApplication : No active profile set, falling back to default profiles: default
2020-08-06 13:23:56.206 INFO 20304 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8004 (http)
2020-08-06 13:23:56.225 INFO 20304 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2020-08-06 13:23:56.226 INFO 20304 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.29]
2020-08-06 13:23:56.343 INFO 20304 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2020-08-06 13:23:56.343 INFO 20304 --- [ main] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 3275 ms
2020-08-06 13:23:56.512 INFO 20304 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
2020-08-06 13:23:56.721 INFO 20304 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8004 (http) with context path ''
2020-08-06 13:23:56.724 INFO 20304 --- [ main] com.niewj.springboot.ConfigApplication : Started ConfigApplication in 4.112 seconds (JVM running for 4.652)

能够看到, 应用的是端口: `8004 `, 再通过 http://localhost:8004/hello 拜访, 显示: 

{"age":30,"lastName":"wj","student":false,"location":"file/config/application.properties","hobbies":["8004","running","coding","cooking"]}

--> 可见起作用的是: `app.jar同目录下的 config/application.properties`6. 咱们删掉这个目录再试一次: 

PS E:deploy> java -jar .app.jar

 .   ____          _            __ _ _/\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \

( ( )__ | ' | '_| | '_ / _` | \

\\/  ___)| |_)| | | | | || (_| |  ) ) ) ) '  |____| .__|_| |_|_| |_\__, | / / / /=========|_|==============|___/=/_/_/_/:: Spring Boot ::        (v2.2.2.RELEASE)

2020-08-06 13:27:45.312 INFO 7716 --- [ main] com.niewj.springboot.ConfigApplication : Starting ConfigApplication v0.0.1-SNAPSHOT on LAPTOP-7EINAF4M with PID 7716 (E:deployapp.jar started by niewj in E:deploy)
2020-08-06 13:27:45.315 INFO 7716 --- [ main] com.niewj.springboot.ConfigApplication : No active profile set, falling back to default profiles: default
2020-08-06 13:27:48.470 INFO 7716 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8003 (http)
2020-08-06 13:27:48.482 INFO 7716 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2020-08-06 13:27:48.483 INFO 7716 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.29]
2020-08-06 13:27:48.591 INFO 7716 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2020-08-06 13:27:48.592 INFO 7716 --- [ main] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 3227 ms
2020-08-06 13:27:48.754 INFO 7716 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
2020-08-06 13:27:48.954 INFO 7716 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8003 (http) with context path ''
2020-08-06 13:27:48.957 INFO 7716 --- [ main] com.niewj.springboot.ConfigApplication : Started ConfigApplication in 4.081 seconds (JVM running for 4.606)

能够看到, 应用的是端口: `8003`, 再通过 http://localhost:8003/hello 拜访, 显示: 

{"age":30,"lastName":"wj","student":false,"location":"file/application.properties","hobbies":["8003","running","coding","cooking"]}

--> 可见起作用的是: `app.jar同目录下的 ./application.properties`7. 删掉./application.properties再试:

PS E:deploy> java -jar .app.jar

 .   ____          _            __ _ _/\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \

( ( )__ | ' | '_| | '_ / _` | \

\\/  ___)| |_)| | | | | || (_| |  ) ) ) ) '  |____| .__|_| |_|_| |_\__, | / / / /=========|_|==============|___/=/_/_/_/:: Spring Boot ::        (v2.2.2.RELEASE)

2020-08-06 13:31:42.852 INFO 3700 --- [ main] com.niewj.springboot.ConfigApplication : Starting ConfigApplication v0.0.1-SNAPSHOT on LAPTOP-7EINAF4M with PID 3700 (E:deployapp.jar started by niewj in E:deploy)
2020-08-06 13:31:42.855 INFO 3700 --- [ main] com.niewj.springboot.ConfigApplication : No active profile set, falling back to default profiles: default
2020-08-06 13:31:46.018 INFO 3700 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8002 (http)
2020-08-06 13:31:46.032 INFO 3700 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2020-08-06 13:31:46.033 INFO 3700 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.29]
2020-08-06 13:31:46.144 INFO 3700 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2020-08-06 13:31:46.145 INFO 3700 --- [ main] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 3239 ms
2020-08-06 13:31:46.306 INFO 3700 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
2020-08-06 13:31:46.509 INFO 3700 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8002 (http) with context path ''
2020-08-06 13:31:46.514 INFO 3700 --- [ main] com.niewj.springboot.ConfigApplication : Started ConfigApplication in 4.051 seconds (JVM running for 4.579)

能够看到, 应用的是端口: `8002`, 再通过 http://localhost:8002/hello 拜访, 显示: 

{"age":30,"lastName":"wj","student":false,"location":"resource/config/application.properties","hobbies":["8002","running","coding","cooking"]}

--> 可见起作用的是: `app.jar包内的classpath目录下的: classpath:config/application.properties`8. 到此就不必再试了, 如果没有config目录, 必定读取的是classpath: application.properties了, 这个咱们平时用的就是它;正好证实了下面的论断.9. 咱们再试试 `spring.config.location`命令行指定配置文件的执行形式: 在桌面上放了一个 application.properties, 内容如下:
  server.port=8333    person.hobbies=8333,running,coding,cooking  person.location=spring.config.location/application.properties    ```
  1. java -jar app.jar --spring.config.location=C:\Users\weiju\Desktop\application.properties

    PS E:\deploy> java -jar app.jar --spring.config.location=C:\Users\weiju\Desktop\application.properties  .   ____          _            __ _ _ /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/  ___)| |_)| | | | | || (_| |  ) ) ) )  '  |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot ::        (v2.2.2.RELEASE)2020-08-06 13:39:40.251  INFO 20548 --- [           main] com.niewj.springboot.ConfigApplication   : Starting ConfigApplication v0.0.1-SNAPSHOT on LAPTOP-7EINAF4M with PID 20548 (E:\deploy\app.jar started by niewj in E:\deploy)2020-08-06 13:39:40.254  INFO 20548 --- [           main] com.niewj.springboot.ConfigApplication   : No active profile set, falling back to default profiles: default2020-08-06 13:39:43.357  INFO 20548 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8333 (http)2020-08-06 13:39:43.368  INFO 20548 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]2020-08-06 13:39:43.368  INFO 20548 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.29]2020-08-06 13:39:43.452  INFO 20548 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext2020-08-06 13:39:43.453  INFO 20548 --- [           main] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 3142 ms2020-08-06 13:39:43.615  INFO 20548 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'2020-08-06 13:39:43.805  INFO 20548 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8333 (http) with context path ''2020-08-06 13:39:43.809  INFO 20548 --- [           main] com.niewj.springboot.ConfigApplication   : Started ConfigApplication in 3.997 seconds (JVM running for 4.531)
    能够看到, 应用的是端口: `8333`, 再通过 http://localhost:8333/hello 拜访, 显示: ```json{"age":null,"lastName":null,"student":false,"location":"spring.config.location/application.properties","hobbies":["8333","running","coding","cooking"]}```--> 同样: 证实了渣男属性 `spring.config.location` : 只顾本人, 他人都摈弃了, 没有了`互补`性能;

须要留神的几点:

  1. 咱们能够看到他们之间除了优先级, 其余的是都加载的, 是互补的关系(命令行带参spring.config.properties除外)
  2. 下面的测试, 除了删除之外, 改名也失效, 名字不是 application.properties/application.yml都不会认的;
  3. 咱们没有试命令行指定某个参数, 比方 java -jar app.jar --server.port=8080 这个; 它是第一优先级!

8.3 官网阐明

4.2.3. Application Property Files


SpringApplication loads properties from application.properties files in the following locations and adds them to the Spring Environment:

  1. A /config subdirectory of the current directory
  2. The current directory
  3. A classpath /config package
  4. The classpath root

The list is ordered by precedence (properties defined in locations higher in the list override those defined in lower locations).

......

Config locations are searched in reverse order. By default, the configured locations are classpath:/,classpath:/config/,file:./,file:./config/*/,file:./config/. The resulting search order is the following:

  1. file:./config/
  2. file:./config/*/
  3. file:./
  4. classpath:/config/
  5. classpath:/

8.4 加载优先级总结(按高到底:)

优先级高的会笼罩低的, 也能够了解他们的加载机会是程序相同的!
  1. 启动时指定某些参数 > java -jar app.jar --server.port=9999
  2. 启动时指定配置文件(有坑:互补生效!)

    java -jar app.jar -spring.config.location=/mydir/application.properties
  3. jar同目录的config/application.properties

    app.jar 同级别目录下的 ./config/application.properties
  4. jar同目录的application.properties

    app.jar同级别目录下的 application.properties
  5. jar外部 classpath目录下的 ./config/application.properties

    app.jar/BOOT-INF/classes/config/application.properties
  6. jar外部classpath目录下的 application.properties

    app.jar/BOOT-INF/classes/application.properties