Using the legacy REST Client
本指南是关于与 RESTEasy Classic 兼容的 REST 客户端的,直到 Quarkus 2.8,它一直是默认的 Jakarta REST(以前称为 JAX-RS)实现。
This guide is about the REST Client compatible with RESTEasy Classic which used to be the default Jakarta REST (formerly known as JAX-RS) implementation until Quarkus 2.8.
现在建议使用 Quarkus REST(以前称为 RESTEasy Reactive),它同样支持传统的阻塞工作负载和反应式工作负载。有关 Quarkus REST 的更多信息,请参阅 REST Client guide,对于服务器端,请参阅 introductory REST JSON guide 或更详细的 Quarkus REST guide。
It is now recommended to use Quarkus REST (formerly RESTEasy Reactive), which supports equally well traditional blocking workloads and reactive workloads. For more information about Quarkus REST, please see the REST Client guide and, for the server side, the introductory REST JSON guide or the more detailed Quarkus REST guide.
本指南解释了如何使用 RESTEasy REST 客户端与 REST API 进行交互,而几乎不需要任何工作。
This guide explains how to use the RESTEasy REST Client in order to interact with REST APIs with very little effort.
如果您需要编写服务器 JSON REST APIs,还有其他指南。 |
there is another guide if you need to write server JSON REST APIs. |
Prerequisites
Unresolved directive in resteasy-client.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].
解决方案位于 resteasy-client-quickstart
directory。
The solution is located in the resteasy-client-quickstart
directory.
Creating the Maven project
首先,我们需要一个新项目。使用以下命令创建一个新项目:
First, we need a new project. Create a new project with the following command:
Unresolved directive in resteasy-client.adoc - include::{includes}/devtools/create-app.adoc[]
此命令生成具有 REST 端点的 Maven 项目,并导入:
This command generates the Maven project with a REST endpoint and imports:
-
the
resteasy
andresteasy-jackson
extensions for the REST server support; -
the
resteasy-client
andresteasy-client-jackson
extensions for the REST client support.
如果您已配置 Quarkus 项目,您可以通过在项目根目录中运行以下命令将 resteasy-client
和 resteasy-client-jackson
扩展添加到您的项目:
If you already have your Quarkus project configured, you can add the resteasy-client
and the resteasy-client-jackson
extensions
to your project by running the following command in your project base directory:
Unresolved directive in resteasy-client.adoc - include::{includes}/devtools/extension-add.adoc[]
这会将以下内容添加到您的 pom.xml
:
This will add the following to your pom.xml
:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-client</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-client-jackson</artifactId>
</dependency>
implementation("io.quarkus:quarkus-resteasy-client")
implementation("io.quarkus:quarkus-resteasy-client-jackson")
Setting up the model
在本指南中,我们将演示如何使用 stage.code.quarkus.io 服务提供的 REST API 的一部分。我们的首要任务是设置我们所使用的模型,采用 Extension
POJO 的形式。
In this guide we will be demonstrating how to consume part of the REST API supplied by the stage.code.quarkus.io service.
Our first order of business is to set up the model we will be using, in the form of an Extension
POJO.
创建一个 src/main/java/org/acme/rest/client/Extension.java
文件,并设置以下内容:
Create a src/main/java/org/acme/rest/client/Extension.java
file and set the following content:
package org.acme.rest.client;
import java.util.List;
public class Extension {
public String id;
public String name;
public String shortName;
public List<String> keywords;
}
以上模型只是该服务所提供的字段的一个子集,但足以满足本指南的目的。
The model above is only a subset of the fields provided by the service, but it suffices for the purposes of this guide.
Create the interface
使用 RESTEasy REST 客户端就像使用适当的 Jakarta REST 和 MicroProfile 注释创建一个接口一样简单。在我们的情况下,应该在 src/main/java/org/acme/rest/client/ExtensionsService.java
处创建接口,且内容如下:
Using the RESTEasy REST Client is as simple as creating an interface using the proper Jakarta REST and MicroProfile annotations. In our case the interface should be created at src/main/java/org/acme/rest/client/ExtensionsService.java
and have the following content:
package org.acme.rest.client;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import org.jboss.resteasy.annotations.jaxrs.QueryParam;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.QueryParam;
import java.util.Set;
@Path("/extensions")
@RegisterRestClient
public interface ExtensionsService {
@GET
Set<Extension> getById(@QueryParam String id);
}
getById
方法为我们的代码提供从 Code Quarkus API 根据 id 获取扩展的能力。客户端将处理所有网络连接和封送,使我们的代码不包含此类技术细节。
The getById
method gives our code the ability to get an extension by id from the Code Quarkus API. The client will handle all the networking and marshalling leaving our code clean of such technical details.
上述代码中注释的目的如下:
The purpose of the annotations in the code above is the following:
-
@RegisterRestClient
allows Quarkus to know that this interface is meant to be available for CDI injection as a REST Client -
@Path
,@GET
and@QueryParam
are the standard Jakarta REST annotations used to define how to access the service
当安装了 JSON 扩展(例如 When a JSON extension is installed such as 如果你不想默认使用 JSON,你可以设置 If you don’t want JSON by default you can set 如果你不依赖于 JSON 默认值,强烈建议使用 If you don’t rely on the JSON default, it is heavily recommended to annotate your endpoints with the |
Path Parameters
如果 GET 请求需要路径参数,你可以利用 @PathParam("parameter-name")
注释,而非(或附加) @QueryParam
。路径和查询参数可以根据需要组合,如下面的模拟示例所示。
If the GET request requires path parameters you can leverage the @PathParam("parameter-name")
annotation instead of (or in addition to) the @QueryParam
. Path and query parameters can be combined, as required, as illustrated in a mock example below.
package org.acme.rest.client;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import org.jboss.resteasy.annotations.jaxrs.PathParam;
import org.jboss.resteasy.annotations.jaxrs.QueryParam;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import java.util.Set;
@Path("/extensions")
@RegisterRestClient
public interface ExtensionsService {
@GET
@Path("/stream/{stream}")
Set<Extension> getByStream(@PathParam String stream, @QueryParam("id") String id);
}
Create the configuration
要确定发起 REST 调用时的基本 URL,REST 客户端使用 application.properties
的配置。属性的名称需要遵循特定的约定,这在下面的代码中展示得最好:
In order to determine the base URL to which REST calls will be made, the REST Client uses configuration from application.properties
.
The name of the property needs to follow a certain convention which is best displayed in the following code:
# Your configuration properties
quarkus.rest-client."org.acme.rest.client.ExtensionsService".url=https://stage.code.quarkus.io/api # (1)
quarkus.rest-client."org.acme.rest.client.ExtensionsService".scope=jakarta.inject.Singleton # (2)
1 | Having this configuration means that all requests performed using ExtensionsService will use https://stage.code.quarkus.io as the base URL.
Using the configuration above, calling the getById method of ExtensionsService with a value of io.quarkus:quarkus-resteasy-client would result in an HTTP GET request being made to https://stage.code.quarkus.io/api/extensions?id=io.quarkus:quarkus-rest-client . |
2 | Having this configuration means that the default scope of ExtensionsService will be @Singleton . Supported scope values are @Singleton , @Dependent , @ApplicationScoped and @RequestScoped . The default scope is @Dependent .
The default scope can also be defined on the interface. |
请注意,org.acme.rest.client.ExtensionsService
must 匹配我们之前部分中创建的 ExtensionsService
界面中的完整限定名。
Note that org.acme.rest.client.ExtensionsService
must match the fully qualified name of the ExtensionsService
interface we created in the previous section.
也可以使用标准的 MicroProfile Rest 客户端属性表示法配置客户端: The standard MicroProfile Rest Client properties notation can also be used to configure the client:
如果通过 Quarkus 表示法和 MicroProfile 表示法指定一个属性,Quarkus 表示法具有优先权。 If a property is specified via both the Quarkus notation and the MicroProfile notation, the Quarkus notation takes a precedence. |
为了便于配置,你可以使用 @RegisterRestClient
configKey
属性,该属性允许你使用其他配置根路径,而非界面的完整限定名。
To facilitate the configuration, you can use the @RegisterRestClient
configKey
property that allows to use another configuration root than the fully qualified name of your interface.
@RegisterRestClient(configKey="extensions-api")
public interface ExtensionsService {
[...]
}
# Your configuration properties
quarkus.rest-client.extensions-api.url=https://stage.code.quarkus.io/api
quarkus.rest-client.extensions-api.scope=jakarta.inject.Singleton
Disabling Hostname Verification
要为特定 REST 客户端禁用 SSL 主机名验证,请将以下属性添加到你的配置中:
To disable the SSL hostname verification for a specific REST client, add the following property to your configuration:
quarkus.rest-client.extensions-api.verify-host=false
此设置不应在生产环境中使用,因为它会禁用 SSL 主机名验证。
This setting should not be used in production as it will disable the SSL hostname verification.
此外,你可以将 REST 客户端配置为使用自定义主机名验证策略,只需提供实现 javax.net.ssl.HostnameVerifier
界面的类,并将以下属性添加到你的配置中:
Moreover, you can configure a REST client to use your custom hostname verify strategy. All you need to do is to provide a class that implements the interface javax.net.ssl.HostnameVerifier
and add the following property to your configuration:
quarkus.rest-client.extensions-api.hostname-verifier=<full qualified custom hostname verifier class name>
Quarkus REST 客户端提供了一个嵌入式主机名验证器策略,以禁用名为 Quarkus REST client provides an embedded hostname verifier strategy to disable the hostname verification called |
Create the Jakarta REST resource
使用以下内容创建 src/main/java/org/acme/rest/client/ExtensionsResource.java
文件:
Create the src/main/java/org/acme/rest/client/ExtensionsResource.java
file with the following content:
package org.acme.rest.client;
import org.eclipse.microprofile.rest.client.inject.RestClient;
import org.jboss.resteasy.annotations.jaxrs.PathParam;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import java.util.Set;
@Path("/extension")
public class ExtensionsResource {
@Inject
@RestClient
ExtensionsService extensionsService;
@GET
@Path("/id/{id}")
public Set<Extension> id(@PathParam String id) {
return extensionsService.getById(id);
}
}
请注意除了标准 CDI @Inject`注解以外,还需要使用 MicroProfile `@RestClient`注解来注入 `ExtensionsService
。
Note that in addition to the standard CDI @Inject
annotation, we also need to use the MicroProfile @RestClient
annotation to inject ExtensionsService
.
Update the test
还需要更新功能测试来反映端点所做的更改。编辑 `src/test/java/org/acme/rest/client/ExtensionsResourceTest.java`文件并将 `testExtensionIdEndpoint`方法的内容更改为:
We also need to update the functional test to reflect the changes made to the endpoint.
Edit the src/test/java/org/acme/rest/client/ExtensionsResourceTest.java
file and change the content of the testExtensionIdEndpoint
method to:
package org.acme.rest.client;
import static io.restassured.RestAssured.given;
import static org.hamcrest.CoreMatchers.hasItem;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.Matchers.greaterThan;
import org.acme.rest.client.resources.WireMockExtensionsResource;
import org.junit.jupiter.api.Test;
import io.quarkus.test.common.WithTestResource;
import io.quarkus.test.junit.QuarkusTest;
@QuarkusTest
@WithTestResource(WireMockExtensionsResource.class)
public class ExtensionsResourceTest {
@Test
public void testExtensionsIdEndpoint() {
given()
.when().get("/extension/id/io.quarkus:quarkus-rest-client")
.then()
.statusCode(200)
.body("$.size()", is(1),
"[0].id", is("io.quarkus:quarkus-rest-client"),
"[0].name", is("REST Client Classic"),
"[0].keywords.size()", greaterThan(1),
"[0].keywords", hasItem("rest-client"));
}
}
上面的代码使用的是 REST Assured的 json-path功能。
The code above uses REST Assured's json-path capabilities.
Redirection
HTTP 服务器可以通过发送一个以“3”开头的状态码和一个包含待重定向到的 URL 的 HTTP 标头“Location”的响应来重定向响应到另一个位置。当 REST 客户端从 HTTP 服务器接收到重定向响应时,它不会自动对新位置执行另一个请求。但是,可以通过启用“follow-redirects”属性来启用自动重定向:
A HTTP server can redirect a response to another location by sending a response with a status code that starts with "3" and a HTTP header "Location" holding the URL to be redirected to. When the REST Client receives a redirection response from a HTTP server, it won’t automatically perform another request to the new location. However, you can enable the automatic redirection by enabling the "follow-redirects" property:
-
quarkus.rest-client.follow-redirects
to enable redirection for all REST clients. -
quarkus.rest-client.<client-prefix>.follow-redirects
to enable redirection for a specific REST client.
如果该属性为 true,则 REST 客户端将执行它从 HTTP 服务器接收到重定向响应后执行的新请求。
If this property is true, then REST Client will perform a new request that it receives a redirection response from the HTTP server.
此外,我们可以使用“max-redirects”属性限制重定向次数。
Additionally, we can limit the number of redirections using the property "max-redirects".
需要注意的重要一点是,根据 RFC2616规范,默认情况下重定向只会发生在 GET 或 HEAD 方法中。
One important note is that according to the RFC2616 specs, by default the redirection will only happen for GET or HEAD methods.
Async Support
Rest 客户端支持异步 rest 调用。异步支持有 2 种类型:可以返回 CompletionStage`或 `Uni
(需要 `quarkus-resteasy-client-mutiny`扩展)。让我们通过在 `ExtensionsService`REST 接口中添加一个 `getByIdAsync`方法来对其实现进行操作。代码应如下所示:
The rest client supports asynchronous rest calls.
Async support comes in 2 flavors: you can return a CompletionStage
or a Uni
(requires the quarkus-resteasy-client-mutiny
extension).
Let’s see it in action by adding a getByIdAsync
method in our ExtensionsService
REST interface. The code should look like:
package org.acme.rest.client;
import java.util.Set;
import java.util.concurrent.CompletionStage;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import org.jboss.resteasy.annotations.jaxrs.QueryParam;
@Path("/extensions")
@RegisterRestClient
public interface ExtensionsService {
@GET
Set<Extension> getById(@QueryParam String id);
@GET
CompletionStage<Set<Extension>> getByIdAsync(@QueryParam String id);
}
打开 `src/main/java/org/acme/rest/client/ExtensionsResource.java`文件并用以下内容更新它:
Open the src/main/java/org/acme/rest/client/ExtensionsResource.java
file and update it with the following content:
package org.acme.rest.client;
import java.util.Set;
import java.util.concurrent.CompletionStage;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import org.eclipse.microprofile.rest.client.inject.RestClient;
import org.jboss.resteasy.annotations.jaxrs.PathParam;
@Path("/extension")
public class ExtensionsResource {
@Inject
@RestClient
ExtensionsService extensionsService;
@GET
@Path("/id/{id}")
public Set<Extension> id(@PathParam String id) {
return extensionsService.getById(id);
}
@GET
@Path("/id-async/{id}")
public CompletionStage<Set<Extension>> idAsync(@PathParam String id) {
return extensionsService.getByIdAsync(id);
}
}
要测试异步方法,请在 `ExtensionsResourceTest`中添加以下测试方法:
To test asynchronous methods, add the test method below in ExtensionsResourceTest
:
@Test
public void testExtensionIdAsyncEndpoint() {
given()
.when().get("/extension/id-async/io.quarkus:quarkus-rest-client")
.then()
.statusCode(200)
.body("$.size()", is(1),
"[0].id", is("io.quarkus:quarkus-rest-client"),
"[0].name", is("REST Client Classic"),
"[0].keywords.size()", greaterThan(1),
"[0].keywords", hasItem("rest-client"));
}
`Uni`版本非常相似:
The Uni
version is very similar:
package org.acme.rest.client;
import java.util.Set;
import java.util.concurrent.CompletionStage;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import org.jboss.resteasy.annotations.jaxrs.QueryParam;
import io.smallrye.mutiny.Uni;
@Path("/extensions")
@RegisterRestClient
public interface ExtensionsService {
// ...
@GET
Uni<Set<Extension>> getByIdAsUni(@QueryParam String id);
}
`ExtensionsResource`变为:
The ExtensionsResource
becomes:
package org.acme.rest.client;
import java.util.Set;
import java.util.concurrent.CompletionStage;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import org.eclipse.microprofile.rest.client.inject.RestClient;
import org.jboss.resteasy.annotations.jaxrs.PathParam;
import io.smallrye.mutiny.Uni;
@Path("/extension")
public class ExtensionsResource {
@Inject
@RestClient
ExtensionsService extensionsService;
// ...
@GET
@Path("/id-uni/{id}")
public Uni<Set<Extension>> idMutiny(@PathParam String id) {
return extensionsService.getByIdAsUni(id);
}
}
Mutiny
前面的片段使用了 Mutiny reactive 类型。如果不熟悉 Mutiny,请参阅 Mutiny - an intuitive reactive programming library。 The previous snippet uses Mutiny reactive types. If you are not familiar with Mutiny, check Mutiny - an intuitive reactive programming library. |
在返回 Uni`时,每个 _subscription_都会调用远程服务。这意味着可以通过重新订阅 `Uni`重新发送请求,或按如下方式使用 `retry
:
When returning a Uni
, every subscription invokes the remote service.
It means you can re-send the request by re-subscribing on the Uni
, or use a retry
as follows:
@Inject @RestClient ExtensionsService extensionsService;
// ...
extensionsService.getByIdAsUni(id)
.onFailure().retry().atMost(10);
如果使用 CompletionStage
,则需要调用服务的方法来重试。这种差异源自 Mutiny 的惰性方面及其订阅协议。有关这方面的更多详细信息,请参阅 the Mutiny documentation。
If you use a CompletionStage
, you would need to call the service’s method to retry.
This difference comes from the laziness aspect of Mutiny and its subscription protocol.
More details about this can be found in the Mutiny documentation.
Custom headers support
MicroProfile REST 客户端允许通过使用具有 `@RegisterClientHeaders`注解的 `ClientHeadersFactory`来修改请求头。
The MicroProfile REST client allows amending request headers by registering a ClientHeadersFactory
with the @RegisterClientHeaders
annotation.
让我们通过在 `ExtensionsService`REST 接口中添加一个指向 `RequestUUIDHeaderFactory`类的 `@RegisterClientHeaders`注解来对其进行操作:
Let’s see it in action by adding a @RegisterClientHeaders
annotation pointing to a RequestUUIDHeaderFactory
class in our ExtensionsService
REST interface:
package org.acme.rest.client;
import java.util.Set;
import java.util.concurrent.CompletionStage;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import org.jboss.resteasy.annotations.jaxrs.QueryParam;
import io.smallrye.mutiny.Uni;
@Path("/extensions")
@RegisterRestClient
@RegisterClientHeaders(RequestUUIDHeaderFactory.class)
public interface ExtensionsService {
@GET
Set<Extension> getById(@QueryParam String id);
@GET
CompletionStage<Set<Extension>> getByIdAsync(@QueryParam String id);
@GET
Uni<Set<Extension>> getByIdAsUni(@QueryParam String id);
}
而 RequestUUIDHeaderFactory
将类似如下所示:
And the RequestUUIDHeaderFactory
would look like:
package org.acme.rest.client;
import org.eclipse.microprofile.rest.client.ext.ClientHeadersFactory;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.ws.rs.core.MultivaluedHashMap;
import jakarta.ws.rs.core.MultivaluedMap;
import java.util.UUID;
@ApplicationScoped
public class RequestUUIDHeaderFactory implements ClientHeadersFactory {
@Override
public MultivaluedMap<String, String> update(MultivaluedMap<String, String> incomingHeaders, MultivaluedMap<String, String> clientOutgoingHeaders) {
MultivaluedMap<String, String> result = new MultivaluedHashMap<>();
result.add("X-request-uuid", UUID.randomUUID().toString());
return result;
}
}
正如你在上面的示例中看到的,你可以通过用范围定义声明(例如 @Singleton
、@ApplicationScoped
等)对 ClientHeadersFactory
实现进行声明,将其变成一个 CDI Bean。
As you see in the example above, you can make your ClientHeadersFactory
implementation a CDI bean by
annotating it with a scope-defining annotation, such as @Singleton
, @ApplicationScoped
, etc.
Default header factory
你还可以使用没有指定任何自定义工厂的 @RegisterClientHeaders
声明。在这种情况下,将使用 DefaultClientHeadersFactoryImpl
工厂,并将修改 org.eclipse.microprofile.rest.client.propagateHeaders
配置属性中列出的所有头文件。各个头文件名称以逗号分隔。
You can also use @RegisterClientHeaders
annotation without any custom factory specified. In that case the DefaultClientHeadersFactoryImpl
factory will be used and all headers listed in org.eclipse.microprofile.rest.client.propagateHeaders
configuration property will be amended. Individual header names are comma-separated.
@Path("/extensions")
@RegisterRestClient
@RegisterClientHeaders
public interface ExtensionsService {
@GET
Set<Extension> getById(@QueryParam String id);
@GET
CompletionStage<Set<Extension>> getByIdAsync(@QueryParam String id);
@GET
Uni<Set<Extension>> getByIdAsUni(@QueryParam String id);
}
org.eclipse.microprofile.rest.client.propagateHeaders=Authorization,Proxy-Authorization
Package and run the application
使用以下内容运行应用程序:
Run the application with:
Unresolved directive in resteasy-client.adoc - include::{includes}/devtools/dev.adoc[]
使用 [role="bare"][role="bare"]http://localhost:8080/extension/id/io.quarkus:quarkus-rest-client 打开你的浏览器。
Open your browser to [role="bare"]http://localhost:8080/extension/id/io.quarkus:quarkus-rest-client.
你应该会看到一个 JSON 对象,其中包含有关 REST 客户端扩展的一些基本信息。
You should see a JSON object containing some basic information about the REST Client extension.
和往常一样,可以使用以下命令打包应用程序:
As usual, the application can be packaged using:
Unresolved directive in resteasy-client.adoc - include::{includes}/devtools/build.adoc[]
并且使用 java -jar target/quarkus-app/quarkus-run.jar
执行。
And executed with java -jar target/quarkus-app/quarkus-run.jar
.
你还可以按如下方式生成本机可执行文件:
You can also generate the native executable with:
Unresolved directive in resteasy-client.adoc - include::{includes}/devtools/build-native.adoc[]
REST Client and RESTEasy interactions
在 Quarkus 中,REST 客户端扩展和 the RESTEasy extension 共享相同的架构。这一考虑的一个重要后果是它们共享相同的提供程序列表(在 Jakarta REST 的术语意义上)。
In Quarkus, the REST Client extension and the RESTEasy extension share the same infrastructure. One important consequence of this consideration is that they share the same list of providers (in the Jakarta REST meaning of the word).
例如,如果你声明一个 WriterInterceptor
,它将默认拦截服务器调用和客户端调用,但这可能不是期望的行为。
For instance, if you declare a WriterInterceptor
, it will by default intercept both the servers calls and the client calls,
which might not be the desired behavior.
但是,您可以更改此默认行为,并将一个提供程序约束为:
However, you can change this default behavior and constrain a provider to:
-
only consider client calls by adding the
@ConstrainedTo(RuntimeType.CLIENT)
annotation to your provider; -
only consider server calls by adding the
@ConstrainedTo(RuntimeType.SERVER)
annotation to your provider.
Using a Mock HTTP Server for tests
在某些情况下,你可能希望模拟远程端点(HTTP 服务器),而不是模拟客户端本身。这对于原生测试或程序化创建的客户端可能特别有用。
In some cases you may want to mock the remote endpoint - the HTTP server - instead of mocking the client itself. This may be especially useful for native tests, or for programmatically created clients.
你可以使用 Wiremock 轻松模拟 HTTP 服务器。Wiremock section of the Quarkus - Using the REST Client 详细介绍了如何设置该服务器。
You can easily mock an HTTP Server with Wiremock. The Wiremock section of the Quarkus - Using the REST Client describes how to set it up in detail.