Nessa aula, vamos aprender sobre como enviar 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.com/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.com/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.com/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.com/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:
Exercício:
Até a próxima aula!