编辑此页面

使用 Spring Boot 属性 API 访问应用程序属性

如果您更喜欢使用 Spring Boot @ConfigurationProperties 注解的类来访问应用程序属性,而不是 @ConfigMapping 或 MicroProfile @ConfigProperty 方法,您可以使用此扩展来实现。

Spring Boot @ConfigurationProperties 有一些限制。例如,不支持 Map 注入。请考虑使用 将配置映射到对象

先决条件

要完成本指南,您需要

  • 大约 15 分钟

  • 一个 IDE

  • 已安装 JDK 17+ 并正确配置了 JAVA_HOME

  • Apache Maven 3.9.9

  • 如果您想使用它,可以选择 Quarkus CLI

  • 如果您想构建本机可执行文件(或者如果您使用本机容器构建,则为 Docker),可以选择安装 Mandrel 或 GraalVM 并进行适当的配置

解决方案

我们建议您按照以下章节中的说明,逐步创建应用程序。但是,您可以直接转到完整的示例。

克隆 Git 仓库:git clone https://github.com/quarkusio/quarkus-quickstarts.git,或下载 压缩包

解决方案位于 spring-boot-properties-quickstart 目录中。

创建 Maven 项目

首先,我们需要一个新项目。使用以下命令创建一个新项目

CLI
quarkus create app org.acme:spring-boot-properties-quickstart \
    --extension='rest,spring-boot-properties' \
    --no-code
cd spring-boot-properties-quickstart

要创建 Gradle 项目,请添加 --gradle--gradle-kotlin-dsl 选项。

有关如何安装和使用 Quarkus CLI 的更多信息,请参阅 Quarkus CLI 指南。

Maven
mvn io.quarkus.platform:quarkus-maven-plugin:3.24.4:create \
    -DprojectGroupId=org.acme \
    -DprojectArtifactId=spring-boot-properties-quickstart \
    -Dextensions='rest,spring-boot-properties' \
    -DnoCode
cd spring-boot-properties-quickstart

要创建 Gradle 项目,请添加 -DbuildTool=gradle-DbuildTool=gradle-kotlin-dsl 选项。

对于 Windows 用户

  • 如果使用 cmd,(不要使用反斜杠 \ 并将所有内容放在同一行上)

  • 如果使用 Powershell,请将 -D 参数用双引号括起来,例如 "-DprojectArtifactId=spring-boot-properties-quickstart"

此命令生成一个项目并导入 spring-boot-properties 扩展。

如果您已经配置了 Quarkus 项目,可以通过在项目根目录中运行以下命令将 spring-boot-properties 扩展添加到您的项目中

CLI
quarkus extension add spring-boot-properties
Maven
./mvnw quarkus:add-extension -Dextensions='spring-boot-properties'
Gradle
./gradlew addExtension --extensions='spring-boot-properties'

这会将以下内容添加到您的构建文件中

pom.xml
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-spring-boot-properties</artifactId>
</dependency>
build.gradle
implementation("io.quarkus:quarkus-spring-boot-properties")

GreetingController

首先,在 src/main/java/org/acme/spring/boot/properties/GreetingResource.java 文件中创建一个如下所示的 GreetingResource Jakarta REST 资源

package org.acme.spring.boot.properties;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;

@Path("/hello")
public class GreetingResource {

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String hello() {
        return "hello";
    }
}

注入属性

创建一个新类 src/main/java/org/acme/spring/boot/properties/GreetingProperties.java,其中包含一个 message 字段

package org.acme.spring.boot.properties;

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

@ConfigurationProperties("greeting")
public class GreetingProperties {

    public String text;
}

这里 text 字段是 public 的,但它也可以是带有 getter 和 setter 的 private 字段,或者只是接口中的 public getter。由于 text 没有默认值,因此被认为是必需的,除非它在配置文件(默认情况下为 application.properties)中定义,否则您的应用程序将无法启动。在您的 src/main/resources/application.properties 文件中定义此属性

# Your configuration properties
greeting.text=hello

现在修改 GreetingResource 以开始使用 GreetingProperties

package org.acme.spring.boot.properties;

import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;

@Path("/greeting")
public class GreetingResource {

    @Inject
    GreetingProperties properties;

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String hello() {
        return properties.text;
    }
}

运行测试以验证应用程序是否仍然正常运行。

打包并运行应用程序

使用以下命令在开发模式下运行应用程序

CLI
quarkus dev
Maven
./mvnw quarkus:dev
Gradle
./gradlew --console=plain quarkusDev

在浏览器中打开 https://:8080/greeting

更改配置文件会立即反映出来。

与往常一样,可以使用以下命令打包应用程序

CLI
quarkus build
Maven
./mvnw install
Gradle
./gradlew build

并使用 java -jar target/quarkus-app/quarkus-run.jar 执行。

您还可以使用以下命令生成原生可执行文件

CLI
quarkus build --native
Maven
./mvnw install -Dnative
Gradle
./gradlew build -Dquarkus.native.enabled=true

默认值

现在让我们添加一个问候语后缀,我们将为其设置一个默认值。

具有默认值的属性可以在配置文件中像任何其他属性一样配置。但是,如果属性未在配置文件中定义,则将使用默认值。

继续并将新字段添加到 GreetingProperties

package org.acme.spring.boot.properties;

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

@ConfigurationProperties("greeting")
public class GreetingProperties {

    public String text;

    public String suffix = "!";
}

并更新 GreetingResource 及其测试 GreetingResourceTest

package org.acme.spring.boot.properties;

import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;

@Path("/greeting")
public class GreetingResource {

    @Inject
    GreetingProperties properties;

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String hello() {
        return properties.text + properties.suffix;
    }
}
package org.acme.spring.boot.properties;

import io.quarkus.test.junit.QuarkusTest;
import org.junit.jupiter.api.Test;

import static io.restassured.RestAssured.given;
import static org.hamcrest.CoreMatchers.is;

@QuarkusTest
public class GreetingResourceTest {

    @Test
    public void testHelloEndpoint() {
        given()
          .when().get("/greeting")
          .then()
             .statusCode(200)
             .body(is("hello!"));
    }
}

运行测试以验证更改。

可选值

具有可选值的属性是标准属性和具有默认值的属性之间的中间地带。虽然配置文件中缺少属性不会导致您的应用程序失败,但它仍然不会设置值。我们使用 java.util.Optional 类型来定义此类属性。

将可选的 name 属性添加到 GreetingProperties

package org.acme.spring.boot.properties;

import java.util.Optional;

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

@ConfigurationProperties("greeting")
public class GreetingProperties {

    public String text;

    public String suffix = "!";

    public Optional<String> name;
}

并更新 GreetingResource 及其测试 GreetingResourceTest

package org.acme.spring.boot.properties;

import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;

@Path("/greeting")
public class GreetingResource {

    @Inject
    GreetingProperties properties;

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String hello() {
        return properties.text + ", " + properties.name.orElse("You") + properties.suffix;
    }
}
package org.acme.spring.boot.properties;

import io.quarkus.test.junit.QuarkusTest;
import org.junit.jupiter.api.Test;

import static io.restassured.RestAssured.given;
import static org.hamcrest.CoreMatchers.is;

@QuarkusTest
public class GreetingResourceTest {

    @Test
    public void testHelloEndpoint() {
        given()
          .when().get("/greeting")
          .then()
             .statusCode(200)
             .body(is("hello, You!"));
    }
}

运行测试以验证更改。

分组属性

现在我们的 GreetingProperties 类中有三个属性。虽然 name 可以被认为更像是一个运行时属性(并且将来可以作为 HTTP 查询参数传递),但 textsuffix 用于定义消息模板。让我们将这两个属性分组到一个单独的内部类中

package org.acme.spring.boot.properties;

import java.util.Optional;

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

@ConfigurationProperties("greeting")
public class GreetingProperties {

    public Message message;

    public Optional<String> name;

    public static class Message {

        public String text;

        public String suffix = "!";
    }
}

这里的 Message 属性类被定义为一个内部类,但它也可以是一个顶级类。

拥有这样的属性组可以为您的配置带来更多的结构。当属性数量增长时,这尤其有用。

由于添加了类,我们的属性名称已更改。让我们更新属性文件和 GreetingResource 类。

# Your configuration properties
greeting.message.text=hello
package org.acme.spring.boot.properties;

import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;

@Path("/greeting")
public class GreetingResource {

    @Inject
    GreetingProperties properties;

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String hello() {
        return properties.message.text + ", " + properties.name.orElse("You") + properties.message.suffix;
    }
}

相关内容