Una guía para Google-Http-Client

1. Información general

En este artículo, veremos la biblioteca de cliente HTTP de Google para Java, que es una biblioteca rápida y bien resumida para acceder a cualquier recurso a través del protocolo de conexión HTTP.

Las principales características del cliente son:

  • una capa de abstracción HTTP que le permite desacoplar cualquier biblioteca de bajo nivel
  • Modelos de análisis JSON y XML rápidos, eficientes y flexibles de la respuesta HTTP y el contenido de la solicitud
  • anotaciones y abstracciones fáciles de usar para asignaciones de recursos HTTP

La biblioteca también se puede usar en Java 5 y superior, lo que la convierte en una opción considerable para proyectos heredados (SE y EE).

En este artículo, vamos a desarrollar una aplicación simple que se conectará a la API de GitHub y recuperará usuarios , mientras cubre algunas de las características más interesantes de la biblioteca.

2. Dependencias de Maven

Para usar la biblioteca, necesitaremos la dependencia google-http-client :

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

La última versión se puede encontrar en Maven Central.

3. Hacer una solicitud simple

Comencemos haciendo una simple solicitud GET a la página de GitHub para mostrar cómo funciona el cliente Http de Google de inmediato:

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

Para hacer la solicitud más simple, necesitaremos al menos:

  • HttpRequestFactory esto se usa para construir nuestras solicitudes
  • HttpTransport una abstracción de la capa de transporte HTTP de bajo nivel
  • GenericUrl una clase que envuelve la URL
  • HttpRequest maneja la ejecución real de la solicitud

Revisaremos todos estos y un ejemplo más complejo con una API real que devuelve un formato JSON en las siguientes secciones.

4. Transporte HTTP conectable

La biblioteca tiene una clase HttpTransport bien abstraída que nos permite construir sobre ella y cambiar a la biblioteca de transporte HTTP subyacente de bajo nivel de elección :

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

En este ejemplo, usamos NetHttpTransport , que se basa en HttpURLConnection que se encuentra en todos los SDK de Java. Ésta es una buena opción de partida ya que es conocida y confiable.

Por supuesto, podría darse el caso de que necesitemos una personalización avanzada y, por lo tanto, el requisito de una biblioteca de bajo nivel más compleja.

Para este tipo de casos, existe ApacheHttpTransport:

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

El ApacheHttpTransport se basa en el popular Apache HttpClient que incluye una gran variedad de opciones a las conexiones de configure.

Además, la biblioteca ofrece la opción de crear su implementación de bajo nivel, lo que la hace muy flexible.

5. Análisis JSON

El cliente Http de Google incluye otra abstracción para el análisis JSON. Una de las principales ventajas de esto es que la elección de la biblioteca de análisis de bajo nivel es intercambiable .

Hay tres opciones integradas, todas las cuales amplían JsonFactory, y también incluye la posibilidad de implementar la nuestra.

5.1. Biblioteca de análisis intercambiable

En nuestro ejemplo, usaremos la implementación de Jackson2, que requiere la dependencia google-http-client-jackson2 :

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

Después de esto, ahora podemos incluir JsonFactory:

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

El JacksonFactory es la biblioteca más rápido y popular para las operaciones de análisis sintáctico / serialización.

Esto tiene como costo el tamaño de la biblioteca (que podría ser una preocupación en ciertas situaciones). Por esta razón, Google también proporciona GsonFactory , que es una implementación de la biblioteca GSON de Google, una biblioteca de análisis JSON liviana.

También existe la posibilidad de escribir nuestra implementación de analizador de bajo nivel.

5.2. La anotación @ clave

Podemos usar la anotación @Key para indicar campos que necesitan ser analizados o serializados en JSON:

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

Aquí estamos haciendo una abstracción de usuario , que recibimos por lotes de la API de GitHub (llegaremos al análisis real más adelante en este artículo) .

Tenga en cuenta que los campos que no tienen la anotación @Key se consideran internos y no se analizan ni se serializan en JSON . Además, la visibilidad de los campos no importa, ni la existencia de los métodos getter o setter.

Podemos especificar el valor de la anotación @Key , para asignarlo a la clave JSON correcta.

5.3. GenericJson

Solo se analizan los campos que declaramos y marcamos como @Key .

Para retener el otro contenido, podemos declarar nuestra clase para extender GenericJson:

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

GenericJson implementa la interfaz Map , lo que significa que podemos usar los métodos get y put para configurar / obtener contenido JSON en la solicitud / respuesta.

6. Hacer la llamada

Para conectarnos a un punto final con Google Http Client, necesitaremos una HttpRequestFactory , que se configurará con nuestras abstracciones anteriores HttpTransport y 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)); }); } }

Lo siguiente que necesitaremos es una URL a la que conectarnos. La biblioteca maneja esto como una clase que extiende GenericUrl en la que cualquier campo declarado se trata como un parámetro de consulta:

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

Aquí, en nuestra GitHubUrl, declaramos la propiedad per_page para indicar cuántos usuarios queremos en una sola llamada a la API de GitHub.

Continuemos construyendo nuestra llamada usando 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.

Como siempre, el código fuente completo de este tutorial está disponible en GitHub.