Accessing application properties with Spring Boot properties API
如果你希望使用 Spring Boot @ConfigurationProperties
注解类来访问应用程序属性,而不是 @ConfigMapping
或 MicroProfile @ConfigProperty
方法,你可以使用此扩展。
If you prefer to use Spring Boot @ConfigurationProperties
annotated class to access application properties instead of
@ConfigMapping
or a MicroProfile @ConfigProperty
approach, you can do that with this extension.
Spring Boot @ConfigurationProperties
有些局限。例如,不支持注入 Map
。请考虑使用 Mapping configuration to objects。
Spring Boot @ConfigurationProperties
has a few limitations. For instance, Map
injection is not
supported. Consider using Mapping configuration to objects.
Prerequisites
Unresolved directive in spring-boot-properties.adoc - include::{includes}/prerequisites.adoc[]
Solution
我们建议您遵循接下来的部分中的说明,按部就班地创建应用程序。然而,您可以直接跳到完成的示例。
We recommend that you follow the instructions in the next sections and create the application step by step. However, you can go right to the completed example.
克隆 Git 存储库: git clone {quickstarts-clone-url}
,或下载 {quickstarts-archive-url}[存档]。
Clone the Git repository: git clone {quickstarts-clone-url}
, or download an {quickstarts-archive-url}[archive].
该解法位于 spring-boot-properties-quickstart
… directory。
The solution is located in the spring-boot-properties-quickstart
directory.
Creating the Maven project
首先,我们需要一个新项目。使用以下命令创建一个新项目:
First, we need a new project. Create a new project with the following command:
Unresolved directive in spring-boot-properties.adoc - include::{includes}/devtools/create-app.adoc[]
此命令会生成一个项目并导入 spring-boot-properties
扩展。
This command generates a project and imports the spring-boot-properties
extension.
如果你已经配置好了 Quarkus 项目,则可以按如下方式在项目基本目录中运行以下命令,将 spring-boot-properties
扩展添加到项目:
If you already have your Quarkus project configured, you can add the spring-boot-properties
extension
to your project by running the following command in your project base directory:
Unresolved directive in spring-boot-properties.adoc - include::{includes}/devtools/extension-add.adoc[]
这会将以下内容添加到构建文件中:
This will add the following to your build file:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-spring-boot-properties</artifactId>
</dependency>
implementation("io.quarkus:quarkus-spring-boot-properties")
GreetingController
首先,以类似如下所示方式在 src/main/java/org/acme/spring/boot/properties/GreetingResource.java
文件中创建一个 GreetingResource
Jakarta REST 资源:
First, create a GreetingResource
Jakarta REST resource in the
src/main/java/org/acme/spring/boot/properties/GreetingResource.java
file that looks like:
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";
}
}
Injecting properties
创建一个带有 message 字段的新类 src/main/java/org/acme/spring/boot/properties/GreetingProperties.java
:
Create a new class src/main/java/org/acme/spring/boot/properties/GreetingProperties.java
with a message field:
package org.acme.spring.boot.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("greeting")
public class GreetingProperties {
public String text;
}
此处的 text
字段是公共字段,但也可以是带 getter 和 setter 方法的私有字段,也可以是接口中的公共 getter。因为 text
没有默认值,因此被视为必需字段,而且除非在配置文件中定义(默认情况下为 application.properties
),否则你的应用程序将启动失败。在你的 src/main/resources/application.properties
文件中定义此属性:
Here text
field is public, but it could also be a private field with getter and setter or just a public getter in an interface.
Because text
does not have a default value it is considered required and unless it is defined in a configuration file (application.properties
by default) your application will fail to start.
Define this property in your src/main/resources/application.properties
file:
# Your configuration properties
greeting.text=hello
现在修改 GreetingResource
,以开始使用 GreetingProperties
:
Now modify GreetingResource
to start using the 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;
}
}
运行测试,验证应用程序仍能正确运行。
Run the tests to verify that application still functions correctly.
Package and run the application
按如下方式在开发模式下运行应用程序:
Run the application in dev mode with:
Unresolved directive in spring-boot-properties.adoc - include::{includes}/devtools/dev.adoc[]
用浏览器打开 [role="bare"][role="bare"]http://localhost:8080/greeting.
Open your browser to [role="bare"]http://localhost:8080/greeting.
修改配置文件会立即反映出来。
Changing the configuration file is immediately reflected.
和往常一样,可以使用以下命令打包应用程序:
As usual, the application can be packaged using:
Unresolved directive in spring-boot-properties.adoc - include::{includes}/devtools/build.adoc[]
并使用 `java -jar target/quarkus-app/quarkus-run.jar`执行。
And executed using java -jar target/quarkus-app/quarkus-run.jar
.
你还可以按如下方式生成本机可执行文件:
You can also generate the native executable with:
Unresolved directive in spring-boot-properties.adoc - include::{includes}/devtools/build-native.adoc[]
Default values
现在我们添加一个我们设置默认值的问候语后缀。
Now let’s add a suffix for a greeting for which we’ll set a default value.
具有默认值的属性可以像任何其他属性一样在配置文件中配置。但是,如果属性未在配置文件中定义,则将使用默认值。
Properties with default values can be configured in a configuration file just like any other property. However, the default value will be used if the property was not defined in a configuration file.
继续并将新字段添加到 @ [1]
类:
Go ahead and add the new field to the GreetingProperties
class:
package org.acme.spring.boot.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("greeting")
public class GreetingProperties {
public String text;
public String suffix = "!";
}
并更新 @ [2]
及其测试 @ [3]
:
And update the GreetingResource
and its test 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!"));
}
}
运行测试以验证更改。
Run the tests to verify the change.
Optional values
具有可选值的属性是标准和具有默认值的属性之间的中间值。虽然配置文件中缺少的属性不会导致你的应用程序失败,但它仍然没有设置值。我们使用 @ [4]
类型来定义此类属性。
Properties with optional values are the middle-ground between standard and properties with default values.
While a missing property in a configuration file will not cause your application to fail, it will nevertheless not have a value set.
We use java.util.Optional
type to define such properties.
向 @ [6]
添加一个可选的 @ [5]
属性:
Add an optional name
property to the 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;
}
并更新 @ [2]
及其测试 @ [3]
:
And update the GreetingResource
and its test 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!"));
}
}
运行测试以验证更改。
Run the tests to verify the change.
Grouping properties
现在我们的 @ [7]
类中有三个属性。虽然 @ [8]
可以被认为更多是一个运行时属性(并且将来可能可以作为 HTTP 查询参数传递),但 @ [9]
和 @ [10]
用于定义一个消息模板。让我们将这两个属性分组到一个单独的内部类:
Now we have three properties in our GreetingProperties
class.
While name
could be considered more of a runtime property (and maybe could be passed as an HTTP query parameter in the future), text
and suffix
are used to define a message template.
Let’s group these two properties in a separate inner class:
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 = "!";
}
}
这里 @ [11]
属性类被定义为一个内部类,但它也可以是顶级类。
Here Message
properties class is defined as an inner class, but it could also be a top level class.
具有这样的属性组将为你的配置带来更多的结构。当属性数增长时,这一点特别有用。
Having such property groups brings more structure to your configuration. This is especially useful when then number of properties grows.
由于添加了类,我们的属性名称发生了变化。让我们更新属性文件和 @ [12]
类。
Because of the additional class, our property names have changed.
Let’s update the properties file and the GreetingResource
class.
# 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;
}
}
More Spring guides
Quarkus 还有更多 Spring 兼容性功能。请参阅以下指南以获取更多详情:
Quarkus has more Spring compatibility features. See the following guides for more details: