精通Spring Boot 3 : Spring Boot 的内部机制 (3)
myzbx 2025-01-09 14:47 54 浏览
Spring Boot 的特点
现在,让我们通过使用我们的 My Retro App 项目来探索一些 Spring Boot 的功能。如果你查看主类,会发现 SpringApplication.run 方法。这个方法可以通过不同的方式进行实例化,以便利用其他功能;请参考列表 2-7。
package com.apress.myretro;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MyretroApplication {
    public static void main(String[] args) {
        SpringApplication sa = new SpringApplication(MyretroApplication.class);
                  // Spring Application features ...
                  sa.run(args);
    }
}列表 2-7 源代码:src/main/java/com/apress/myretro/MyretroApplication.java
列表 2-7 展示了与列表 2-2 之间的小修改。在这里,我们没有使用静态的 run(...args)方法调用。如果你查看 SpringApplication 类提供的选项(通过在 IDE 中输入实例变量 sa.并使用代码补全功能),你会看到一个与图 2-7 中所示(部分)相似的列表。
图 2-7 展示了 SpringApplication 实例变量的代码补全。接下来的部分将介绍一些您可以为 Spring Boot 应用程序添加的常见功能。
自定义广告横幅
当您启动应用程序时,会显示一个横幅。默认情况下是 Spring Boot 的 ASCII 艺术。请参见图 2-8。
在 SpringApplication 类中,您可以通过多种方式添加自定义横幅。您可以按照清单 2-8 中的示例以编程方式实现。
package com.apress.myretro;
import org.springframework.boot.Banner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.core.env.Environment;
import java.io.PrintStream;
@SpringBootApplication
public class MyretroApplication {
    public static void main(String[] args) {
        SpringApplication sa = new SpringApplication(MyretroApplication.class);
        sa.setBanner(new Banner() {
                    @Override
                    public void printBanner(Environment environment, Class<?> sourceClass, PrintStream out) {
                        out.println("\n\n\tThis is my custom Banner!\n\n".toUpperCase());
            }
        });
        sa.run(args);
    }
}列表 2-8 源代码:src/main/java/com/apress/myretro/MyretroApplication.java
列表 2-8 展示了如何通过调用 setBanner(Banner)方法来实现自定义横幅。如果您运行这个程序,您将看到类似于图 2-9 的内容。
另一种创建自定义横幅的方法是使用 ASCII 艺术。有一些网站可以为您生成这些艺术作品。例如,您可以访问 https://www.patorjk.com,向下滚动页面,点击“文本转 ASCII 艺术生成器”链接,然后输入“我的复古”。图 2-10 展示了选择不同字体时文本的效果。
您可以浏览和尝试各种字体,选择您喜欢的字体。点击“选择并复制”按钮。接下来,您需要在 src/main/resources 目录下创建一个 banner.txt 文件,并粘贴 ASCII 艺术。图 2-11 显示了 banner.txt 文件及其 ASCII 艺术。
还要注意在图 2-11 中,我们在我的复古应用程序中添加了一个标题${spring-boot.version}。这是一个在运行时设置的全局属性,它将显示所使用的 Spring Boot 版本。如果您运行我的复古应用程序,您应该会看到与图 2-12 中所示的结果相同。
默认情况下,Spring Boot 会在资源文件夹中查找 banner.txt 文件,但您可以指定其他位置或文件扩展名。例如,您可以创建 src/main/resources/META-INF 文件夹并添加 banner.txt 文件。请参见图 2-13。
要使这项工作正常进行,您需要使用 spring.banner.location 属性。如果您想在 IDE 中使用它,您需要了解如何覆盖 Spring Boot 的配置属性。如果您使用的是 IntelliJ IDEA,请选择“编辑配置” ? “修改选项”,找到“覆盖配置属性”部分,并添加 spring.banner.location 和 classpath:/META-INF/banner.txt,如图 2-14 所示。
如果您使用 VS Code,您需要修改 launch.json 文件,并添加 env 键,值为 spring.banner.location 和 classpath:/META-INF/banner.txt。请参见图 2-15。
如果您希望通过命令行运行应用程序,请在 build.gradle 文件的末尾添加以下代码片段:
bootRun {
    systemProperties = System.properties
}然后你可以执行以下命令,期待得到与图 2-12 中相同的结果:
./gradlew bootRun -Dspring.banner.location=classpath:/META-INF/banner.txt正如你所看到的,有多种方式可以配置这些功能。如果你完全不需要横幅,可以使用如清单 2-9 所示的 setBanner(Mode)方法。
package com.apress.myretro;
import org.springframework.boot.Banner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.core.env.Environment;
import java.io.PrintStream;
@SpringBootApplication
public class MyretroApplication {
    public static void main(String[] args) {
        SpringApplication sa = new SpringApplication(MyretroApplication.class);
        sa.setBannerMode(Banner.Mode.OFF);
        sa.run(args);
    }
}列表 2-9 源代码:src/main/java/com/apress/myretro/MyretroApplication.java
Spring 应用程序构建器
Spring Boot 提供了一个流畅的构建器 API,允许您配置应用程序。该 API 引入了 ApplicationContext(来自 Spring 框架),使您的应用程序更加灵活可定制。列表 2-10 展示了 SpringApplicationBuilder 类,您可以在其中自定义应用程序的启动过程。
package com.apress.myretro;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.Banner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import java.io.PrintStream;
@SpringBootApplication
public class MyretroApplication {
    static Logger  log = LoggerFactory.getLogger(MyretroApplication.class);
    public static void main(String[] args) {
        new SpringApplicationBuilder()
                    .sources(MyretroApplication.class)
                    .logStartupInfo(false)
                    .bannerMode(Banner.Mode.OFF)
                    .lazyInitialization(true)
                    .web(WebApplicationType.NONE)
                    .profiles("cloud")
                    .listeners(event -> log.info("Event: {}",event.getClass().getCanonicalName()))
                    .run(args);
    }
}列表 2-10 源代码:src/main/java/com/apress/myretro/MyretroApplication.java
让我们来分析一下列表 2-10 中展示的代码:
- .sources(Class...): 这个方法是您添加应用程序所需的所有配置类和组件的地方。请记住,这些类需要标记为@Configuration,或者使用其他 Spring 相关的注解,如@Component、@Service、@Repository 等。
- .logStartup(boolean): 此方法会将所有启动相关的日志信息输出到控制台。它接受一个布尔值,如果您将其设置为 false,您将看不到任何信息(或者只会看到您自己的日志,如果有的话)。
- .bannerMode(模式):此方法接受一个模式参数,用于控制横幅的显示与否。可选值包括 Banner.Mode.OFF(禁用横幅打印)、Banner.Mode.CONSOLE(将横幅打印到 System.out)和 Banner.Mode.LOG(将横幅打印到日志文件)。
- .lazyInitialization(boolean):此方法接受一个布尔值,默认值为 false。如果设置为 true,则在需要该 bean 之前不会进行创建。
- .web(WebApplicationType): 此方法定义了 web 应用程序的类型。可选值包括 WebApplicationType.NONE(表示应用程序不应作为 web 应用程序运行,也不应启动嵌入式 web 服务器)、WebApplicationType.SERVLET(表示应用程序应作为基于 servlet 的 web 应用程序运行,并启动嵌入式 servlet web 服务器;如果您将 spring-boot-starter-web 作为依赖项/类路径,则此项为真),以及 WebApplicationType.REACTIVE(表示应用程序应作为反应式 web 应用程序运行,并启动嵌入式反应式 web 服务器,您需要将 spring-boot-starter-webflux 作为依赖项/类路径)。
- .profiles(String...): 此方法列出可用的 Spring 配置文件。在运行应用程序时,您应该会看到输出“当前活动的配置文件为:‘cloud’”。(本章最后部分将详细讨论应用程序配置文件。)
- .listeners(ApplicationListener...): 这个方法让您可以定义 Spring 事件。在我的复古应用程序中,我们监听所有 ApplicationListener 接口的实现,因此如果您运行该应用程序,您应该会看到如下输出:
Event: o.s.boot.context.event.ApplicationPreparedEvent
Event: o.s.context.event.ContextRefreshedEvent
Event: o.s.boot.context.event.ApplicationStartedEvent
Event: o.s.boot.availability.AvailabilityChangeEvent
Event: o.s.boot.context.event.ApplicationReadyEvent
Event: o.s.boot.availability.AvailabilityChangeEvent
Event: o.s.context.event.ContextClosedEvent运行(String...): 这个方法允许您传递任何参数,正如您在本章前面看到的。如果您仍在使用 META-INF/banner.txt,并且横幅模式设置为 Banner.Mode.Console,您可以将以下内容添加到 args 中:
.run("--spring.banner.location=classpath:/META-INF/banner.txt");应用程序的参数
在任何 Java 应用中,您都可以将有用的参数传递给主类,Spring Boot 会通过提供 ApplicationArguments 接口来帮助您访问这些参数。让我们来看看如何使用它。
在 myretro 包中创建一个名为 MyRetroConfiguration 的新类。请参阅列表 2-11。
package com.apress.myretro;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.ApplicationArguments;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyRetroConfiguration {
    Logger log = LoggerFactory.getLogger(MyretroApplication.class);
    MyRetroConfiguration(ApplicationArguments arguments){
            log.info("Option Arg Values: {}", arguments.getOptionValues("option"));
    }
}列表 2-11 源代码:src/main/java/com/apress/myretro/MyRetroConfiguration.java
在 MyRetroConfiguration 类中,我们将使用并传递以下参数:
--enable --remote --option=value1 --option=value2 update upgrade
Option Args: [enable, remote, option]
Option Arg Values: [value1, value2]
Option: [update, upgrade]让我们来分析一下列表 2-11 中的代码及其结果:
- @Configuration: 自动配置会识别此注解,评估其内容,并确定(在此情况下)它有一个使用 ApplicationArguments 接口作为参数的构造函数。这个参数会在 Spring 应用程序生命周期中自动注入;在这种情况下,它会传递在主类中 .run(args) 方法调用时声明的 args。ApplicationArguments 接口提供了多种方法,可以帮助识别所有参数,包括带值的选项(用 -- 和 = 及其值表示)以及仅称为非选项参数的参数。
- getOptionNames() 方法将获取所有通过 --<参数名称> 指定的选项。在这个例子中,这些选项是 enable、remote 和 option。
- getOptionValues(String) 方法接受一个参数名称,该名称可以有一个或多个值,格式为 --=。在这个例子中,我们查找名为 option 的参数及其值,结果是 value1 和 value2(因为它出现了多次)。
- getNonOptionArgs() 方法用于获取所有未用 -- 标记的参数(即仅常规参数)。在这个例子中,这些参数是 update 和 upgrade。
可执行的 JAR 文件
这个功能与您选择的任何依赖管理工具(如 Maven 或 Gradle)的 Spring Boot 插件更为相关。本书假设使用 Gradle。要在 build/libs 目录中创建可执行的 JAR,请运行以下命令:
./gradlew build然后,你可以使用它来运行
java -jar build/libs/myretro-0.0.1-SNAPSHOT.jar如果您想向您的 JAR 传递一些参数,可以执行以下命令:
java -jar build/libs/myretro-0.0.1-SNAPSHOT.jar --enable --remote --option=value1 --option=value2 update upgrade你应该得到与之前相同的结果。
应用程序运行器、命令行运行器与应用程序准备就绪事件
作为开发者,我们需要在应用程序准备好接受任何请求或其他交互之前,启动一个过程或执行某些逻辑。Spring Boot 提供了多个接口和事件,允许我们在应用程序准备就绪之前执行代码。您可以将列表 2-12 中的代码添加到 MyRetroConfiguration 类中。
package com.apress.myretro;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Arrays;
@Configuration
public class MyRetroConfiguration {
    Logger log = LoggerFactory.getLogger(MyretroApplication.class);
@Bean
        CommandLineRunner commandLineRunner(){
                return args -> {
                        log.info("[CLR] Args: {}",Arrays.toString(args));
                };
        }
        @Bean
        ApplicationRunner applicationRunner(){
            return args -> {
                    log.info("[AR] Option Args: {}", args.getOptionNames());
                    log.info("[AR] Option Arg Values: {}", args.getOptionValues("option"));
                    log.info("[AR] Non Option: {}",args.getNonOptionArgs());
            };
    }
    @Bean
    ApplicationListener<ApplicationReadyEvent> applicationReadyEventApplicationListener(){
            return event -> {
                    log.info("[AL] Im ready to interact...");
            };
    }
}列表 2-12 源代码:src/main/java/com/apress/myretro/MyRetroConfiguration.java
正如您所看到的,我们已经去掉了构造函数,因为 ApplicationRunner 接口已经提供了应用程序参数。请注意,现在有一些方法被标记为 @Bean 注解,Spring Boot 的自动配置将利用这些方法来创建所需的 Spring bean。让我们来回顾一下代码。
- CommandLineRunner:这个接口的实现将在 Spring 和 Spring Boot 完成所有配置后被调用。它是一个功能接口,包含一个回调(run 方法),用于接收传递给应用程序的参数。在这种情况下,结果是所有的参数。
- 应用程序运行器:此接口的实现将在命令行运行器的实现之前被调用。它是一个函数式接口,包含一个回调(运行方法),该方法以应用程序参数作为参数,因此如果我们想使用这些参数,它是一个很好的选择。
- 应用监听器: 当 Spring Boot 应用程序完成所有配置并准备好进行交互时,将触发此事件。因此,这个事件将是最后一个被调用的。
如果你按照之前的方式运行应用程序(使用相同的参数),你应该会看到以下输出:
...
[AR] Option Args: [enable, remote, option]
[AR] Option Arg Values: [value1, value2]
[AR] Non Option: [update, upgrade]
[CLR] Args: [--enable, --remote, --option=value1, --option=value2, update, upgrade]
[AL] Im ready to interact...
...请注意,ApplicationRunner 首先被调用,然后是 CommandLineRunner,最后是 ApplicationReadyEvent。您可以有多个实现 run 方法的 CommandLineRunner 类,这些类必须标记为 @Component。如果需要按顺序列出,可以使用 @Order 注解(根据优先级,使用 Ordered 枚举作为参数)。
应用程序配置
有时候,我们需要对远程服务器进行非常具体的访问,或者需要连接远程服务器的凭据,甚至需要存储在数据库中的敏感数据。虽然我们可以将这些信息(凭据、远程 IP、敏感数据)硬编码,但这并不是最佳实践,因为这些信息可能会迅速变化,可能会导致我们在重新部署应用时出现错误,进而带来不良后果,比如连接到错误的服务器。
Spring Boot 使用 application.properties 或 application.yaml 来外部化所需的配置,同时也利用这些文件来覆盖应用程序中的一些默认设置(这与自动配置和条件有关)。在本书中,您将学习如何更改这些默认设置,但现在我们先来讨论如何创建自己的属性以及如何使用它们。
我的复古应用与用户应用项目的整合
为了了解如何使用外部配置,让我们继续我们的旅程,回顾我们的两个项目:我的复古应用和用户应用。尽管我们尚未讨论这些项目在本书中将如何集成,但在某个时刻,我的复古应用需要联系用户应用,以验证和授权希望使用我的复古应用的用户。因此,在这种情况下,必须拥有服务器、端口和其他有用的信息。
在我的复古应用程序中,打开 application.properties 文件,并添加列表 2-13 所示的内容。
# Users Properties
users.server=127.0.0.1
users.port=8081
users.username=admin
users.password=aW3s0m3列表 2-13 源文件:src/main/java/resources/application.properties
列表 2-13 展示了我们在 My Retro App 项目中需要的一些属性。接下来,打开 MyRetroConfiguration 类,并将内容替换为列表 2-14 中提供的代码。
package com.apress.myretro;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyRetroConfiguration {
    Logger log = LoggerFactory.getLogger(MyRetroConfiguration.class);
     @Value("${users.server}")
        String server;
        @Value("${users.port}")
        Integer port;
        @Value("${users.username}")
        String username;
        @Value("${users.password}")
        String password;
    @Bean
    ApplicationListener<ApplicationReadyEvent> init(){
        return event -> {
            log.info("\nThe users service properties are:\n- Server: {}\n- Port: {}\n- Username: {}\n- Password: {}",server,port,username,password);
        };
    }
}列表 2-14 源代码:src/main/java/com/apress/myretro/MyRetroConfiguration.java
列表 2-14 展示了更新后的 MyRetroConfiguration 类。我们来分析一下。
- 这是一个新的注解,用于收集在“”之间指定的属性值,使用以$开头的 SpEL(Spring 表达式语言)和{}中的属性名称。在 Spring 应用程序的生命周期中(收集信息和创建 bean),它会查找所有@Value 注解,并尝试在默认文件 application.properties 或 application.yaml 中查找相应的值。例如,我们声明了一个 Integer 类型的 port 变量,并用@Value("${users.port}")注解它,因此在这个类实例化时,它将获取值 8081 并赋值给 port 变量。
- 应用监听器:当 ApplicationReadyEvent 被触发时,此接口将执行 init 方法(这表示应用程序已准备好与其他逻辑进行交互)。
如果你运行这个应用程序,你应该会看到类似于以下的输出:
The users service properties are:
- Server: 127.0.0.1
- Port: 8081
- Username: admin
- Password: aW3s0m3现在,如果我们有超过四个属性会发生什么呢?我们可以添加更多变量并用@Value 进行标记,但这样很快就会变得混乱。Spring Boot 在这种情况下提供了更好的解决方案,接下来将进行介绍。
配置选项
Spring Boot 提供了一个简单的解决方案来处理多个和更复杂的属性。它定义了一个类标记 @ConfigurationProperties 注解,将类的字段与外部定义的属性(在我们的例子中是 application.properties)绑定。
让我们在 src/main/java/com/apress/myretro 文件夹中创建一个名为 MyRetroProperties 的新类,内容如清单 2-15 所示。
package com.apress.myretro;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties
public class MyRetroProperties {
    Users users;
    public Users getUsers() {
        return users;
    }
    public void setUsers(Users users) {
        this.users = users;
    }
}
class Users {
    String server;
    Integer port;
    String username;
    String password;
    public String getServer() {
        return server;
    }
    public void setServer(String server) {
        this.server = server;
    }
    public Integer getPort() {
        return port;
    }
    public void setPort(Integer port) {
        this.port = port;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
}列表 2-15 源代码:src/main/java/com/apress/myretro/MyRetroProperties.java
列表 2-15 展示了 MyRetroProperties 类,得益于@ConfigurationProperties,它将 application.properties(或 application.yaml)中的属性绑定到该类的每个字段。请注意,这个类只是一个 POJO(普通旧 Java 对象),包含 setter 和 getter 方法。其设计理念是每个字段的名称相同,以便能够匹配。为了告诉 Spring Boot 这个类是一个 ConfigurationProperties 类,我们需要通过将类标记为@Component 或在 Configuration 类中使用@EnableConfigurationProperties 注解来进行说明。列表 2-16 展示了修改后的 MyRetroConfiguration 类。
package com.apress.myretro;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@EnableConfigurationProperties({MyRetroProperties.class})
@Configuration
public class MyRetroConfiguration {
    Logger log = LoggerFactory.getLogger(MyRetroConfiguration.class);
    @Bean
    ApplicationListener<ApplicationReadyEvent> init(MyRetroProperties myRetroProperties){
        return event -> {
            log.info("\nThe users service properties are:\n- Server: {}\n- Port: {}\n- Username: {}\n- Password: {}",
                    myRetroProperties.getUsers().getServer(),
                    myRetroProperties.getUsers().getPort(),
                    myRetroProperties.getUsers().getUsername(),
                    myRetroProperties.getUsers().getPassword());
        };
    }
}列表 2-16 源代码:src/main/java/com/apress/myretro/MyRetroConfiguration.java
在修改后的 MyRetroConfiguration 类中,我们使用了 @EnableConfigurationProperties 注解,该注解接受一个标记为 ConfigurationProperties 的类数组。此外,请注意,init 方法现在有一个 MyRetroProperties 参数,这个类(MyRetroConfiguration.class)将由 Spring 自动注入(因为它使用 @Bean 注解标记)。这样,您可以像访问其他常规类一样,通过其 getter 方法来访问这些属性。
如果我们有多个服务(不仅仅是用户),会发生什么呢?将它们标识为服务会很好,对吧?这意味着我们可以在配置属性类中添加一个前缀。请看下一个代码片段。
@ConfigurationProperties(prefix="service")
public class MyRetroProperties {
    Users users;
    public Users getUsers() {
        return users;
    }
    public void setUsers(Users users) {
        this.users = users;
    }
}前缀参数将根据您在属性文件中设置的内容,使用服务.* 属性进行绑定匹配。这意味着我们的 application.properties 文件应该如下所示:
service.users.server=127.0.0.1
service.users.port=8081
service.users.username=admin
service.users.password=aW3s0m3如果你运行这个应用程序,应该会得到相同的结果。
轻松的绑定
我之前提到过,属性名称必须与类中的字段名称一致,对吗?那么,Spring Boot 提供了一种宽松的绑定方式;它为将环境属性绑定到标记为 @ConfigurationProperties 的类提供了一些宽松的规则。如果你的字段名是过长的驼峰命名,你可以使用驼峰命名、下划线、短横线或大写格式。请考虑以下示例:
private String hostNameServer;你可以使用以下表示法:
- 驼峰命名:hostNameServer
- 主机名: host-name-server
- 下划线:host_name_server
- 大写: HOST_NAME_SERVER
配置的优先级
使用外部化配置的另一个好处是可以通过不同的方式来定义属性。您可以使用环境变量、Java 系统属性、JNDI、servlet 内容、配置参数、命令行参数等多种方式。但是,如果我在所有这些机制中都定义了相同的属性,会发生什么呢?好消息是,Spring Boot 在运行应用程序时有一些优先级规则可以遵循。
以下列表展示了在运行您的应用程序及其属性绑定时将遵循的优先级顺序:
- 默认属性(由 SpringApplication.setDefaultProperties 设置)。
- @Configuration 类中的@PropertySource 注解。请注意,这些属性源在应用程序上下文刷新之前不会被添加到环境中。因此,对于某些属性(如 logging.*和 spring.main.*)的配置来说,这个时机已经太晚,因为它们在刷新开始之前就会被读取。
- 配置数据(如 application.properties 文件)。
- 一个仅在 random.* 中包含属性的 RandomValuePropertySource。
- 操作系统的环境变量。
- Java 系统属性(通过 System.getProperties() 获取)。
- 来自 java:comp/env 的 JNDI 属性。
- ServletContext 的初始化参数。
- ServletConfig 的初始化参数。
- 来自 SPRING_APPLICATION_JSON 的属性(嵌入在环境变量或系统属性中的 JSON)。
- 命令行选项。
- 您的测试中的属性(可在@SpringBootTest 和用于测试应用程序特定部分的测试注解中使用)。
- 在测试中使用@TestPropertySource 注解。
- 当开发工具处于活动状态时,$HOME/.config/spring-boot 目录下的开发工具全局设置属性。
使用 application.properties 文件时,您可以遵循以下优先级:
- 打包在您的 JAR 文件中的应用程序属性(application.properties 和 YAML 格式)
- 打包在您的 JAR 文件中的特定于配置文件的应用程序属性(application-{profile}.properties 和 YAML 格式)
- 应用程序属性文件位于您的打包 JAR 之外(包括 application.properties 和 YAML 格式)
- 针对特定配置文件的应用程序属性应放在打包的 JAR 文件之外(application-{profile}.properties 和 YAML 变体)
当然,有很多选项可以使用外部配置,您甚至可以通过以下属性/参数来指定读取文件的位置:--spring.config.location=。我认为这里最重要的是关注优先级。总结一下,如果您有一个包含 application.properties 的 JAR 文件,而您运行应用程序的地方有另一个同名文件,那么这个文件将覆盖您已有的配置,任何环境变量也会覆盖 JAR 应用程序中的属性。
修改默认设置
正如您所知,Spring Boot 使用默认设置来配置您的应用程序,但有时这些默认设置并不符合您的需求。Spring Boot 的一个重要特性是可以更改这些默认设置。您已经看到可以通过在 @SpringBootApplication 注解中使用 exclude={} 参数来排除某些自动配置。此外,还有一种方法可以指定您希望如何更改这些默认设置。
这里有一个重要的应用程序属性列表,您可以在此链接访问:https://docs.spring.io/spring-boot/docs/current/reference/html/application-properties.html。例如,如果您想将默认端口 8080 更改为 8082,可以使用属性 server.port=8082。
以下命令可以达到相同的效果:
java -jar build/libs/myretro-0.0.1-SNAPSHOT.jar --server.port=8082
SERVER_POST=8082  java -jar build/libs/myretro-0.0.1-SNAPSHOT.jar
java -Dspring.application.json='{"server.port":8082}' -jar build/libs/myretro-0.0.1-SNAPSHOT.jar应用程序档案
Spring Boot 也支持处理配置文件,这意味着您不仅可以使用自定义属性或覆盖默认设置,还可以利用配置文件来创建 bean。在接下来的章节中,我们将讨论 Spring Profile。
正如您之前看到的,您可以创建 application-.properties(或 YAML 文件)。当您有多个环境并希望为每个环境跟踪不同的值时,这非常方便。要使用这些功能,您需要通过 SpringApplicationBuilder.profiles(如您之前所见)或通过设置属性 spring.profiles.active= 来激活配置文件。
例如,您可以在资源文件夹中创建一个额外的 application-cloud.properties 文件,并添加其他值:
service.users.server=cloud.server.com
service.users.port=1089
service.users.username=root
service.users.password=Sup3RaW3s0m3如果您通过命令行或您喜欢的 IDE 传递属性来运行应用程序
--spring.profiles.active="cloud"你应该只查看 application-cloud.properties 文件中的值。
使用 YAML 格式可以通过只用一个文件来简化属性。例如,application.yaml 文件可以是这样的:
service:
  users:
    server: 127.0.0.1
    port: 8081
    username: admin
    password: aW3s0m3
---
spring:
  config:
    activate:
      on-profile: cloud
service:
  users:概要
本章介绍了许多功能,重点关注最重要的部分,或者说大多数开发者会使用的功能。你了解了 Spring Boot 的内部机制,并发现 Spring Boot 通过自动配置功能来设置默认值,这些默认值结合了应用程序的最佳实践。你还了解到,Spring Boot 会通过自动配置功能检查你的应用程序所使用的依赖项或类路径,并决定应用哪些默认值。所有这些都得益于自动配置类和@Conditional*注解,这些注解帮助过滤出应用程序所需的内容以及如何连接各个部分,从而减少了在创建 Spring 应用程序时通常需要进行的配置工作。
本章还向您展示了如何通过使用 SpringApplication 类或 SpringApplicationBuilder 流式 API 来定制您的 Spring Boot 应用程序。您还了解了如何在应用程序中使用参数,以及如何设置和使用 application.properties,甚至可以通过配置文件对其进行过滤。
在第三章中,我们将讨论如何使用 Spring Boot 开发 Web 应用,并通过我们的 My Retro App 和 Users App 项目创建 Web 端点。
相关推荐
- 如何设计一个优秀的电子商务产品详情页
- 
        加入人人都是产品经理【起点学院】产品经理实战训练营,BAT产品总监手把手带你学产品电子商务网站的产品详情页面无疑是设计师和开发人员关注的最重要的网页之一。产品详情页面是客户作出“加入购物车”决定的页面... 
- 怎么在JS中使用Ajax进行异步请求?
- 
        大家好,今天我来分享一项JavaScript的实战技巧,即如何在JS中使用Ajax进行异步请求,让你的网页速度瞬间提升。Ajax是一种在不刷新整个网页的情况下与服务器进行数据交互的技术,可以实现异步加... 
- 中小企业如何组建,管理团队_中小企业应当如何开展组织结构设计变革
- 
        前言写了太多关于产品的东西觉得应该换换口味.从码农到架构师,从前端到平面再到UI、UE,最后走向了产品这条不归路,其实以前一直再给你们讲.产品经理跟项目经理区别没有特别大,两个岗位之间有很... 
- 前端监控 SDK 开发分享_前端监控系统 开源
- 
        一、前言随着前端的发展和被重视,慢慢的行业内对于前端监控系统的重视程度也在增加。这里不对为什么需要监控再做解释。那我们先直接说说需求。对于中小型公司来说,可以直接使用三方的监控,比如自己搭建一套免费的... 
- Ajax 会被 fetch 取代吗?Axios 怎么办?
- 
        大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!今天给大家带来的主题是ajax、fetch... 
- 前端面试题《AJAX》_前端面试ajax考点汇总
- 
        1.什么是ajax?ajax作用是什么?AJAX=异步JavaScript和XML。AJAX是一种用于创建快速动态网页的技术。通过在后台与服务器进行少量数据交换,AJAX可以使网页实... 
- Ajax 详细介绍_ajax
- 
        1、ajax是什么?asynchronousjavascriptandxml:异步的javascript和xml。ajax是用来改善用户体验的一种技术,其本质是利用浏览器内置的一个特殊的... 
- 6款可替代dreamweaver的工具_替代powerdesigner的工具
- 
        dreamweaver对一个web前端工作者来说,再熟悉不过了,像我07年接触web前端开发就是用的dreamweaver,一直用到现在,身边的朋友有跟我推荐过各种更好用的可替代dreamweaver... 
- 我敢保证,全网没有再比这更详细的Java知识点总结了,送你啊
- 
        接下来你看到的将是全网最详细的Java知识点总结,全文分为三大部分:Java基础、Java框架、Java+云数据小编将为大家仔细讲解每大部分里面的详细知识点,别眨眼,从小白到大佬、零基础到精通,你绝... 
- 福斯《死侍》发布新剧照 "小贱贱"韦德被改造前造型曝光
- 
        时光网讯福斯出品的科幻片《死侍》今天发布新剧照,其中一张是较为罕见的死侍在被改造之前的剧照,其余两张剧照都是死侍在执行任务中的状态。据外媒推测,片方此时发布剧照,预计是为了给不久之后影片发布首款正式预... 
- 2021年超详细的java学习路线总结—纯干货分享
- 
        本文整理了java开发的学习路线和相关的学习资源,非常适合零基础入门java的同学,希望大家在学习的时候,能够节省时间。纯干货,良心推荐!第一阶段:Java基础重点知识点:数据类型、核心语法、面向对象... 
- 不用海淘,真黑五来到你身边:亚马逊15件热卖爆款推荐!
- 
        Fujifilm富士instaxMini8小黄人拍立得相机(黄色/蓝色)扫二维码进入购物页面黑五是入手一个轻巧可爱的拍立得相机的好时机,此款是mini8的小黄人特别版,除了颜色涂装成小黄人... 
- 2025 年 Python 爬虫四大前沿技术:从异步到 AI
- 
        作为互联网大厂的后端Python爬虫开发,你是否也曾遇到过这些痛点:面对海量目标URL,单线程爬虫爬取一周还没完成任务;动态渲染的SPA页面,requests库返回的全是空白代码;好不容易... 
- 最贱超级英雄《死侍》来了!_死侍超燃
- 
        死侍Deadpool(2016)导演:蒂姆·米勒编剧:略特·里斯/保罗·沃尼克主演:瑞恩·雷诺兹/莫蕾娜·巴卡林/吉娜·卡拉诺/艾德·斯克林/T·J·米勒类型:动作/... 
- 停止javascript的ajax请求,取消axios请求,取消reactfetch请求
- 
        一、Ajax原生里可以通过XMLHttpRequest对象上的abort方法来中断ajax。注意abort方法不能阻止向服务器发送请求,只能停止当前ajax请求。停止javascript的ajax请求... 
- 一周热门
- 最近发表
- 标签列表
- 
- HTML 简介 (30)
- HTML 响应式设计 (31)
- HTML URL 编码 (32)
- HTML Web 服务器 (31)
- HTML 表单属性 (32)
- HTML 音频 (31)
- HTML5 支持 (33)
- HTML API (36)
- HTML 总结 (32)
- HTML 全局属性 (32)
- HTML 事件 (31)
- HTML 画布 (32)
- HTTP 方法 (30)
- 键盘快捷键 (30)
- CSS 语法 (35)
- CSS 轮廓宽度 (31)
- CSS 谷歌字体 (33)
- CSS 链接 (31)
- CSS 定位 (31)
- CSS 图片库 (32)
- CSS 图像精灵 (31)
- SVG 文本 (32)
- 时钟启动 (33)
- HTML 游戏 (34)
- JS Loop For (32)
 
