RESTEasy Client API

1. Einleitung

Im vorherigen Artikel haben wir uns auf die serverseitige RESTEasy -Implementierung von JAX-RS 2.0 konzentriert .

JAX-RS 2.0 führt eine neue Client-API ein, mit der Sie HTTP-Anforderungen an Ihre Remote-RESTful-Webdienste senden können. Jersey, Apache CXF, Restlet und RESTEasy sind nur eine Teilmenge der beliebtesten Implementierungen.

In diesem Artikel erfahren Sie, wie Sie die REST-API verwenden, indem Sie Anforderungen mit einer RESTEasy-API senden .

2. Projekteinrichtung

Fügen Sie in Ihrer pom.xml die folgende Abhängigkeit hinzu:

 3.0.14.Final    org.jboss.resteasy resteasy-client ${resteasy.version}  ... 

3. Client-seitiger Code

Die Client-Implementierung besteht aus drei Hauptklassen:

    • Klient
    • WebTarget
    • Antwort

Die Client- Oberfläche ist ein Builder für WebTarget- Instanzen.

WebTarget stellt eine bestimmte URL oder URL-Vorlage dar, aus der Sie weitere WebTargets für Unterressourcen erstellen oder Anforderungen aufrufen können.

Es gibt zwei Möglichkeiten, einen Client zu erstellen:

  • Die Standardmethode mithilfe von org.jboss.resteasy.client.ClientRequest
  • RESTeasy Proxy Framework : Verwenden der ResteasyClientBuilder- Klasse

Wir werden uns hier auf das RESTEasy Proxy Framework konzentrieren.

Anstatt JAX-RS-Annotationen zu verwenden, um eine eingehende Anforderung Ihrer RESTFul-Webdienstmethode zuzuordnen, erstellt das Clientframework eine HTTP-Anforderung, die zum Aufrufen eines Remote-RESTful-Webdiensts verwendet wird.

Beginnen wir also damit, eine Java-Schnittstelle zu schreiben und JAX-RS-Annotationen für die Methoden und die Schnittstelle zu verwenden.

3.1. Die ServicesClient- Schnittstelle

@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. Die Filmklasse

@XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "movie", propOrder = { "imdbId", "title" }) public class Movie { protected String imdbId; protected String title; // getters and setters }

3.3. Die Anforderungserstellung

Wir werden jetzt einen Proxy-Client generieren, mit dem wir die API verwenden können:

String transformerImdbId = "tt0418279"; Movie transformerMovie = new Movie("tt0418279", "Transformer 2"); final String path = "//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(); 

Beachten Sie, dass die RESTEasy-Client-API auf dem Apache HttpClient basiert .

Beachten Sie auch, dass wir nach jeder Operation die Antwort schließen müssen, bevor wir eine neue Operation ausführen können. Dies ist erforderlich, da dem Client standardmäßig nur eine einzige HTTP-Verbindung zur Verfügung steht.

Beachten Sie abschließend, wie wir direkt mit den DTOs arbeiten. Wir beschäftigen uns nicht mit der Marshall- / Unmarshal-Logik von und zu JSON oder XML . Dies geschieht hinter den Kulissen mit JAXB oder Jackson, da die Movie- Klasse ordnungsgemäß mit Anmerkungen versehen wurde .

3.4. Die Anforderungserstellung mit Verbindungspool

Ein Hinweis aus dem vorherigen Beispiel war, dass wir nur eine einzige Verbindung zur Verfügung hatten. Wenn wir zum Beispiel versuchen:

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

ohne Aufruf von close () bei batmanResponse - eine Ausnahme wird ausgelöst, wenn die zweite Zeile ausgeführt wird:

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

Wieder - dies geschieht einfach , weil die Standard - Httpclient von Resteasy verwendet wird , ist org.apache.http.impl.conn.SingleClientConnManager - was natürlich nur eine einzige Verbindung zur Verfügung stellt.

Um diese Einschränkung zu umgehen, muss die RestEasyClient- Instanz jetzt anders erstellt werden (mit einem Verbindungspool):

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);

Jetzt können wir von einem ordnungsgemäßen Verbindungspool profitieren und mehrere Anforderungen über unseren Client ausführen, ohne dass die Verbindung jedes Mal freigegeben werden muss.

4. Fazit

In diesem kurzen Tutorial haben wir das RESTEasy Proxy Framework vorgestellt und damit eine supereinfache Client-API erstellt.

Das Framework bietet einige weitere Hilfsmethoden zum Konfigurieren eines Clients und kann als Spiegel gegenüber den serverseitigen JAX-RS-Spezifikationen definiert werden.

Das in diesem Artikel verwendete Beispiel ist als Beispielprojekt in GitHub verfügbar.