关于springboot:springboot开发笔记8配置文件的加载顺序

37次阅读

共计 13781 个字符,预计需要花费 35 分钟才能阅读完成。

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


8.1 配置文件的优先级

server.servlet.context-path=/app
server.port=8888
spring.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=true

2. 打包后生成一个 `app.jar` 可执行文件

3. `show in explore` 进入 app.jar 所在目录, 咱们抉择把 jar 包复制到其余目录, 比方: E:/deploy/app.jar

4. 目录下 `shift+ 右键 -> 在此处关上命令行窗口 `

>config(目录下有 application.properties)
>app.jar
>application.properties

5. 在命令行 `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: default
    2020-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 WebApplicationContext
    2020-08-06 13:39:43.453  INFO 20548 --- [main] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 3142 ms
    2020-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

正文完
 0