1. 簡介
在上一篇文章中,我們重點介紹了 RESTEasy 服務器端實現 JAX-RS 2.0。
JAX-RS 2.0 引入了一個新的客户端 API,以便您可以向您的遠程 RESTful Web 服務發送 HTTP 請求。 Jersey、Apache CXF、Restlet 和 RESTEasy 只是最受歡迎的實現方案中的一部分。
在本文中,我們將探討如何通過使用 RESTEasy API 發送請求來消費 REST 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代表一個獨立的 URL 或 URL 模板,你可以從中構建更多的子資源WebTarget或發起請求。
創建Client 有兩種主要方式:
- 標準方式是使用 org.jboss.resteasy.client.ClientRequest
- RESTEasy 代理框架:通過使用 ResteasyClientBuilder 類
我們將重點關注 RESTEasy 代理框架。
而不是使用 JAX-RS 註解將傳入的請求映射到你的 RESTful Web Service 方法,客户端框架會構建一個 HTTP 請求,用於發起到遠程 RESTful Web Service 的請求。
所以讓我們開始編寫一個 Java 接口並使用 JAX-RS 註解在方法和接口上。
3.1. <em dịch vụClient 接口
@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.2. 電影類
@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 – 我們沒有處理到和從 JSON 或 XML 進行 marshal/unmarshal 的邏輯,這在幕後使用 JAXB 或 Jackson,因為 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.
再次説明——這僅僅是因為 RESTEasy 默認使用的 HttpClient 是 org.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 服務器端規範的鏡像反向。