2.2. Jakarta RESTful Web 服务客户端


2.2.1. Jakarta RESTful Web Services 客户端 API

Jakarta RESTful Web Services 2.0 引入了一个新的客户端 API,用于将 HTTP 请求发送到远程 RESTful Web 服务。这是一个 流畅 的请求构建 API,包含 3 个主要类:

  • 客户端
  • Web 目标
  • 响应

客户端 接口是 Web 目标实例的构建器。WebTarget 代表用于构建子资源 Web 目标或调用请求的不同 URL 或 URL 模板。

可以通过两种方式创建客户端:标准方式,或使用 ResteasyClientBuilder 类。使用 ResteasyClientBuilder 类的优点是它提供了一些额外的帮助程序方法来配置您的客户端。

ResteasyClientBuilder 类提供这些帮助程序方法,但该类特定于 JBoss EAP API。如果要将应用程序迁移到新服务器,您必须重新构建应用程序。ResteasyClientBuilder 类依赖于 RESTEasy,并且类不可移植。

创建客户端的标准方式同时遵循 Jakarta RESTful Web 服务和 Jakarta EE API 规范,可在 Jakarta RESTful Web 服务实施中移植。

注意

为确保 Jakarta RESTful Web Services 应用保持可移植性,请遵循 Jakarta EE API 规范,并在可能的情况下使用 Jakarta EE API 应用。如果用例不支持使用 Jakarta EE API,则仅使用特定于 JBoss 的 API。

遵循这些准则可以帮助减少将应用迁移到其他服务器或新的 Jakarta EE 兼容 JBoss 实施时可能出现的问题数量。

使用标准方法创建客户端

以下示例显示了创建客户端的标准方法之一:

Client client = ClientBuilder.newClient();
Copy to Clipboard Toggle word wrap

另外,您可以使用另一种标准方法来创建客户端,如下例所示:

Client client = ClientBuilder.newBuilder().build();
WebTarget target = client.target("http://foo.com/resource");
Response response = target.request().get();
String value = response.readEntity(String.class);
response.close();  // You should close connections!
Copy to Clipboard Toggle word wrap
使用 ResteasyClientBuilder 类创建客户端

以下示例演示了使用 ResteasyClientBuilder 类来创建客户端:

ResteasyClient client = new ResteasyClientBuilder().build();
ResteasyWebTarget target = client.target("http://foo.com/resource");
Copy to Clipboard Toggle word wrap

通过 Jakarta RESTful Web Services 2.1,您可以向 ClientBuilder 类添加两种超时方法。超时方法是符合规格的方法,您可以使用它们,而不使用 RESTEasy 方法。

以下 ClientBuilder 规格兼容方法替换了一些已弃用的 RESTEasy 方法:

  • connectTimeout 方法替换了 create ConnectionTimeout 方法。

    connectTimeout 方法决定了客户端在进行新服务器连接时必须等待的时长。

  • readTimeout 方法替换了 socketTimeout 方法。

    readTimeout 方法决定了客户端必须等待来自服务器的响应的时长。

以下示例显示了 connectTimeout 和 readTimeout 方法 的指定值:

import javx.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Client;

Client client = ClientBuilder.newBuilder()
	       .connectTimeout(100, TimeUnit.SECONDS)
	       .readTimeout(2, TimeUnit.SECONDS)
	       .build();
Copy to Clipboard Toggle word wrap

请注意 ,readTimeout 适用于现有连接上已执行的请求。

注意

将 timeout 参数的值设置为零会导致服务器无限期等待。

RESTEasy 自动加载一组默认提供程序,其中包含 META-INF/services/javax.ws.rs.ext.Providers 文件中列出的所有类。另外,您可以通过方法调用 Client.configuration() 提供的配置对象手动注册其他提供程序、过滤器和拦截器。通过配置,您可以设置可能需要的配置属性。

每个 Web 目标 都有一个配置实例,它继承了与父实例注册的组件和属性。这可让您为每个目标资源设置特定的配置选项,例如用户名和密码。

其它资源

使用 RESTEasy 客户端类

您必须将 RESTEasy 客户端的以下依赖项添加到 Maven pom.xml 文件中:

<dependency>
	<groupId>org.jboss.resteasy</groupId>
	<artifactId>resteasy-client</artifactId>
	<version>VERSION_IN_EAP</version>
 </dependency>
Copy to Clipboard Toggle word wrap

有关使用 RESTEasy 客户端类 的工作示例,请参见 JBoss EAP 附带的 jaxrs-client 和 resteasy-jaxrs-client 快速入门。

客户端过滤器

客户端具有两种过滤器:

ClientRequestFilter
ClientRequestFilter 在通过线路将 HTTP 请求发送到服务器之前运行。ClientRequestFilter 也被允许中止请求执行并提供修剪的响应,而无需通过线路传输到服务器。
ClientResponseFilter
ClientResponseFilter 在从服务器收到响应后运行,但在取消托管响应正文之前。ClientResponseFilter 可以在将响应对象提交到应用代码之前对其进行修改。以下示例演示了这些概念:
// execute request filters
for (ClientRequestFilter filter : requestFilters) {
	filter.filter(requestContext);
	if (isAborted(requestContext)) {
    return requestContext.getAbortedResponseObject();
  }
}

// send request over the wire
response = sendRequest(request);

// execute response filters
for (ClientResponseFilter filter : responseFilters) {
	filter.filter(requestContext, responseContext);
}
Copy to Clipboard Toggle word wrap
将客户端过滤器注册到客户端请求

以下示例演示了如何将客户端过滤器注册到客户端请求:

client = ClientBuilder.newClient();
WebTarget base = client.target(generateURL("/") + "get");
base.register(ClientExceptionsCustomClientResponseFilter.class).request("text/plain").get();
Copy to Clipboard Toggle word wrap
客户端缓存

RESTEasy 能够设置客户端缓存。此缓存查找随服务器响应发回的 cache-control 标头。如果 cache-control 标头指定允许客户端缓存响应,RESTEasy 会将它缓存在本地内存中。

ResteasyWebTarget target = client.target(generateBaseUrl());
target.register(BrowserCacheFeature.class);
Copy to Clipboard Toggle word wrap
块编码支持

RESTEasy 为客户端 API 提供指定请求应在 区块传输 模式中发送的功能。可以通过两种方式指定 区块传输 模式,如下所示:

  • 您可以将 org.jboss.resteasy.client.jaxrs.ResteasyWebTarget 配置为以区块模式发送所有请求:

    ResteasyClient client = new ResteasyClientBuilder().build();
    ResteasyWebTarget target = client.target("http://localhost:8081/test");
    target.setChunked(b.booleanValue());
    Invocation.Builder request = target.request();
    Copy to Clipboard Toggle word wrap
  • 另外,您还可以将特定请求配置为以块模式发送:

    ResteasyClient client = new ResteasyClientBuilder().build();
    ResteasyWebTarget target = client.target("http://localhost:8081/test");
    ClientInvocationBuilder request = (ClientInvocationBuilder) target.request();
    request.setChunked(b);
    Copy to Clipboard Toggle word wrap

    javax.ws.rs.client.Invocation.Builder 类不同,org.jboss.resteasy.client.jaxrs.internal.ClientInvocationBuilder 是 RESTEasy 类。

注意

以块模式发送请求的能力取决于底层传输层。特别是,它取决于所使用的 org.jboss.resteasy.client.jaxrs.ClientHttpEngine 类的实施。目前,只有 ApacheHttpClient43Engine 和之前实施 ApacheHttpClient4Engine 的默认实施支持区块模式。这两个都位于 org.jboss.resteasy.client.jaxrs.engines 软件包中。如需更多信息,请参阅 通过 HTTP 客户端实施 RESTEasy 部分。

2.2.2. 使用 HTTP 客户端实施 RESTEasy

默认情况下,在 RESTEasy 中处理客户端和服务器之间的网络通信。它使用 Apache Http Components 项目中的 Http Client。RESTEasy 客户端框架和网络之间的接口由 ClientHttpEngine 接口定义。

RESTEasy 随附此接口的四种实施:默认实施是 ApacheHttpClient43Engine。此实施使用 Apache 4.3。

ApacheHttpClient4Engine 是一种使用比 Apache 4.3 更早的版本的实现。此类提供向后兼容性。RESTEasy 根据 Apache 版本检测自动选择这两个 ClientHttpEngine 实施之一。InMemoryClientEngine 是一种将请求分配到同一 JVM 中的服务器的实施,而 URLConnectionEngine 则是使用 java.net.HttpURLConnection 的一种实施。

客户端执行器可以传递给特定的 ClientRequest

ResteasyClient client = new
ResteasyClientBuilder().httpEngine(engine).build();
Copy to Clipboard Toggle word wrap

RESTEasy 和 HttpClient 做出默认决策以使用客户端框架,而无需引用 HttpClient。但是,在某些应用中,可能需要深入查看 HttpClient 详细信息。ApacheHttpClient43EngineApacheHttpClient4Engine 可以提供 org.apache.http.client.HttpClientorg.apache.http.protocol.HttpContext 的实例,它们将额外的配置详细信息传输到 HttpClient 层。例如,身份验证可以配置如下:

// Configure HttpClient to authenticate preemptively
// by prepopulating the authentication data cache.

// 1. Create AuthCache instance
AuthCache authCache = new BasicAuthCache();

// 2. Generate BASIC scheme object and add it to the local auth cache
AuthScheme basicAuth = new BasicScheme();
authCache.put(new HttpHost("sippycups.bluemonkeydiamond.com"), basicAuth);

// 3. Add AuthCache to the execution context
BasicHttpContext localContext = new BasicHttpContext();
localContext.setAttribute(ClientContext.AUTH_CACHE, authCache);

// 4. Create client executor and proxy
HttpClient httpClient = HttpClientBuilder.create().build();
ApacheHttpClient4Engine engine = new ApacheHttpClient4Engine(httpClient, localContext);
ResteasyClient client = new ResteasyClientBuilder().httpEngine(engine).build();
Copy to Clipboard Toggle word wrap

HttpContextProvider 是 RESTEasy 提供的接口,您可以使用它为 Apache Http Client43Engine 和 ApacheHttpClient4Engine 实施提供自定义 Http Context

注意

了解 释放 连接 和关闭 连接之间的区别非常重要。释放连接使其可以重复利用。关闭连接会释放其资源,使其无法使用。

RESTEasy 在没有通知的情况下释放连接。唯一的计数器示例是响应是 InputStream 实例,它必须显式关闭。

另一方面,如果调用的结果是 Response 实例,则必须使用 Response .close() 方法来释放连接。

WebTarget target = client.target("http://localhost:8081/customer/123");
Response response = target.request().get();
System.out.println(response.getStatus());
response.close();
Copy to Clipboard Toggle word wrap

您可以在一个 试用的 块中执行此操作。释放连接使其可用于另一用途。它通常不关闭套接字。

如果创建了任何开放的套接字,ApacheHttpClient4Engine.finalize() 将关闭它一直使用的 HttpClient。依靠 JDK 调用 finalize() 并不安全。如果 HttpClient 传递给 ApacheHttpClient4Executor,用户必须关闭连接,如下所示:

HttpClient httpClient = new HttpClientBuilder.create().build();
ApacheHttpClient4Engine executor = new ApacheHttpClient4Engine(httpClient);
...
httpClient.getConnectionManager().shutdown();
Copy to Clipboard Toggle word wrap
注意

如果 ApacheHttpClient4Engine 创建了自己的 HttpClient 实例,则无需等待 finalize() 关闭打开套接字。ClientHttpEngine 接口具有一个 close() 方法来实现这一目的。

最后,如果 javax.ws.rs.client.Client 类已自动创建引擎,请调用 Client.close( )。这个调用会清理任何套接字连接。

2.2.2.1. HTTP 重定向

基于 Apache H ttpClient 的 ClientHttpEngine 实施支持 HTTP 重定向。默认情况下禁用此资源。您可以通过将 setFollowRedirects 方法设置为 true 来启用 此功能,如下所示:

ApacheHttpClient43Engine engine = new ApacheHttpClient43Engine();
engine.setFollowRedirects(true);
Client client = new ResteasyClientBuilder().httpEngine(engine).build();
Copy to Clipboard Toggle word wrap
Red Hat logoGithubredditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。 了解我们当前的更新.

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

Theme

© 2026 Red Hat
返回顶部