Una guida a Google-Http-Client

1. Panoramica

In questo articolo daremo uno sguardo alla libreria client HTTP di Google per Java, che è una libreria veloce e ben astratta per accedere a qualsiasi risorsa tramite il protocollo di connessione HTTP.

Le caratteristiche principali del cliente sono:

  • un livello di astrazione HTTP che consente di disaccoppiare qualsiasi libreria di basso livello
  • modelli di analisi JSON e XML veloci, efficienti e flessibili della risposta HTTP e del contenuto della richiesta
  • annotazioni e astrazioni facili da usare per le mappature delle risorse HTTP

La libreria può essere utilizzata anche in Java 5 e versioni successive, rendendola una scelta considerevole per i progetti legacy (SE ed EE).

In questo articolo, svilupperemo una semplice applicazione che si connetterà all'API di GitHub e recupererà gli utenti , coprendo alcune delle funzionalità più interessanti della libreria.

2. Dipendenze di Maven

Per utilizzare la libreria avremo bisogno della dipendenza google-http-client :

 com.google.http-client google-http-client 1.23.0 

L'ultima versione può essere trovata su Maven Central.

3. Effettuare una semplice richiesta

Cominciamo con una semplice richiesta GET alla pagina GitHub per mostrare come funziona il client Http di Google fuori dagli schemi:

HttpRequestFactory requestFactory = new NetHttpTransport().createRequestFactory(); HttpRequest request = requestFactory.buildGetRequest( new GenericUrl("//github.com")); String rawResponse = request.execute().parseAsString()

Per rendere la richiesta più semplice avremo bisogno almeno di:

  • HttpRequestFactory viene utilizzato per creare le nostre richieste
  • HttpTransport un'astrazione del livello di trasporto HTTP di basso livello
  • GenericUrl una classe che racchiude il file Url
  • HttpRequest gestisce l'effettiva esecuzione della richiesta

Esamineremo tutti questi e un esempio più complesso con un'API effettiva che restituisce un formato JSON nelle sezioni seguenti.

4. Pluggable HTTP Transport

La libreria ha una classe HttpTransport ben astratta che ci consente di costruire su di essa e di passare alla libreria di trasporto HTTP di basso livello sottostante di scelta :

public class GitHubExample { static HttpTransport HTTP_TRANSPORT = new NetHttpTransport(); }

In questo esempio, stiamo usando NetHttpTransport , che si basa su HttpURLConnection che si trova in tutti gli SDK Java. Questa è una buona scelta di partenza poiché è ben nota e affidabile.

Naturalmente, potrebbe esserci il caso in cui abbiamo bisogno di una personalizzazione avanzata, e quindi il requisito di una libreria di basso livello più complessa.

Per questo tipo di casi, c'è ApacheHttpTransport:

public class GitHubExample { static HttpTransport HTTP_TRANSPORT = new ApacheHttpTransport(); }

L'ApacheHttpTransport si basa sul popolare Apache HttpClient che comprende una vasta gamma di scelte per i collegamenti di configurazione.

Inoltre, la libreria offre la possibilità di creare la tua implementazione di basso livello, rendendola molto flessibile.

5. Analisi JSON

Il client Http di Google include un'altra astrazione per l'analisi JSON. Uno dei principali vantaggi di ciò è che la scelta della libreria di analisi di basso livello è intercambiabile .

Ci sono tre scelte integrate, che estendono tutte JsonFactory e includono anche la possibilità di implementare la nostra.

5.1. Libreria di analisi intercambiabile

Nel nostro esempio, utilizzeremo l'implementazione Jackson2, che richiede la dipendenza google-http-client-jackson2 :

 com.google.http-client google-http-client-jackson2 1.23.0 

Successivamente, possiamo ora includere JsonFactory:

public class GitHubExample { static HttpTransport HTTP_TRANSPORT = new NetHttpTransport(); staticJsonFactory JSON_FACTORY = new JacksonFactory(); }

Il JacksonFactory è la biblioteca più veloce e più popolare per le operazioni di analisi / serializzazione.

Ciò viene a scapito delle dimensioni della libreria (che potrebbe essere un problema in determinate situazioni). Per questo motivo, Google fornisce anche GsonFactory , che è un'implementazione della libreria Google GSON, una libreria di analisi JSON leggera.

C'è anche la possibilità di scrivere la nostra implementazione del parser di basso livello.

5.2. L' annotazione chiave @

Possiamo utilizzare l' annotazione @Key per indicare i campi che devono essere analizzati o serializzati in JSON:

public class User { @Key private String login; @Key private long id; @Key("email") private String email; // standard getters and setters }

Qui stiamo facendo un'astrazione utente , che riceviamo in batch dall'API GitHub (arriveremo all'analisi effettiva più avanti in questo articolo) .

Tieni presente che i campi che non hanno l' annotazione @Key sono considerati interni e non vengono analizzati o serializzati in JSON . Inoltre, la visibilità dei campi non ha importanza, né l'esistenza dei metodi getter o setter.

Possiamo specificare il valore dell'annotazione @Key , per mapparlo alla chiave JSON corretta.

5.3. GenericJson

Vengono analizzati solo i campi che dichiariamo e contrassegniamo come @Key .

Per mantenere gli altri contenuti, possiamo dichiarare che la nostra classe estenda GenericJson:

public class User extends GenericJson { //... }

GenericJson implementa l' interfaccia Map , il che significa che possiamo usare i metodi get e put per impostare / ottenere contenuto JSON nella richiesta / risposta.

6. Effettuare la chiamata

Per connettersi a un endpoint con il client Http di Google, avremo bisogno di un HttpRequestFactory , che verrà configurato con le nostre astrazioni precedenti HttpTransport e JsonFactory:

public class GitHubExample { static HttpTransport HTTP_TRANSPORT = new NetHttpTransport(); static JsonFactory JSON_FACTORY = new JacksonFactory(); private static void run() throws Exception { HttpRequestFactory requestFactory = HTTP_TRANSPORT.createRequestFactory( (HttpRequest request) -> { request.setParser(new JsonObjectParser(JSON_FACTORY)); }); } }

La prossima cosa di cui avremo bisogno è un URL a cui connetterci. La libreria lo gestisce come una classe che estende GenericUrl su cui qualsiasi campo dichiarato viene trattato come un parametro di query:

public class GitHubUrl extends GenericUrl { public GitHubUrl(String encodedUrl) { super(encodedUrl); } @Key public int per_page; }

Qui nel nostro GitHubUrl, dichiariamo la proprietà per_page per indicare quanti utenti vogliamo in una singola chiamata all'API GitHub.

Continuiamo a creare la nostra chiamata utilizzando GitHubUrl:

private static void run() throws Exception { HttpRequestFactory requestFactory = HTTP_TRANSPORT.createRequestFactory( (HttpRequest request) -> { request.setParser(new JsonObjectParser(JSON_FACTORY)); }); GitHubUrl url = new GitHubUrl("//api.github.com/users"); url.per_page = 10; HttpRequest request = requestFactory.buildGetRequest(url); Type type = new TypeToken
    
     () {}.getType(); List users = (List)request .execute() .parseAs(type); }
    

Notice how we specify how many users we'll need for the API call, and then we build the request with the HttpRequestFactory.

Following this, since the GitHub API's response contains a list of users, we need to provide a complex Type, which is a List.

Then, on the last line, we make the call and parse the response to a list of our User class.

7. Custom Headers

One thing we usually do when making an API request is to include some kind of custom header or even a modified one:

HttpHeaders headers = request.getHeaders(); headers.setUserAgent("Baeldung Client"); headers.set("Time-Zone", "Europe/Amsterdam");

We do this by getting the HttpHeaders after we've created our request but before executing it and adding the necessary values.

Please be aware that the Google Http Client includes some headers as special methods. The User-Agent header for example, if we try to include it with just the set method it would throw an error.

8. Exponential Backoff

Another important feature of the Google Http Client is the possibility to retry requests based on certain status codes and thresholds.

We can include our exponential backoff settings right after we've created our request object:

ExponentialBackOff backoff = new ExponentialBackOff.Builder() .setInitialIntervalMillis(500) .setMaxElapsedTimeMillis(900000) .setMaxIntervalMillis(6000) .setMultiplier(1.5) .setRandomizationFactor(0.5) .build(); request.setUnsuccessfulResponseHandler( new HttpBackOffUnsuccessfulResponseHandler(backoff));

Exponential Backoff is turned off by default in HttpRequest, so we must include an instance of HttpUnsuccessfulResponseHandler to the HttpRequest to activate it.

9. Logging

The Google Http Client uses java.util.logging.Logger for logging HTTP request and response details, including URL, headers, and content.

Commonly, logging is managed using a logging.properties file:

handlers = java.util.logging.ConsoleHandler java.util.logging.ConsoleHandler.level = ALL com.google.api.client.http.level = ALL

In our example we use ConsoleHandler, but it's also possible to choose the FileHandler.

The properties file configures the operation of the JDK logging facility. This config file can be specified as a system property:

-Djava.util.logging.config.file=logging.properties

So after setting the file and system property, the library will produce a log like the following:

-------------- REQUEST -------------- GET //api.github.com/users?page=1&per_page=10 Accept-Encoding: gzip User-Agent: Google-HTTP-Java-Client/1.23.0 (gzip) Nov 12, 2017 6:43:15 PM com.google.api.client.http.HttpRequest execute curl -v --compressed -H 'Accept-Encoding: gzip' -H 'User-Agent: Google-HTTP-Java-Client/1.23.0 (gzip)' -- '//api.github.com/users?page=1&per_page=10' Nov 12, 2017 6:43:16 PM com.google.api.client.http.HttpResponse -------------- RESPONSE -------------- HTTP/1.1 200 OK Status: 200 OK Transfer-Encoding: chunked Server: GitHub.com Access-Control-Allow-Origin: * ... Link: ; rel="next", ; rel="first" X-GitHub-Request-Id: 8D6A:1B54F:3377D97:3E37B36:5A08DC93 Content-Type: application/json; charset=utf-8 ...

10. Conclusion

In this tutorial, we've shown the Google HTTP Client Library for Java and its more useful features. Their Github contains more information about it as well as the source code of the library.

Come sempre, il codice sorgente completo di questo tutorial è disponibile su GitHub.