«1. Введение

В предыдущей статье мы сосредоточились на реализации JAX-RS 2.0 на стороне сервера RESTEasy.

JAX-RS 2.0 представляет новый клиентский API, позволяющий отправлять HTTP-запросы к удаленным веб-службам RESTful. Jersey, Apache CXF, Restlet и RESTEasy — это лишь часть наиболее популярных реализаций.

В этой статье мы рассмотрим, как использовать REST API, отправляя запросы с помощью RESTEasy API.

2. Настройка проекта

Добавьте в ваш pom.xml следующую зависимость:

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

3. Код на стороне клиента

Реализация клиента состоит из 3 основных классов: ~~ ~ Client WebTarget Response

    Клиентский интерфейс является построителем экземпляров WebTarget.

WebTarget представляет собой отдельный URL-адрес или шаблон URL-адреса, из которого вы можете создавать дополнительные WebTarget-субресурсы или вызывать запросы.

На самом деле существует два способа создания клиента:

Стандартный способ с использованием org.jboss.resteasy.client.ClientRequest RESTeasy Proxy Framework: с использованием класса ResteasyClientBuilder

    Мы сосредоточимся на RESTEasy Прокси Фреймворк здесь.

Вместо использования аннотаций JAX-RS для сопоставления входящего запроса с методом веб-службы RESTFul клиентская среда создает HTTP-запрос, который используется для вызова удаленной веб-службы RESTful.

Итак, давайте начнем писать интерфейс Java и использовать аннотации JAX-RS для методов и интерфейса.

3.1. Интерфейс ServicesClient

3.2. Кинокласс

@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.3. Создание запроса

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

    protected String imdbId;
    protected String title;

    // getters and setters
}

Теперь мы создадим прокси-клиент, который мы можем использовать для использования API:

Обратите внимание, что клиентский API RESTEasy основан на Apache HttpClient.

String transformerImdbId = "tt0418279";
Movie transformerMovie = new Movie("tt0418279", "Transformer 2");
final String path = "http://127.0.0.1:8080/RestEasyTutorial/rest"; 
 
ResteasyClient client = new ResteasyClientBuilder().build();
ResteasyWebTarget target = client.target(UriBuilder.fromPath(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();

Также обратите внимание, что после каждой операции нам нужно закрыть ответ, прежде чем мы сможем выполнить новую операцию. Это необходимо, потому что по умолчанию у клиента есть только одно доступное HTTP-соединение.

Наконец, обратите внимание, как мы работаем с DTO напрямую — мы не имеем дело с логикой маршалинга/демаршалирования в JSON или XML и обратно; это происходит за кулисами с использованием JAXB или Jackson, поскольку класс Movie был правильно аннотирован.

3.4. Создание запроса с пулом соединений

Одно замечание из предыдущего примера заключалось в том, что у нас было только одно доступное соединение. Если, например, мы пытаемся сделать:

без вызова close() в batmanResponse, при выполнении второй строки будет выдано исключение:

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

Снова — это просто происходит потому, что HttpClient по умолчанию, используемый RESTEasy, — это org.apache.http.impl.conn.SingleClientConnManager, что, конечно, делает доступным только одно соединение.

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

Теперь, чтобы обойти это ограничение, экземпляр 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
ApacheHttpClient4Engine engine = new ApacheHttpClient4Engine(httpClient);

ResteasyClient client = new ResteasyClientBuilder().httpEngine(engine).build();
ResteasyWebTarget target = client.target(UriBuilder.fromPath(path));
ServicesInterface proxy = target.proxy(ServicesInterface.class);

4. Заключение

В этом кратком руководстве мы представили RESTEasy Proxy Framework и создали с его помощью очень простой клиентский API.

Фреймворк дает нам еще несколько вспомогательных методов для настройки клиента и может быть определен как зеркальная противоположность серверным спецификациям JAX-RS.

Пример, использованный в этой статье, доступен как образец проекта на GitHub.

«