A API HttpClient

Computação II - Ciência da Computação


Prof.: Danilo S. Carvalho

Nessa aula, vamos aprender sobre como enviar e responder à requisições usando a linguagem Java.


Ao final da aula, poderemos construir e enviar requisições usando as classes da API (Application Programming Interface) HttpClient.

Desde a sua versão 11, a linguagem Java oferece uma maneira simplificada de construir e enviar requisições HTTP em sua biblioteca padrão: a API HttpClient (java.net.http).


Uma API (Application Programming Interface) é um conjunto de classes, interfaces e seus métodos, que juntos atendem a um propósito de facilitar a realização de tarefas específicas pelo programador,


nesse caso a construção e envio de requisições HTTP e tratamento das respostas.

Os principais módulos da API HttpClient são as classes HttpClient, HttpRequest, e a interface HttpResponse.

São utilizadas de forma básica como mostrado à seguir:

Uma instância de HttpClient é criada a partir do método newBuilder() da classe HttpClient.

O método newBuilder() retorna uma instância de HttpClient.Builder uma classe responsável pela construção parametrizada de HttpClients (padrão de projeto Builder).

Definimos os parâmetros de construção do cliente usando métodos do builder e por fim, usamos o método build() para criar a instância de HttpClient.

Em seguida, precisamos criar uma instância de HttpRequest, para representar a requisição a ser enviada.

Similar à classe HttpClient, a classe HttpRequest também possui um builder, que nos permite parametrizar a criação da requisição.

Precisamos incluir no mínimo a URI que queremos requisitar do servidor. Nesse caso, usamos a URL da página dessa disciplina.

Realizamos então o envio da requisição pelo método send() da classe HttpClient.

Além da requisição, precisamos passar como argumento um objeto BodyHandler que define como a resposta do servidor será interpretada, pois há diversos formatos de recursos na Web, e podemos fazer a interpretação desses recursos no momento da recepção.

A interface HttpResponse é parametrizada por esse motivo.
Nesse exemplo, vamos apenas ler o conteúdo da resposta como uma string.

Entretanto, o envio da requisição pode lançar dois tipos diferentes de exceção: IOException (se a conexão falhar, por exemplo) e InterruptedException (se a requisição for interrompida por um dos dois lados).

Uma informação importante que podemos obter da resposta é o seu código de status. Um código entre 200 e 300 indica que a requisição foi atendida sem problemas.

Já um código diferente indica alguma condição especial: 300 (redirecionamentos), 400 (problemas com a requisição), 500 (problemas com o servidor). Por exemplo, o código 404 indica que o recurso requisitado não foi encontrado.

Por fim, podemos acessar o conteúdo da resposta (nesse caso como uma string) usando o método body() da interface HttpResponse.

                         
                            /*
                            import java.net.*;
                            import java.net.http.*;
                            import java.net.http.HttpClient.*;
                            */

                            ...

                            HttpClient cliente = HttpClient.newBuilder()
                                                           .version(Version.HTTP_2)
                                                           .followRedirects(Redirect.ALWAYS)
                                                           .build();
                        
                    
                        
                            /*
                            import java.net.*;
                            import java.net.http.*;
                            import java.net.http.HttpClient.*;
                            */

                            ...

                            HttpClient cliente = HttpClient.newBuilder()
                                                           .version(Version.HTTP_2)
                                                           .followRedirects(Redirect.ALWAYS)
                                                           .build();
                            
                            HttpRequest requisicao = HttpRequest.newBuilder()
                                                                .uri(URI.create("http://www.danilosc.ml/teaching/comp2/PLE"))
                                                                .build();
                        
                    
                        
                            /*
                            import java.net.*;
                            import java.net.http.*;
                            import java.net.http.HttpClient.*;
                            */

                            ...

                            HttpClient cliente = HttpClient.newBuilder()
                                                           .version(Version.HTTP_2)
                                                           .followRedirects(Redirect.ALWAYS)
                                                           .build();
                            
                            HttpRequest requisicao = HttpRequest.newBuilder()
                                                                .uri(URI.create("http://www.danilosc.ml/teaching/comp2/PLE"))
                                                                .build();

                            HttpResponse<String> resposta = cliente.send(requisicao, HttpResponse.BodyHandlers.ofString());
                        
                    
                        
                            /*
                            import java.io.IOException;
                            import java.net.*;
                            import java.net.http.*;
                            import java.net.http.HttpClient.*;
                            */

                            ...

                            HttpClient cliente = HttpClient.newBuilder()
                                                           .version(Version.HTTP_2)
                                                           .followRedirects(Redirect.ALWAYS)
                                                           .build();

                            HttpRequest requisicao = HttpRequest.newBuilder()
                                                                .uri(URI.create("http://www.danilosc.ml/teaching/comp2/PLE"))
                                                                .build();

                            try {
                                HttpResponse<String> resposta = cliente.send(requisicao, HttpResponse.BodyHandlers.ofString());
                            } 
                            catch (IOException e) {
                                System.err.println("Problema com a conexão");
                                e.printStackTrace();
                            } 
                            catch (InterruptedException e) {
                                System.err.println("Requisição interrompida");
                                e.printStackTrace();
                            }
                        
                    
                        
                            /*
                            import java.io.IOException;
                            import java.net.*;
                            import java.net.http.*;
                            import java.net.http.HttpClient.*;
                            */

                            ...

                            HttpClient cliente = HttpClient.newBuilder()
                                                           .version(Version.HTTP_2)
                                                           .followRedirects(Redirect.ALWAYS)
                                                           .build();

                            HttpRequest requisicao = HttpRequest.newBuilder()
                                                                .uri(URI.create("http://www.danilosc.ml/teaching/comp2/PLE"))
                                                                .build();

                            try {
                                HttpResponse<String> resposta = cliente.send(requisicao, HttpResponse.BodyHandlers.ofString());
                                int codStatus = resposta.statusCode();
                                
                                System.out.println(codStatus);
                                System.out.println(resposta.body());
                            } 
                            catch (IOException e) {
                                System.err.println("Problema com a conexão");
                                e.printStackTrace();
                            } 
                            catch (InterruptedException e) {
                                System.err.println("Requisição interrompida");
                                e.printStackTrace();
                            }
                        
                    

Podemos também interpretar o conteúdo da resposta utilizando um interpretador separado, já que nem todo recurso é um documento HTML.

No exemplo abaixo, interpretamos a reposta a uma requisição para o serviço Web de dados sobre COVID-19 como uma string JSON. A resposta pode ser vista nesse link.

A partir do objeto JSONObject (um mapa recursivo de objetos) da biblioteca JSON.simple, obtido da interpretação da resposta, podemos acessar os dados da resposta de forma organizada.

                        
                            /*
                            import java.io.IOException;
                            import java.net.*;
                            import java.net.http.*;
                            import java.net.http.HttpClient.*;

                            import org.json.simple.*;
                            import org.json.simple.parser.*;
                            */
                            
                            ...

                            HttpClient cliente = HttpClient.newBuilder()
                                                           .version(Version.HTTP_2)
                                                           .followRedirects(Redirect.ALWAYS)
                                                           .build();

                            HttpRequest requisicao = HttpRequest.newBuilder()
                                                                .uri(URI.create("https://api.covid19api.com/summary"))
                                                                .build();

                            try {
                                HttpResponse<String> resposta = cliente.send(requisicao, HttpResponse.BodyHandlers.ofString());
                                int codStatus = resposta.statusCode();
                                
                                try {
                                    JSONObject respostaJson = (JSONObject) new JSONParser().parse(resposta.body());
                                    JSONArray paises = (JSONArray) respostaJson.get("Countries");
                                    
                                    for (Object pais : paises) {
                                        String nomePais = (String)((JSONObject) pais).get("Country");
                                        if (nomePais.equals("Brazil")) {
                                            System.out.print("Total de mortos: ");
                                            System.out.println(((JSONObject) pais).get("TotalDeaths"));
                                            System.out.print("Total de recuperados: ");
                                            System.out.println(((JSONObject) pais).get("TotalRecovered"));
                                        }
                                    }
                                } 
                                catch (ParseException e) {
                                    System.err.println("Resposta inválida");
                                    e.printStackTrace();
                                }
                            } 
                            catch (IOException e) {
                                System.err.println("Problema com a conexão");
                                e.printStackTrace();
                            } 
                            catch (InterruptedException e) {
                                System.err.println("Requisição interrompida");
                                e.printStackTrace();
                            }
                        
                    

Sabemos agora como criar e enviar uma requisição HTTP usando Java, e também como receber e tratar a resposta de uma requisição.


Pratique o envio de requisições e a recepção de recursos em diferentes formatos.


Na próxima aula aprenderemos sobre como responder à requisições HTTP usando a API Servlet.

Perguntas:

  1. Que tipo de requisição foi exemplificado nessa aula: GET ou POST?
  2. Que outro tipo de interpretador podemos usar para tratar as respostas?

Exercício:

  1. Crie uma requisição para baixar a imagem presente na seguinte URL: http://musica.ufrj.br/images/logo/ufrj100anos.png
    e gravá-la em um arquivo local.

Até a próxima aula!