Java HttpURLConnection
Faça requisições HTTP em Java com a API legada HttpURLConnection.
HttpURLConnection é a subclasse de URLConnection voltada para HTTP. Ao chamar openConnection() em uma URL com esquema http: ou https:, o objeto retornado é um HttpURLConnection — faça o cast para acessar os recursos específicos do HTTP: definir o método da requisição, ler o código de status e obter o stream de erro separado. Trata-se do cliente HTTP original do JDK, disponível desde o Java 1.1.
Este capítulo aborda o cast da conexão e a escolha do método, o envio de um corpo de requisição, o código de status e os dois streams de resposta (a armadilha clássica do error stream), além de um exemplo completo de POST que você pode executar.
Nota moderna: para código novo, prefira
java.net.http.HttpClient— é mais limpo, suporta HTTP/2 e lida com operações assíncronas.HttpURLConnectionainda está presente em muitas bases de código legadas, por isso vale a pena conhecê-lo bem.
Cast e escolha do método
URL url = URI.create("http://example.com/api").toURL();
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST"); // GET is the default
conn.setRequestProperty("Content-Type", "application/json");
conn.setConnectTimeout(2000);
conn.setReadTimeout(2000);setRequestMethod aceita "GET", "POST", "PUT", "DELETE", entre outros. Adicione cabeçalhos de requisição com setRequestProperty.
Envio de um corpo de requisição
Para enviar um corpo, é necessário optar por isso com setDoOutput(true) (o que também define o método padrão como POST) e então escrever no stream de saída:
conn.setDoOutput(true);
try (OutputStream os = conn.getOutputStream()) {
os.write(payload.getBytes(StandardCharsets.UTF_8));
}Código de status e os dois streams
O recurso HTTP central é o código de status, e a armadilha que decorre dele:
int code = conn.getResponseCode(); // triggers the request
InputStream body = (code >= 200 && code < 400)
? conn.getInputStream() // success body
: conn.getErrorStream(); // error body (4xx/5xx)getInputStream() lança IOException em respostas 4xx/5xx. O corpo do erro fica em um stream diferente, getErrorStream(). Esquecer isso é o bug clássico do HttpURLConnection: uma resposta de erro causa uma exceção em vez de permitir que você leia a explicação do servidor. Sempre verifique getResponseCode() primeiro. Finalize com conn.disconnect().
Um exemplo completo: uma requisição POST de ida e volta
Este programa executa um servidor loopback que ecoa o corpo da requisição de volta com um 201 Created, e então realiza um POST por meio do HttpURLConnection: definindo o método, escrevendo o corpo, lendo o status e escolhendo o stream correto.
O que observar na execução:
- O cast de
URLConnectionparaHttpURLConnectiondesbloqueou a camada HTTP:setRequestMethod("POST"),getResponseCode()egetResponseMessage()existem apenas na subclasse. Para uma URL com esquemahttp:, o objeto realmente é umHttpURLConnection, portanto o cast sempre funciona. - O envio de um corpo exigiu
setDoOutput(true)antes de escrever emgetOutputStream(). Sem essa chamada, a conexão permanece somente leitura e a escrita falha — optar pela saída é o interruptor que transforma um GET em uma requisição com corpo. getResponseCode()retornou201e é o que de fato disparou a requisição para o servidor. O código de status é a primeira coisa a ser lida, pois a próxima decisão — qual stream ler — depende dele.- O exemplo ramificou entre
getInputStream()egetErrorStream(). Aqui201é sucesso, então o stream de entrada transportou o corpo ecoado, mas em uma resposta 4xx/5xxgetInputStream()teria lançado uma exceção e a mensagem do servidor só seria acessível por meio degetErrorStream(). Essa divisão é a aresta mais afiada da API. - O fluxo exigiu mais de cinco chamadas de configuração para um único POST, além de
disconnect()para encerrar. Essa verbosidade — streams manuais, a armadilha do error stream, sem suporte nativo a operações assíncronas — é exatamente o motivo pelo qual oHttpClientexiste.
Quando usar HttpURLConnection
Use HttpURLConnection quando estiver em um JDK mais antigo (anterior ao Java 11), quando uma biblioteca ou base de código já o adota como padrão, ou quando quiser evitar adicionar qualquer dependência extra para uma única chamada simples. Para qualquer coisa nova e não trivial — reutilização de conexão, HTTP/2, operações assíncronas ou objetos de requisição/resposta mais limpos — prefira o moderno HttpClient. Se você só precisa ler de uma URL sem controle específico de HTTP, as classes URL e URLConnection simples são suficientes.