«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.
«