Como usar java.net.URLConnection para triggersr e manipular solicitações HTTP

O uso de java.net.URLConnection é perguntado com bastante frequência aqui, e o tutorial do Oracle é muito conciso sobre isso.

Esse tutorial basicamente mostra apenas como triggersr uma requisição GET e ler a resposta. Ele não explica em nenhum lugar como usá-lo para, entre outros, executar uma solicitação POST, definir headers de solicitação, ler headers de resposta, lidar com cookies, enviar um formulário HTML, carregar um arquivo etc.

Então, como posso usar java.net.URLConnection para triggersr e manipular solicitações HTTP “avançadas”?

Primeiro um aviso prévio: os trechos de código postados são todos exemplos básicos. Você precisará lidar com IOException s e RuntimeException como NullPointerException , ArrayIndexOutOfBoundsException e se RuntimeException .


Preparando

Primeiro precisamos saber pelo menos a URL e o charset. Os parâmetros são opcionais e dependem dos requisitos funcionais.

 String url = "http://example.com"; String charset = "UTF-8"; // Or in Java 7 and later, use the constant: java.nio.charset.StandardCharsets.UTF_8.name() String param1 = "value1"; String param2 = "value2"; // ... String query = String.format("param1=%s&param2=%s", URLEncoder.encode(param1, charset), URLEncoder.encode(param2, charset)); 

Os parâmetros de consulta devem estar no formato name=value e serem concatenados por & . Você normalmente também codificaria os parâmetros de consulta com o conjunto de caracteres especificado usando URLEncoder#encode() .

O String#format() é apenas por conveniência. Eu prefiro quando eu preciso do operador de concatenação de String + mais que duas vezes.


Atirando uma solicitação HTTP GET com (opcionalmente) parâmetros de consulta

É uma tarefa trivial. É o método de solicitação padrão.

 URLConnection connection = new URL(url + "?" + query).openConnection(); connection.setRequestProperty("Accept-Charset", charset); InputStream response = connection.getInputStream(); // ... 

Qualquer string de consulta deve ser concatenada ao URL usando ? . O header Accept-Charset pode indicar ao servidor em que codificação os parâmetros estão. Se você não enviar nenhuma string de consulta, poderá deixar o header Accept-Charset . Se você não precisar definir nenhum header, poderá usar o método de atalho URL#openStream() .

 InputStream response = new URL(url).openStream(); // ... 

De qualquer forma, se o outro lado for um HttpServlet , seu método doGet() será chamado e os parâmetros estarão disponíveis por HttpServletRequest#getParameter() .

Para fins de teste, você pode imprimir o corpo da resposta para stdout como abaixo:

 try (Scanner scanner = new Scanner(response)) { String responseBody = scanner.useDelimiter("\\A").next(); System.out.println(responseBody); } 

Disparando uma solicitação HTTP POST com parâmetros de consulta

Definir o URLConnection#setDoOutput() como true define implicitamente o método de solicitação para POST. O HTTP POST padrão, como os formulários da web, é do tipo application/x-www-form-urlencoded em que a string de consulta é gravada no corpo da solicitação.

 URLConnection connection = new URL(url).openConnection(); connection.setDoOutput(true); // Triggers POST. connection.setRequestProperty("Accept-Charset", charset); connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=" + charset); try (OutputStream output = connection.getOutputStream()) { output.write(query.getBytes(charset)); } InputStream response = connection.getInputStream(); // ... 

Nota: sempre que você quiser enviar um formulário HTML programaticamente, não se esqueça de pegar os pares name=value de qualquer elemento na string de consulta e, claro, também o par name=value de o elemento que você gostaria de “pressionar” programaticamente (porque normalmente é usado no lado do servidor para distinguir se um botão foi pressionado e, em caso afirmativo, qual deles).

Você também pode converter a URLConnection obtida em HttpURLConnection e usar sua HttpURLConnection#setRequestMethod() . Mas se você estiver tentando usar a conexão para saída, ainda precisará definir URLConnection#setDoOutput() como true .

 HttpURLConnection httpConnection = (HttpURLConnection) new URL(url).openConnection(); httpConnection.setRequestMethod("POST"); // ... 

De qualquer forma, se o outro lado for um HttpServlet , o método doPost() será chamado e os parâmetros estarão disponíveis por HttpServletRequest#getParameter() .


Na verdade, triggersndo a solicitação HTTP

Você pode triggersr a solicitação HTTP explicitamente com URLConnection#connect() , mas a solicitação será triggersda automaticamente quando desejar obter informações sobre a resposta HTTP, como o corpo da resposta usando URLConnection#getInputStream() e assim por diante. Os exemplos acima fazem exatamente isso, então a chamada connect() é de fato supérflua.


Reunindo Informações de Resposta HTTP

  1. Status de resposta HTTP :

    Você precisa de um HttpURLConnection aqui. Lance primeiro se necessário.

     int status = httpConnection.getResponseCode(); 
  2. Cabeçalhos de resposta HTTP :

     for (Entry> header : connection.getHeaderFields().entrySet()) { System.out.println(header.getKey() + "=" + header.getValue()); } 
  3. Codificação de resposta HTTP :

    Quando o Content-Type contém um parâmetro charset , então o corpo da resposta é provavelmente baseado em texto e gostaríamos de processar o corpo da resposta com a codificação de caracteres especificada no lado do servidor.

     String contentType = connection.getHeaderField("Content-Type"); String charset = null; for (String param : contentType.replace(" ", "").split(";")) { if (param.startsWith("charset=")) { charset = param.split("=", 2)[1]; break; } } if (charset != null) { try (BufferedReader reader = new BufferedReader(new InputStreamReader(response, charset))) { for (String line; (line = reader.readLine()) != null;) { // ... System.out.println(line) ? } } } else { // It's likely binary content, use InputStream/OutputStream. } 

Mantendo a session

A session do lado do servidor é geralmente apoiada por um cookie. Alguns formulários da web exigem que você esteja conectado e / ou seja acompanhado por uma session. Você pode usar a API CookieHandler para manter os cookies. Você precisa preparar um CookieManager com uma CookiePolicy de ACCEPT_ALL antes de enviar todas as solicitações HTTP.

 // First set the default cookie manager. CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ALL)); // All the following subsequent URLConnections will use the same cookie manager. URLConnection connection = new URL(url).openConnection(); // ... connection = new URL(url).openConnection(); // ... connection = new URL(url).openConnection(); // ... 

Observe que isso nem sempre funciona adequadamente em todas as circunstâncias. Se isso falhar para você, o melhor é reunir e definir manualmente os headers dos cookies. Você basicamente precisa pegar todos Set-Cookie headers Set-Cookie da resposta do login ou da primeira requisição GET e depois passar pelos pedidos subseqüentes.

 // Gather all cookies on the first request. URLConnection connection = new URL(url).openConnection(); List cookies = connection.getHeaderFields().get("Set-Cookie"); // ... // Then use the same cookies on all subsequent requests. connection = new URL(url).openConnection(); for (String cookie : cookies) { connection.addRequestProperty("Cookie", cookie.split(";", 2)[0]); } // ... 

A split(";", 2)[0] está lá para se livrar dos atributos de cookie que são irrelevantes para o lado do servidor como expires , path , etc. Alternativamente, você também pode usar cookie.substring(0, cookie.indexOf(';')) vez de split() .


Modo de streaming

O HttpURLConnection por padrão armazena em buffer todo o corpo da solicitação antes de realmente enviá-lo, independentemente de você ter definido um tamanho de conteúdo fixo usando connection.setRequestProperty("Content-Length", contentLength); . Isso pode causar OutOfMemoryException sempre que você envia simultaneamente grandes solicitações POST (por exemplo, upload de arquivos). Para evitar isso, você gostaria de definir o HttpURLConnection#setFixedLengthStreamingMode() .

 httpConnection.setFixedLengthStreamingMode(contentLength); 

Mas se o comprimento do conteúdo não for realmente conhecido de antemão, então você pode usar o modo de streaming em partes configurando o HttpURLConnection#setChunkedStreamingMode() acordo. Isso definirá o header HTTP Transfer-Encoding como chunked que forçará o envio do corpo da solicitação em partes. O exemplo abaixo irá enviar o corpo em pedaços de 1KB.

 httpConnection.setChunkedStreamingMode(1024); 

Agente de usuário

Pode acontecer que uma solicitação retorne uma resposta inesperada, enquanto ela funciona bem com um navegador da Web real . O lado do servidor provavelmente está bloqueando solicitações com base no header de solicitação do User-Agent . O URLConnection irá, por padrão, configurá-lo para Java/1.6.0_19 onde a última parte é obviamente a versão do JRE. Você pode replace isso da seguinte maneira:

 connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36"); // Do as if you're using Chrome 41 on Windows 7. 

Use a string User-Agent de um navegador recente .


Tratamento de erros

Se o código de resposta HTTP for 4nn (Erro do Cliente) ou 5nn (Erro do Servidor), você poderá querer ler o HttpURLConnection#getErrorStream() para ver se o servidor enviou alguma informação de erro útil.

 InputStream error = ((HttpURLConnection) connection).getErrorStream(); 

Se o código de resposta HTTP for -1, então algo deu errado com a manipulação de conexão e resposta. A implementação do HttpURLConnection está em JREs mais antigos com um pouco de bugs, mantendo as conexões HttpURLConnection . Você pode querer desativá-lo definindo a propriedade do sistema http.keepAlive como false . Você pode fazer isso programaticamente no início do seu aplicativo por:

 System.setProperty("http.keepAlive", "false"); 

Upload de arquivos

Você normalmente usaria multipart/form-data codificação multipart/form-data para conteúdo misto de POST (dados binários e de caracteres). A codificação é descrita com mais detalhes no RFC2388 .

 String param = "value"; File textFile = new File("/path/to/file.txt"); File binaryFile = new File("/path/to/file.bin"); String boundary = Long.toHexString(System.currentTimeMillis()); // Just generate some unique random value. String CRLF = "\r\n"; // Line separator required by multipart/form-data. URLConnection connection = new URL(url).openConnection(); connection.setDoOutput(true); connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary); try ( OutputStream output = connection.getOutputStream(); PrintWriter writer = new PrintWriter(new OutputStreamWriter(output, charset), true); ) { // Send normal param. writer.append("--" + boundary).append(CRLF); writer.append("Content-Disposition: form-data; name=\"param\"").append(CRLF); writer.append("Content-Type: text/plain; charset=" + charset).append(CRLF); writer.append(CRLF).append(param).append(CRLF).flush(); // Send text file. writer.append("--" + boundary).append(CRLF); writer.append("Content-Disposition: form-data; name=\"textFile\"; filename=\"" + textFile.getName() + "\"").append(CRLF); writer.append("Content-Type: text/plain; charset=" + charset).append(CRLF); // Text file itself must be saved in this charset! writer.append(CRLF).flush(); Files.copy(textFile.toPath(), output); output.flush(); // Important before continuing with writer! writer.append(CRLF).flush(); // CRLF is important! It indicates end of boundary. // Send binary file. writer.append("--" + boundary).append(CRLF); writer.append("Content-Disposition: form-data; name=\"binaryFile\"; filename=\"" + binaryFile.getName() + "\"").append(CRLF); writer.append("Content-Type: " + URLConnection.guessContentTypeFromName(binaryFile.getName())).append(CRLF); writer.append("Content-Transfer-Encoding: binary").append(CRLF); writer.append(CRLF).flush(); Files.copy(binaryFile.toPath(), output); output.flush(); // Important before continuing with writer! writer.append(CRLF).flush(); // CRLF is important! It indicates end of boundary. // End of multipart/form-data. writer.append("--" + boundary + "--").append(CRLF).flush(); } 

Se o outro lado é um HttpServlet , então seu método doPost() será chamado e as partes estarão disponíveis por HttpServletRequest#getPart() (note, portanto, não getParameter() e assim por diante!). O método getPart() é relativamente novo, é introduzido no Servlet 3.0 (Glassfish 3, Tomcat 7, etc). Antes do Servlet 3.0, sua melhor opção é usar o Apache Commons FileUpload para analisar uma solicitação de multipart/form-data . Veja também esta resposta para exemplos das abordagens FileUpload e Servelt 3.0.


Lidando com sites HTTPS não confiáveis ​​ou mal configurados

Às vezes, você precisa conectar um URL HTTPS, talvez porque esteja escrevendo um web scraper. Nesse caso, você provavelmente enfrentará uma javax.net.ssl.SSLException: Not trusted server certificate em alguns sites HTTPS que não mantém seus certificados SSL atualizados ou java.security.cert.CertificateException: No subject alternative DNS name matching [hostname] found ou javax.net.ssl.SSLProtocolException: handshake alert: unrecognized_name em alguns sites HTTPS configurados incorretamente.

O seguinte inicializador static execução única em sua class de raspadores da Web deve tornar o HttpsURLConnection mais tolerante em relação a esses sites HTTPS e, portanto, não deve mais lançar essas exceções.

 static { TrustManager[] trustAllCertificates = new TrustManager[] { new X509TrustManager() { @Override public X509Certificate[] getAcceptedIssuers() { return null; // Not relevant. } @Override public void checkClientTrusted(X509Certificate[] certs, String authType) { // Do nothing. Just allow them all. } @Override public void checkServerTrusted(X509Certificate[] certs, String authType) { // Do nothing. Just allow them all. } } }; HostnameVerifier trustAllHostnames = new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { return true; // Just allow them all. } }; try { System.setProperty("jsse.enableSNIExtension", "false"); SSLContext sc = SSLContext.getInstance("SSL"); sc.init(null, trustAllCertificates, new SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); HttpsURLConnection.setDefaultHostnameVerifier(trustAllHostnames); } catch (GeneralSecurityException e) { throw new ExceptionInInitializerError(e); } } 

Últimas palavras

O Apache HttpComponents HttpClient é muito mais conveniente neste tudo 🙂

  • Tutorial HttpClient
  • Exemplos de HttpClient

Analisando e Extraindo HTML

Se tudo que você quer é analisar e extrair dados do HTML, então é melhor usar um analisador de HTML como o Jsoup

  • Quais são os prós e contras dos principais analisadores de HTML em Java
  • Como escanear e extrair uma página da Web em Java

Ao trabalhar com HTTP, é quase sempre mais útil se referir a HttpURLConnection em vez da class base URLConnection (uma vez que URLConnection é uma class abstrata quando você solicita URLConnection.openConnection() em uma URL HTTP que é o que você receberá de volta mesmo assim).

Então você pode, em vez de depender de URLConnection#setDoOutput(true) para configurar implicitamente o método de solicitação para POST, em vez disso, fazer httpURLConnection.setRequestMethod("POST") que alguns podem achar mais natural (e também permite especificar outros methods de solicitação, como PUT , DELETE , …).

Ele também fornece constantes HTTP úteis para que você possa fazer:

 int responseCode = httpURLConnection.getResponseCode(); if (responseCode == HttpURLConnection.HTTP_OK) { 

Inspirado por esta e outras questões sobre SO, criei um cliente HTTP básico de código aberto mínimo que incorpora a maioria das técnicas encontradas aqui.

O google-http-java-client também é um ótimo recurso de código aberto.

Existem 2 opções que você pode seguir com HTTP URL Hits: GET / POST

Solicitação GET: –

 HttpURLConnection.setFollowRedirects(true); // defaults to true String url = "https://name_of_the_url"; URL request_url = new URL(url); HttpURLConnection http_conn = (HttpURLConnection)request_url.openConnection(); http_conn.setConnectTimeout(100000); http_conn.setReadTimeout(100000); http_conn.setInstanceFollowRedirects(true); System.out.println(String.valueOf(http_conn.getResponseCode())); 

Solicitação POST: –

 HttpURLConnection.setFollowRedirects(true); // defaults to true String url = "https://name_of_the_url" URL request_url = new URL(url); HttpURLConnection http_conn = (HttpURLConnection)request_url.openConnection(); http_conn.setConnectTimeout(100000); http_conn.setReadTimeout(100000); http_conn.setInstanceFollowRedirects(true); http_conn.setDoOutput(true); PrintWriter out = new PrintWriter(http_conn.getOutputStream()); if (urlparameter != null) { out.println(urlparameter); } out.close(); out = null; System.out.println(String.valueOf(http_conn.getResponseCode())); 

Eu sugiro que você dê uma olhada no código em kevinsawicki / http-request , é basicamente um wrapper em cima de HttpUrlConnection que fornece uma API muito mais simples no caso de você só querer fazer as requisições agora ou você pode dar uma olhada nas fonts (não é muito grande) para dar uma olhada em como as conexões são tratadas.

Exemplo: faça uma solicitação GET com o tipo de conteúdo application/json e alguns parâmetros de consulta:

 // GET http://google.com?q=baseball%20gloves&size=100 String response = HttpRequest.get("http://google.com", true, "q", "baseball gloves", "size", 100) .accept("application/json") .body(); System.out.println("Response was: " + response); 

Eu também fui muito inspirado por essa resposta.

Eu estou frequentemente em projetos onde eu preciso fazer algum HTTP, e eu posso não querer trazer muitas dependencies de terceiros (que trazem outros e assim por diante e assim por diante, etc.)

Comecei a escrever meus próprios utilitários com base em algumas dessas conversas (não em qualquer lugar):

 package org.boon.utils; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; import java.util.Map; import static org.boon.utils.IO.read; public class HTTP { 

Então há apenas um monte ou methods estáticos.

 public static String get( final String url) { Exceptions.tryIt(() -> { URLConnection connection; connection = doGet(url, null, null, null); return extractResponseString(connection); }); return null; } public static String getWithHeaders( final String url, final Map headers) { URLConnection connection; try { connection = doGet(url, headers, null, null); return extractResponseString(connection); } catch (Exception ex) { Exceptions.handle(ex); return null; } } public static String getWithContentType( final String url, final Map headers, String contentType) { URLConnection connection; try { connection = doGet(url, headers, contentType, null); return extractResponseString(connection); } catch (Exception ex) { Exceptions.handle(ex); return null; } } public static String getWithCharSet( final String url, final Map headers, String contentType, String charSet) { URLConnection connection; try { connection = doGet(url, headers, contentType, charSet); return extractResponseString(connection); } catch (Exception ex) { Exceptions.handle(ex); return null; } } 

Então postar …

 public static String postBody( final String url, final String body) { URLConnection connection; try { connection = doPost(url, null, "text/plain", null, body); return extractResponseString(connection); } catch (Exception ex) { Exceptions.handle(ex); return null; } } public static String postBodyWithHeaders( final String url, final Map headers, final String body) { URLConnection connection; try { connection = doPost(url, headers, "text/plain", null, body); return extractResponseString(connection); } catch (Exception ex) { Exceptions.handle(ex); return null; } } public static String postBodyWithContentType( final String url, final Map headers, final String contentType, final String body) { URLConnection connection; try { connection = doPost(url, headers, contentType, null, body); return extractResponseString(connection); } catch (Exception ex) { Exceptions.handle(ex); return null; } } public static String postBodyWithCharset( final String url, final Map headers, final String contentType, final String charSet, final String body) { URLConnection connection; try { connection = doPost(url, headers, contentType, charSet, body); return extractResponseString(connection); } catch (Exception ex) { Exceptions.handle(ex); return null; } } private static URLConnection doPost(String url, Map headers, String contentType, String charset, String body ) throws IOException { URLConnection connection;/* Handle output. */ connection = new URL(url).openConnection(); connection.setDoOutput(true); manageContentTypeHeaders(contentType, charset, connection); manageHeaders(headers, connection); IO.write(connection.getOutputStream(), body, IO.CHARSET); return connection; } private static void manageHeaders(Map headers, URLConnection connection) { if (headers != null) { for (Map.Entry entry : headers.entrySet()) { connection.setRequestProperty(entry.getKey(), entry.getValue().toString()); } } } private static void manageContentTypeHeaders(String contentType, String charset, URLConnection connection) { connection.setRequestProperty("Accept-Charset", charset == null ? IO.CHARSET : charset); if (contentType!=null && !contentType.isEmpty()) { connection.setRequestProperty("Content-Type", contentType); } } private static URLConnection doGet(String url, Map headers, String contentType, String charset) throws IOException { URLConnection connection;/* Handle output. */ connection = new URL(url).openConnection(); manageContentTypeHeaders(contentType, charset, connection); manageHeaders(headers, connection); return connection; } private static String extractResponseString(URLConnection connection) throws IOException { /* Handle input. */ HttpURLConnection http = (HttpURLConnection)connection; int status = http.getResponseCode(); String charset = getCharset(connection.getHeaderField("Content-Type")); if (status==200) { return readResponseBody(http, charset); } else { return readErrorResponseBody(http, status, charset); } } private static String readErrorResponseBody(HttpURLConnection http, int status, String charset) { InputStream errorStream = http.getErrorStream(); if ( errorStream!=null ) { String error = charset== null ? read( errorStream ) : read( errorStream, charset ); throw new RuntimeException("STATUS CODE =" + status + "\n\n" + error); } else { throw new RuntimeException("STATUS CODE =" + status); } } private static String readResponseBody(HttpURLConnection http, String charset) throws IOException { if (charset != null) { return read(http.getInputStream(), charset); } else { return read(http.getInputStream()); } } private static String getCharset(String contentType) { if (contentType==null) { return null; } String charset = null; for (String param : contentType.replace(" ", "").split(";")) { if (param.startsWith("charset=")) { charset = param.split("=", 2)[1]; break; } } charset = charset == null ? IO.CHARSET : charset; return charset; } 

Bem, você entendeu a ideia ….

Aqui estão os testes:

 static class MyHandler implements HttpHandler { public void handle(HttpExchange t) throws IOException { InputStream requestBody = t.getRequestBody(); String body = IO.read(requestBody); Headers requestHeaders = t.getRequestHeaders(); body = body + "\n" + copy(requestHeaders).toString(); t.sendResponseHeaders(200, body.length()); OutputStream os = t.getResponseBody(); os.write(body.getBytes()); os.close(); } } @Test public void testHappy() throws Exception { HttpServer server = HttpServer.create(new InetSocketAddress(9212), 0); server.createContext("/test", new MyHandler()); server.setExecutor(null); // creates a default executor server.start(); Thread.sleep(10); Map headers = map("foo", "bar", "fun", "sun"); String response = HTTP.postBodyWithContentType("http://localhost:9212/test", headers, "text/plain", "hi mom"); System.out.println(response); assertTrue(response.contains("hi mom")); assertTrue(response.contains("Fun=[sun], Foo=[bar]")); response = HTTP.postBodyWithCharset("http://localhost:9212/test", headers, "text/plain", "UTF-8", "hi mom"); System.out.println(response); assertTrue(response.contains("hi mom")); assertTrue(response.contains("Fun=[sun], Foo=[bar]")); response = HTTP.postBodyWithHeaders("http://localhost:9212/test", headers, "hi mom"); System.out.println(response); assertTrue(response.contains("hi mom")); assertTrue(response.contains("Fun=[sun], Foo=[bar]")); response = HTTP.get("http://localhost:9212/test"); System.out.println(response); response = HTTP.getWithHeaders("http://localhost:9212/test", headers); System.out.println(response); assertTrue(response.contains("Fun=[sun], Foo=[bar]")); response = HTTP.getWithContentType("http://localhost:9212/test", headers, "text/plain"); System.out.println(response); assertTrue(response.contains("Fun=[sun], Foo=[bar]")); response = HTTP.getWithCharSet("http://localhost:9212/test", headers, "text/plain", "UTF-8"); System.out.println(response); assertTrue(response.contains("Fun=[sun], Foo=[bar]")); Thread.sleep(10); server.stop(0); } @Test public void testPostBody() throws Exception { HttpServer server = HttpServer.create(new InetSocketAddress(9220), 0); server.createContext("/test", new MyHandler()); server.setExecutor(null); // creates a default executor server.start(); Thread.sleep(10); Map headers = map("foo", "bar", "fun", "sun"); String response = HTTP.postBody("http://localhost:9220/test", "hi mom"); assertTrue(response.contains("hi mom")); Thread.sleep(10); server.stop(0); } @Test(expected = RuntimeException.class) public void testSad() throws Exception { HttpServer server = HttpServer.create(new InetSocketAddress(9213), 0); server.createContext("/test", new MyHandler()); server.setExecutor(null); // creates a default executor server.start(); Thread.sleep(10); Map headers = map("foo", "bar", "fun", "sun"); String response = HTTP.postBodyWithContentType("http://localhost:9213/foo", headers, "text/plain", "hi mom"); System.out.println(response); assertTrue(response.contains("hi mom")); assertTrue(response.contains("Fun=[sun], Foo=[bar]")); Thread.sleep(10); server.stop(0); } 

Você pode encontrar o resto aqui:

https://github.com/RichardHightower/boon

Meu objective é fornecer as coisas comuns que alguém gostaria de fazer de uma maneira um pouco mais fácil do que isso …

Atualizar

O novo Cliente HTTP fornecido com o Java 9, mas como parte de um módulo Incubador denominado jdk.incubator.httpclient . Os módulos de incubadora são um meio de colocar APIs não finais nas mãos dos desenvolvedores enquanto as APIs progridem para finalização ou remoção em uma versão futura.

No Java 9, você pode enviar uma solicitação GET como:

 // GET HttpResponse response = HttpRequest .create(new URI("http://www.stackoverflow.com")) .headers("Foo", "foovalue", "Bar", "barvalue") .GET() .response(); 

Então você pode examinar o HttpResponse retornado:

 int statusCode = response.statusCode(); String responseBody = response.body(HttpResponse.asString()); 

Desde que este novo cliente HTTP está em java.httpclient Módulo jdk.incubator.httpclient , você deve declarar esta dependência em seu arquivo module-info.java :

 module com.foo.bar { requires jdk.incubator.httpclient; } 

Inicialmente, fui enganado por este artigo, que favorece o HttpClient .

Mais tarde, percebi que HttpURLConnection vai ficar neste artigo

De acordo com o blog do Google :

O cliente HTTP do Apache tem menos erros no Eclair e no Froyo. É a melhor escolha para esses lançamentos. Para Gingerbread, HttpURLConnection é a melhor escolha. Sua API simples e tamanho pequeno o tornam ideal para o Android.

A compactação transparente e o cache de resposta reduzem o uso da rede, melhoram a velocidade e economizam bateria. Novos aplicativos devem usar HttpURLConnection; é onde nós estaremos gastando nossa energia daqui para frente.

Depois de ler este artigo e algumas outras perguntas sobre o stream de pilha, estou convencido de que o HttpURLConnection permanecerá por HttpURLConnection mais longos.

Algumas das perguntas do SE favorecem o HttpURLConnections :

No Android, faça uma solicitação POST com dados de URL codificado no formulário sem usar UrlEncodedFormEntity

HttpPost trabalha em projeto Java, não no Android

Você também pode usar o JdkRequest do jcabi-http (eu sou um desenvolvedor), que faz todo esse trabalho para você, decorando o HttpURLConnection, triggersndo solicitações HTTP e analisando respostas, por exemplo:

 String html = new JdkRequest("http://www.google.com").fetch().body(); 

Confira esta postagem no blog para mais informações: http://www.yegor256.com/2014/04/11/jcabi-http-intro.html

Há também o OkHttp , que é um cliente HTTP que é eficiente por padrão:

  • O suporte HTTP / 2 permite que todas as solicitações para o mesmo host compartilhem um soquete.
  • O pool de conexões reduz a latência de solicitações (se HTTP / 2 não estiver disponível).
  • O GZIP transparente reduz os tamanhos de download.
  • O cache de resposta evita completamente a rede para solicitações repetidas.

Primeiro crie uma instância de OkHttpClient :

 OkHttpClient client = new OkHttpClient(); 

Em seguida, prepare sua solicitação GET :

 Request request = new Request.Builder() .url(url) .build(); 

finalmente, use OkHttpClient para enviar o Request preparado:

 Response response = client.newCall(request).execute(); 

Para mais detalhes, você pode consultar a documentação do OkHttp

se você estiver usando http get por favor remova essa linha

 urlConnection.setDoOutput(true);