1. введение
В предыдущей статье мы сосредоточились на REST Easy серверной реализации JAX-RS 2.0 .
JAX-RS 2.0 представляет новый клиентский API, позволяющий выполнять HTTP-запросы к удаленным веб-службам RESTful. Jersey, Apache CXF, Restlet и REST Easy-это лишь подмножество наиболее популярных реализаций.
В этой статье мы рассмотрим, как использовать REST API , отправляя запросы с помощью RESTEasy API .
2. Настройка проекта
Добавьте в свой pom.xml следующая зависимость:
3.0.14.Final ... org.jboss.resteasy resteasy-client ${resteasy.version}
3. Код На Стороне Клиента
Клиентская реализация довольно проста, состоит из 3 основных классов:
- Клиент
- WebTarget
- Ответ
Интерфейс Client является построителем экземпляров WebTarget .
Веб-цель представляет собой отдельный URL-адрес или шаблон URL-адреса, из которого можно создавать дополнительные веб-цели подресурсов или вызывать запросы.
На самом деле существует два способа создания клиента:
- Стандартный способ, с помощью org.jboss.resteasy.client.Запрос клиента
- RESTeasy Proxy Framework : с помощью класса ResteasyClientBuilder
Здесь мы сосредоточимся на прокси-фреймворке RESTEasy.
Вместо использования аннотаций JAX-RS для сопоставления входящего запроса с методом веб-службы RESTful клиентская платформа создает HTTP-запрос, который она использует для вызова удаленной веб-службы RESTful.
Итак, давайте начнем писать интерфейс Java и использовать аннотации JAX-RS для методов и интерфейса.
3.1. Клиентский Интерфейс Сервисов
@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"); 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();
Обратите внимание, что клиентский API RESTEasy основан на Apache HttpClient .
Также обратите внимание, что после каждой операции нам нужно будет закрыть ответ, прежде чем мы сможем выполнить новую операцию. Это необходимо, поскольку по умолчанию клиенту доступно только одно HTTP-соединение.
Наконец, обратите внимание, как мы работаем непосредственно с DTOS – мы не имеем дело с логикой маршала/унмаршала в JSON или XML ; это происходит за кулисами с использованием JAXB или Jackson , поскольку класс Movie был правильно аннотирован .
3.4. Создание Запроса С Пулом Соединений
Одно замечание из предыдущего примера заключалось в том, что у нас было доступно только одно соединение. Если – например, мы попытаемся сделать:
Response batmanResponse = proxy.addMovie(batmanMovie); Response transformerResponse = proxy.addMovie(transformerMovie);
без вызова close() on batmanResponse – при выполнении второй строки будет выдано исключение:
java.lang.IllegalStateException: Invalid use of BasicClientConnManager: connection still allocated. Make sure to release the connection before allocating another one.
Опять же – это просто происходит, потому что по умолчанию HttpClient используется RESTEasy/| 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 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 .