RESTEasy Client API – RESTEasy客户端API

最后修改: 2016年 2月 19日

中文/混合/英文(键盘快捷键:t)

1. Introduction

1.介绍

In the previous article, we focused on the RESTEasy server-side implementation of JAX-RS 2.0.

前一篇文章中,我们重点介绍了RESTEasyJAX-RS 2.0的服务器端实现。

JAX-RS 2.0 introduces a new client API so that you can make HTTP requests to your remote RESTful web services. Jersey, Apache CXF, Restlet, and RESTEasy are only a subset of the most popular implementations.

JAX-RS 2.0引入了一个新的客户端API,这样您就可以向您的远程RESTful Web服务发出HTTP请求。Jersey、Apache CXF、Restlet和RESTEasy只是最流行的实现方式的一个子集。

In this article, we’ll explore how to consume the REST API by sending requests with a RESTEasy API.

在这篇文章中,我们将探讨如何通过使用RESTEasy API发送请求来消费REST API

2. Project Setup

2.项目设置

Add in your pom.xml the following dependencies:

在你的pom.xml中添加以下依赖项。

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

    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>4.0.1</version>
    </dependency>
    ...
</dependencies>

3. Client-Side Code

3.客户端代码

The client implementation is quite small, being made up of 3 main classes:

客户端的实现是相当小的,由3个主要的类组成。

    • Client
    • WebTarget
    • Response

The Client interface is a builder of WebTarget instances.

Client接口是WebTarget实例的构建者。

WebTarget represents a distinct URL or URL template from which you can build more sub-resource WebTargets or invoke requests.

WebTarget代表了一个独特的URL或URL模板,您可以从中建立更多的子资源WebTarget或调用请求。

There are really two ways to create a Client:

实际上有两种方法来创建客户。

  • The standard way is using the org.jboss.resteasy.client.ClientRequest
  • RESTeasy Proxy Framework: by using the ResteasyClientBuilder class

We will focus on the RESTEasy Proxy Framework here.

我们在这里将重点讨论RESTEasy代理框架。

Instead of using JAX-RS annotations to map an incoming request to your RESTFul Web Service method, the client framework builds an HTTP request that it uses to invoke on a remote RESTful Web Service.

客户端框架不是使用 JAX-RS 注释来将传入的请求映射到您的 RESTFul Web 服务方法,而是建立一个 HTTP 请求,用来在远程 RESTful Web 服务上调用。

So let’s start writing a Java interface and using JAX-RS annotations on the methods and on the interface.

所以让我们开始写一个Java接口,并在方法和接口上使用JAX-RS注解。

3.1. The ServicesClient Interface

3.1.ServicesClient 接口

@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. The Movie Class

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. The Request Creation

3.3.请求创建

We’ll now generate a proxy client that we can use to consume the API:

现在我们将生成一个代理客户端,我们可以用它来消费该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();

Note that the RESTEasy client API is based on the Apache HttpClient.

请注意,RESTEasy客户端API是基于Apache的HttpClient

Also note that, after each operation, we’ll need to close the response before we can perform a new operation. This is necessary because, by default, the client only has a single HTTP connection available.

还要注意的是,在每次操作之后,我们都需要在执行新的操作之前关闭响应。这是必要的,因为在默认情况下,客户端只有一个HTTP连接可用。

Finally, note how we’re working with the DTOs directly – we’re not dealing with the marshal/unmarshal logic to and from JSON or XML; that happens behind the scenes using JAXB or Jackson since the Movie class was properly annotated.

最后,请注意我们是如何直接处理DTO的–我们没有处理与JSONXML之间的marshal/unmarshal逻辑;这发生在幕后,使用JAXBJackson,因为Movie类被正确注释了

3.4. The Request Creation With Connection Pool

3.4.使用连接池创建请求

One note from the previous example was that we only had a single connection available. If – for example, we try to do:

前面的例子中的一个注意点是,我们只有一个可用的连接。如果–比如说,我们尝试做。

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

without invoke close() on batmanResponse – an exception will be thrown when the second line is executed:

不对batmanResponse调用close()–在执行第二行时将会抛出一个异常。

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

Again – this simply happens because the default HttpClient used by RESTEasy is org.apache.http.impl.conn.SingleClientConnManager – which of course only makes a single connection available.

同样–这只是因为RESTEasy使用的默认HttpClientorg.apache.http.impl.conn.SingleClientConnManager–它当然只提供单一连接。

Now – to work around that limitation – the RestEasyClient instance must be created differently (with a connection pool):

现在–为了绕过这个限制– 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);

Now we can benefit from a proper connection pool and can have multiple requests running through our client without necessarily having to release the connection each time.

现在我们可以受益于一个适当的连接池,并且可以通过我们的客户端运行多个请求,而不一定每次都要释放连接。

4. Conclusion

4.结论

In this quick tutorial, we introduced the RESTEasy Proxy Framework and we built a super simple client API with it.

在这个快速教程中,我们介绍了RESTEasy Proxy Framework ,并利用它构建了一个超级简单的客户端API。

The framework gives us a few more helper methods to configure a client and can be defined as the mirror opposite of the JAX-RS server-side specifications.

该框架给我们提供了一些更多的辅助方法来配置客户端,可以定义为JAX-RS服务器端规范的镜像。

The example used in this article is available as a sample project on GitHub.

本文中使用的示例可作为GitHub上的示例项目