RESTEasy 客户端 API

HTTP Client-Side,REST
Remote
0
04:34 PM · Dec 01 ,2025

1. 簡介

在上一篇文章中,我們重點介紹了 RESTEasy 服務器端的 JAX-RS 2.0 實現。

JAX-RS 2.0 引入了一個新的客户端 API,以便您可以向您的遠程 RESTful Web 服務發送 HTTP 請求。 Jersey、Apache CXF、Restlet 和 RESTEasy 只是最流行的實現中的一部分。

在本文中,我們將探討如何通過使用 REST API 併發送請求來使用 RESTEasy API

2. 項目設置

在您的 pom.xml

中添加以下依賴項:

<properties>
    <resteasy.version>6.2.9.Final</resteasy.version>
</properties>
<dependencies>
    <dependency>
        <groupId>org.jboss.resteasy</groupId>
        <artifactId>resteasy-client</artifactId>
        <version>${resteasy.version}</version>
    </dependency>

    <dependency>
        <groupId>jakarta.servlet</groupId>
        <artifactId>jakarta.servlet-api</artifactId>
        <version>6.1.0</version>
    </dependency>
    ...
</dependencies>

3. 客户端代碼

客户端實現相當小,由 3 個主要類組成:

    • Client
    • WebTarget
    • Response

Client 接口是WebTarget實例的構建器。

WebTarget代表一個從您可以使用構建更多子資源WebTarget或調用請求的唯一 URL 或 URL 模板。

有兩點方式可以創建Client

  • 標準方式是使用org.jboss.resteasy.client.ClientRequest
  • RESTeasy 代理框架:通過使用ResteasyClientBuilder

我們將重點關注RESTeasy 代理框架。

而不是使用 JAX-RS 註解將傳入請求映射到您的 RESTFul Web Service 方法,客户端框架會構建一個用於調用遠程 RESTful Web Service 的 HTTP 請求。

因此,讓我們開始編寫 Java 接口並使用 JAX-RS 註解在方法和接口上。

@Path("/movies")
public interface ServicesInterface {

    @GET
    @Path("/getinfo")
    @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
    Movie movieByImdbId(@QueryParam("imdbId") String imdbId);

    @POST
    @Path("/addmovie")
    @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
    Response addMovie(Movie movie);

    @PUT
    @Path("/updatemovie")
    @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
    Response updateMovie(Movie movie);

    @DELETE
    @Path("/deletemovie")
    Response deleteMovie(@QueryParam("imdbId") String imdbId);
}

3.1. ServicesClient 接口

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "movie", propOrder = { "imdbId", "title" })
public class Movie {

    protected String imdbId;
    protected String title;

    // getters and setters
}

3.2. Movie

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "movie", propOrder = { "imdbId", "title" })
public class Movie {

    protected String imdbId;
    protected String title;

    // getters and setters
}

3.3. 請求創建

現在我們將生成一個我們可以用來消耗 API 的代理客户端:

String transformerImdbId = "tt0418279";
Movie transformerMovie = new Movie("tt0418279", "Transformer 2");
UriBuilder FULL_PATH = UriBuilder.fromPath("http://127.0.0.1:8082/resteasy/rest");
 
ResteasyClient client = (ResteasyClient)ClientBuilder.newClient();
ResteasyWebTarget target = client.target(FULL_PATH);
ServicesInterface proxy = target.proxy(ServicesInterface.class);

// POST
Response moviesResponse = proxy.addMovie(transformerMovie);
System.out.println("HTTP code: " + moviesResponse.getStatus());
moviesResponse.close();

// GET
Movie movies = proxy.movieByImdbId(transformerImdbId);

// PUT
transformerMovie.setTitle("Transformer 4");
moviesResponse = proxy.updateMovie(transformerMovie);
moviesResponse.close();

// DELETE
moviesResponse = proxy.deleteMovie(batmanMovie.getImdbId());
moviesResponse.close();

請注意,RESTeasy 客户端 API 基於 Apache HttpClient

請注意,在每次操作後,我們需要關閉響應,然後再可以執行新的操作。這是因為默認情況下,客户端只有一個 HTTP 連接可用。

最後,請注意我們如何使用 DTO 實際上——我們沒有處理傳入和從 JSONXML 到和從 DTO 的 marshal/unmarshal 邏輯,這發生在後台,使用 JAXBJackson,因為 Movie 類被正確地註釋了。

3.4. 使用連接池創建請求

在之前的示例中,我們只具有一個連接可用。如果,例如,我們嘗試執行:

Response batmanResponse = proxy.addMovie(batmanMovie);
Response transformerResponse = proxy.addMovie(transformerMovie);

而不調用 close()batmanResponse 上,則在第二個行執行時會拋出異常:

java.lang.IllegalStateException:
Invalid use of BasicClientConnManager: connection still allocated.
Make sure to release the connection before allocating another one.

再次,這僅僅是因為默認的 HttpClient,用於 RESTeasyorg.apache.http.impl.conn.SingleClientConnManager,當然只有一個連接可用。

為瞭解決這個問題,RestEasyClient 實例必須以不同的方式創建(使用連接池):

PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(cm).build();
cm.setMaxTotal(200); // Increase max total connection to 200
cm.setDefaultMaxPerRoute(20); // Increase default max connection per route to 20
ApacheHttpClient43Engine engine = new ApacheHttpClient43Engine(httpClient);

ResteasyClient client = ((ResteasyClientBuilder) ClientBuilder.newBuilder()).httpEngine(engine).build();
ResteasyWebTarget target = client.target(FULL_PATH);
ServicesInterface proxy = target.proxy(ServicesInterface.class);

現在我們可以從連接池中受益,並且可以使請求通過我們的客户端運行,而無需每次運行後手動釋放連接。

4. 結論

在本快速教程中,我們介紹了 RESTEasy 代理框架,並使用它構建了一個超簡單的客户端 API。

該框架為我們提供了更多輔助方法來配置客户端,並且可以定義為與 JAX-RS 服務器端規範的鏡像反向。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.