Cómo utilizar java.net.URLConnection al fuego y gestionar las peticiones HTTP
-
04-10-2019 - |
Pregunta
El uso de java.net.URLConnection
se le preguntó acerca de bastante a menudo aquí, y el Oracle tutorial es también concisa al respecto.
Ese tutorial básicamente sólo muestra cómo disparar una petición GET y leer la respuesta. No se explica cómo utilizar en cualquier lugar que entre otros realizan una petición POST, las cabeceras de solicitud de ajuste, las cabeceras de respuesta de lectura, trato con las cookies, enviar un formulario HTML, cargar un archivo, etc.
Así que, ¿cómo puedo usar java.net.URLConnection
al fuego y mango "avanzada" peticiones HTTP?
Solución
Primero un descargo de responsabilidad de antemano: los fragmentos de código enviados son ejemplos básicos. Tendrá que manejar IOException
s triviales y RuntimeException
s como NullPointerException
, ArrayIndexOutOfBoundsException
y consortes usted mismo.
Preparación
En primer lugar, es necesario saber, al menos, la URL y el juego de caracteres. Los parámetros son opcionales y dependen de los requisitos funcionales.
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¶m2=%s",
URLEncoder.encode(param1, charset),
URLEncoder.encode(param2, charset));
Los parámetros de consulta debe estar en formato name=value
y ser concatenada con &
. Lo haría normalmente también cifrar la URL de los parámetros de consulta con el juego de caracteres especificado mediante URLEncoder#encode()
.
El String#format()
es sólo por conveniencia. Yo prefiero que cuando iba a necesitar la +
cadena operador de concatenación más de dos veces.
Disparar un HTTP GET petición con (opcionalmente ) consulta parámetros
Es una tarea trivial. Es el método de solicitudes por defecto.
URLConnection connection = new URL(url + "?" + query).openConnection();
connection.setRequestProperty("Accept-Charset", charset);
InputStream response = connection.getInputStream();
// ...
Cualquier cadena de consulta debe ser concatenado a la URL usando ?
. El Accept-Charset
cabecera puede hacer alusión al servidor qué codificación de los parámetros se encuentra. Si usted no envía ninguna cadena de consulta, a continuación, se puede dejar la cabecera Accept-Charset
de distancia. Si no es necesario establecer ninguna cabecera, después, se puede utilizar el URL#openStream()
atajo método.
InputStream response = new URL(url).openStream();
// ...
De cualquier manera, si la otra parte es un HttpServlet
, entonces su doGet()
método será llamado y los parámetros estará disponible por HttpServletRequest#getParameter()
.
Para propósitos de prueba, se puede imprimir el cuerpo de la respuesta a la salida estándar de la siguiente manera:
try (Scanner scanner = new Scanner(response)) {
String responseBody = scanner.useDelimiter("\\A").next();
System.out.println(responseBody);
}
HTTP solicitud POST con parámetros de consulta
Configuración de la URLConnection#setDoOutput()
para true
establece implícitamente el método de la petición a la POST. El POST HTTP estándar como formularios web hacer es de tipo application/x-www-form-urlencoded
en donde la cadena de consulta se escribe en el cuerpo de la petición.
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: cada vez que desea enviar un formulario HTML mediante programación, no se olvide de tomar los pares name=value
de cualquier elemento <input type="hidden">
en la cadena de consulta y por supuesto también el par name=value
del elemento <input type="submit">
la que desea a "prensa" mediante programación (por lo general debido a que se ha utilizado en el lado del servidor para distinguir si se pulsa un botón y si es así, cuál).
También puede emitir el obtenido URLConnection
HttpURLConnection
y utilizar su HttpURLConnection#setRequestMethod()
vez. Pero si usted está tratando de utilizar la conexión para la salida todavía necesita conjunto URLConnection#setDoOutput()
para true
.
HttpURLConnection httpConnection = (HttpURLConnection) new URL(url).openConnection();
httpConnection.setRequestMethod("POST");
// ...
De cualquier manera, si la otra parte es un HttpServlet
, entonces su doPost()
método será llamado y los parámetros estará disponible por HttpServletRequest#getParameter()
.
De hecho disparar la petición HTTP
Puede disparar la petición HTTP explícitamente URLConnection#connect()
, pero la solicitud será automáticamente despedido en la demanda cuando se desea obtener alguna información acerca de la respuesta HTTP, como el cuerpo de la respuesta usando URLConnection#getInputStream()
y así sucesivamente. Los ejemplos anteriores hace exactamente eso, por lo que la llamada connect()
es, de hecho superflua.
información de respuesta HTTP Encuentro
-
Se necesita una
HttpURLConnection
aquí. Echarlo primero si es necesario.int status = httpConnection.getResponseCode();
-
for (Entry<String, List<String>> header : connection.getHeaderFields().entrySet()) { System.out.println(header.getKey() + "=" + header.getValue()); }
-
Cuando el
Content-Type
contiene un parámetrocharset
, entonces el cuerpo de la respuesta es probable que el texto basada y nos gustaría procesar el cuerpo de la respuesta con el lado del servidor carácter especificado codificación continuación.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. }
El mantenimiento de la sesión
La sesión del lado del servidor es generalmente respaldado por una cookie. Algunos formularios web requieren que está conectado y / o son seguidos por una sesión. Puede utilizar la API CookieHandler
para mantener las cookies . Es necesario preparar un CookieManager
con un < a href = "http://docs.oracle.com/javase/8/docs/api/java/net/CookiePolicy.html" rel = "noreferrer"> CookiePolicy
de ACCEPT_ALL
antes de enviar todas las peticiones 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();
// ...
Tenga en cuenta que esto se sabe que no siempre funciona correctamente en todas las circunstancias. Si falla por usted, entonces lo mejor es reunir y establecer las cabeceras de cookies manualmente. Es, básicamente, tiene que agarrar todas las cabeceras Set-Cookie
partir de la respuesta del usuario o la primera solicitud GET
y luego pasar esto a través de las solicitudes posteriores.
// Gather all cookies on the first request.
URLConnection connection = new URL(url).openConnection();
List<String> 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]);
}
// ...
El split(";", 2)[0]
está allí para deshacerse de los atributos de galletas que son irrelevantes para el lado del servidor como expires
, path
, etc. Alternativamente, también se puede utilizar cookie.substring(0, cookie.indexOf(';'))
en lugar de split()
.
Modo Streaming
El HttpURLConnection
voluntad de búfer predeterminado toda solicitud de cuerpo antes de enviarlo realidad, independientemente de si usted ha fijado una longitud de contenido fijo por sí mismo utilizando connection.setRequestProperty("Content-Length", contentLength);
. Esto puede causar OutOfMemoryException
s cada vez que simultáneamente envía solicitudes POST de gran tamaño (por ejemplo, la carga de archivos). Para evitar esto, le gustaría establecer el HttpURLConnection#setFixedLengthStreamingMode()
.
httpConnection.setFixedLengthStreamingMode(contentLength);
Pero si la longitud del contenido es realmente no sabe de antemano, entonces usted puede hacer uso del modo de transmisión fragmentada mediante el establecimiento de la HttpURLConnection#setChunkedStreamingMode()
en consecuencia. Esto establecerá el HTTP Transfer-Encoding
cabecera a chunked
que será forzar el cuerpo de la petición se envía en trozos. El abajo ejemplo enviará el cuerpo en trozos de 1 KB.
httpConnection.setChunkedStreamingMode(1024);
User-Agent
Puede suceder que una solicitud devuelve una respuesta inesperada, mientras funciona bien con un navegador web real . El lado del servidor es, probablemente, bloqueando las solicitudes basadas en la User-Agent
encabezado de la solicitud. El URLConnection
voluntad, por defecto, a Java/1.6.0_19
donde la última parte es, obviamente, la versión de JRE. Puede anular esta manera siguiente:
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.
Utilice la cadena de agente de usuario desde un reciente del navegador .
El manejo de errores
Si el código de respuesta HTTP es 4nn
(Error de cliente) o 5nn
(error de servidor), entonces puede que desee leer el HttpURLConnection#getErrorStream()
para ver si el servidor ha enviado ninguna información de error de utilidad.
InputStream error = ((HttpURLConnection) connection).getErrorStream();
Si el código de respuesta HTTP es -1, entonces algo salió mal con la conexión y la gestión de respuesta. La aplicación está en HttpURLConnection
JRE de edad avanzada un poco buggy con mantener conexiones con vida. Es posible que desee apagarlo mediante el establecimiento de la propiedad del sistema http.keepAlive
a false
. Usted puede hacer esto mediante programación en el principio de su aplicación por:
System.setProperty("http.keepAlive", "false");
Carga de archivos
multipart/form-data
que codifica para contenido mixto POST (binario y datos de caracteres). La codificación es más detalladamente descrito en 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();
}
Si la otra parte es un HttpServlet
, entonces su doPost()
método será llamado y las partes estará disponible por HttpServletRequest#getPart()
(nota, por lo tanto no getParameter()
y así sucesivamente!). El método getPart()
está sin embargo relativamente nuevo, es introducido en Servlet 3.0 (Glassfish 3, Tomcat 7, etc). Antes de Servlet 3.0, su mejor opción es usar Apache Commons FileUpload para analizar una solicitud multipart/form-data
. También vea esta respuesta de ejemplos tanto de la FileUpload y el 3,0 Servelt enfoques.
Tratar con confianza o mal configurado HTTPS sitios
A veces es necesario conectar un URL HTTPS, tal vez debido a que está escribiendo un raspador web. En ese caso, es posible que probablemente se enfrentará a un javax.net.ssl.SSLException: Not trusted server certificate
en algunos sitios HTTPS y no cumpla sus certificados SSL al día, o una java.security.cert.CertificateException: No subject alternative DNS name matching [hostname] found
o javax.net.ssl.SSLProtocolException: handshake alert: unrecognized_name
en algunos sitios mal configurado HTTPS.
La siguiente static
un tiempo entre ciclos de inicialización en la clase de raspador web debe hacer HttpsURLConnection
más indulgente respecto a esos emplazamientos HTTPS y por lo tanto no lanzar las excepciones más.
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);
}
}
Las últimas palabras
El Apache HttpComponents HttpClient es más más conveniente en todo esto:)
analizar y extraer HTML
Si lo que quieres es analizar y extraer datos de HTML, a continuación, utilizar mejor un analizador HTML como Jsoup
Otros consejos
Cuando se trabaja con HTTP que casi siempre es más útil para referirse a HttpURLConnection
en lugar de la URLConnection
clase base (ya URLConnection
es una clase abstracta cuando se pide URLConnection.openConnection()
en un servidor HTTP URL que es lo que vas a volver de todos modos).
A continuación, puede en lugar de depender URLConnection#setDoOutput(true)
para establecer implícitamente el método de la petición a Post en lugar hacer httpURLConnection.setRequestMethod("POST")
que algunos podrían encontrar más natural (y que también le permite especificar otros métodos de petición, como PUT , eliminar , ...).
También proporciona constantes HTTP útiles por lo que puede hacer:
int responseCode = httpURLConnection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
Inspirado por esta y otras preguntas sobre lo tanto, he creado una fuente abierta mínima básica-http-cliente que encarna la mayor parte de las técnicas que se encuentran aquí.
google-http-java-cliente es también un gran recurso de código abierto.
Hay 2 opciones que puede ir con HTTP URL pertinente: GET / POST
Solicitud 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()));
solicitud 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()));
Le sugiero que tome un vistazo al código de kevinsawicki / petición http , su básicamente un contenedor en la parte superior de HttpUrlConnection
que proporciona una API mucho más simple en caso de que sólo quiere hacer las solicitudes en este momento o se puede echar un vistazo a las fuentes (que no es demasiado grande) para echar un vistazo a cómo se gestionan las conexiones.
Ejemplo: Haz una solicitud GET
con application/json
tipo de contenido y algunos 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);
I fue también muy inspirado por esta respuesta.
Estoy a menudo en proyectos en los que tengo que hacer alguna HTTP, y puede que no desee traer a un gran número de dependencias de 3 ª parte (que traen en los demás y así sucesivamente y así sucesivamente, etc.)
empecé a escribir mis propias utilidades sobre la base de algunos de esta conversación (no en cualquier lugar se hace):
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 {
A continuación, hay sólo un montón o métodos 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<String, ? extends Object> 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<String, ? extends Object> 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<String, ? extends Object> 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;
}
}
A continuación, después ...
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<String, ? extends Object> 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<String, ? extends Object> 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<String, ? extends Object> 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<String, ? extends Object> 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<String, ? extends Object> headers, URLConnection connection) {
if (headers != null) {
for (Map.Entry<String, ? extends Object> 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<String, ? extends Object> 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;
}
Bien se entiende la idea ....
Aquí están las pruebas:
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<String,String> 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<String,String> 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<String,String> 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);
}
Puede encontrar el resto aquí:
https://github.com/RichardHightower/boon
Mi objetivo es proporcionar a las cosas comunes que uno quiere hacer en un poco más de manera más fácil entonces ....
Actualizar
El nuevo cliente HTTP envía con Java 9, pero como parte de una Módulo incubadora nombrado
jdk.incubator.httpclient
. módulos Incubadora son un medio de poner las API no finales en manos de los desarrolladores mientras que el API progresan hacia cualquiera de finalización o la eliminación en un futuro liberación.
En Java 9, se puede enviar una solicitud de GET
como:
// GET
HttpResponse response = HttpRequest
.create(new URI("http://www.stackoverflow.com"))
.headers("Foo", "foovalue", "Bar", "barvalue")
.GET()
.response();
A continuación, se puede examinar el HttpResponse
devuelto:
int statusCode = response.statusCode();
String responseBody = response.body(HttpResponse.asString());
Desde este nuevo cliente HTTP es en módulo de java.httpclient
jdk.incubator.httpclient
, se debe declarar esta dependencia en el archivo de module-info.java
:
module com.foo.bar {
requires jdk.incubator.httpclient;
}
Al principio me fue engañado por este artículo que favorece HttpClient
.
Más tarde se han dado cuenta de que HttpURLConnection
se va a quedar de esta artículo
De acuerdo con el blog de Google
cliente HTTP Apache tiene un menor número de errores en Eclair y Froyo. Es la mejor opción para estas versiones. Para pan de jengibre, HttpURLConnection es la mejor opción. Su API simple y pequeño tamaño hace que sea muy apropiado para Android.
compresión transparente y almacenamiento en caché de respuesta de reducir el uso de la red, mejorar la velocidad y guardar la batería. Las nuevas aplicaciones deben utilizar HttpURLConnection; que es donde vamos a pasar nuestra energía en el futuro.
Después de leer esta artículo y alguna otra pila sobre cuestiones de flujo, estoy convencido de que HttpURLConnection
va a permanecer durante más tiempo.
Algunas de las preguntas que favorecen SE HttpURLConnections
:
También hay OkHttp , que es un cliente HTTP que es eficiente por defecto:
- HTTP apoyo / 2 permite todas las peticiones al mismo host para compartir una toma de corriente.
- La agrupación de conexiones reduce solicitud latencia (si HTTP / 2 no está disponible).
- GZIP transparente psiquiatras tamaños de descarga.
- almacenamiento en caché de respuesta evita por completo la red para las solicitudes de repetición.
En primer lugar crear una instancia de OkHttpClient
:
OkHttpClient client = new OkHttpClient();
A continuación, preparar su solicitud GET
:
Request request = new Request.Builder()
.url(url)
.build();
Por último, el uso OkHttpClient
para enviar Request
preparado:
Response response = client.newCall(request).execute();
Para más detalles, puede consultar la documentación de la OkHttp
También puede utilizar JdkRequest
de jcabi-http (soy un desarrollador), que hace todo este trabajo para usted, decorar HttpURLConnection, disparando las peticiones HTTP y analizar respuestas, por ejemplo:
String html = new JdkRequest("http://www.google.com").fetch().body();
Comprobar esta entrada del blog para más información: http://www.yegor256.com /2014/04/11/jcabi-http-intro.html
si está utilizando HTTP GET por favor, elimine esta línea
urlConnection.setDoOutput(true);