Java
Tutorial Java: HttpClient moderno
Aprende a usar la API HttpClient moderna de Java 11 para realizar peticiones GET y POST de forma eficiente y asíncrona con ejemplos prácticos.
Aprende Java y certifícateAPI HTTP Cliente moderno (Java 11+)
Java 11 introdujo una nueva API de cliente HTTP que representa un cambio significativo en la forma de realizar peticiones web desde aplicaciones Java. Esta API, ubicada en el paquete java.net.http
, reemplaza las antiguas implementaciones como HttpURLConnection
con un enfoque más moderno, fluido y adaptado a los patrones de programación actuales.
El nuevo cliente HTTP se diseñó con varios objetivos clave:
- Proporcionar una API más intuitiva y fácil de usar
- Soportar tanto operaciones síncronas como asíncronas
- Implementar HTTP/2 de forma nativa
- Mejorar el rendimiento general de las comunicaciones HTTP
Componentes principales
La API se estructura alrededor de tres clases fundamentales:
- HttpClient: El punto central para enviar solicitudes HTTP y recibir respuestas
- HttpRequest: Representa una solicitud HTTP con todos sus componentes
- HttpResponse: Encapsula la respuesta recibida del servidor
Creación del cliente HTTP
Para comenzar a utilizar esta API, primero necesitamos crear una instancia de HttpClient
:
HttpClient client = HttpClient.newHttpClient();
Este método de fábrica crea un cliente con la configuración predeterminada. Para casos más específicos, podemos usar un builder para personalizar el comportamiento:
HttpClient client = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_2) // Preferir HTTP/2
.connectTimeout(Duration.ofSeconds(10)) // Tiempo máximo de conexión
.followRedirects(HttpClient.Redirect.NORMAL) // Seguir redirecciones
.build();
Construcción de solicitudes
Las solicitudes HTTP se crean mediante el patrón builder a través de la clase HttpRequest.Builder
:
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.ejemplo.com/datos"))
.header("Content-Type", "application/json")
.timeout(Duration.ofMinutes(1))
.GET() // Método HTTP a utilizar
.build();
La API permite configurar todos los aspectos de una solicitud HTTP de manera fluida:
- URI: Destino de la solicitud
- Encabezados: Metadatos de la solicitud
- Método HTTP: GET, POST, PUT, DELETE, etc.
- Cuerpo de la solicitud: Para métodos como POST o PUT
- Timeout: Tiempo máximo de espera
Envío de solicitudes y procesamiento de respuestas
Una vez configurados el cliente y la solicitud, podemos enviarla y procesar la respuesta:
// Envío síncrono
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
// Acceso a los componentes de la respuesta
int statusCode = response.statusCode();
String body = response.body();
HttpHeaders headers = response.headers();
La API utiliza procesadores de cuerpo (body handlers) para convertir el flujo de bytes de la respuesta al formato deseado. Algunos handlers comunes incluyen:
BodyHandlers.ofString()
: Convierte el cuerpo en un StringBodyHandlers.ofInputStream()
: Proporciona un InputStream para procesar los datosBodyHandlers.ofFile(Path)
: Guarda la respuesta directamente en un archivoBodyHandlers.ofByteArray()
: Convierte el cuerpo en un array de bytes
Peticiones asíncronas
Una de las características más potentes de la nueva API es el soporte nativo para operaciones asíncronas mediante CompletableFuture
:
CompletableFuture<HttpResponse<String>> futureResponse =
client.sendAsync(request, HttpResponse.BodyHandlers.ofString());
// Procesamiento asíncrono de la respuesta
futureResponse.thenApply(HttpResponse::body)
.thenAccept(System.out::println)
.join(); // Esperar a que se complete (opcional)
Este enfoque asíncrono permite realizar múltiples solicitudes en paralelo sin bloquear el hilo principal, lo que resulta especialmente útil para aplicaciones que necesitan alta concurrencia.
Manejo de autenticación
El cliente HTTP moderno también facilita la implementación de mecanismos de autenticación:
HttpClient client = HttpClient.newBuilder()
.authenticator(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(
"usuario", "contraseña".toCharArray());
}
})
.build();
Soporte para WebSockets
Otra característica importante es el soporte nativo para WebSockets, permitiendo comunicaciones bidireccionales en tiempo real:
WebSocket.Builder wsBuilder = client.newWebSocketBuilder();
WebSocket webSocket = wsBuilder.buildAsync(
URI.create("ws://servidor.ejemplo.com/socket"),
new WebSocket.Listener() {
@Override
public CompletionStage<?> onText(WebSocket webSocket,
CharSequence data,
boolean last) {
System.out.println("Mensaje recibido: " + data);
return WebSocket.Listener.super.onText(webSocket, data, last);
}
}).join();
// Enviar un mensaje
webSocket.sendText("Hola, servidor", true);
Ventajas sobre las APIs anteriores
El cliente HTTP moderno ofrece varias mejoras significativas sobre HttpURLConnection
:
- API fluida con patrón builder que facilita la configuración
- Soporte nativo para operaciones asíncronas
- Implementación de HTTP/2 con multiplexación de conexiones
- Mejor manejo de errores y excepciones más informativas
- Procesadores de cuerpo flexibles para diferentes tipos de respuestas
- Rendimiento mejorado gracias a la implementación moderna
Esta nueva API representa un gran avance en la forma de realizar comunicaciones HTTP en Java, alineándose con las prácticas modernas de desarrollo y proporcionando herramientas potentes para crear aplicaciones conectadas eficientes.
Realizar peticiones GET simples
Las peticiones GET son el tipo más común de solicitud HTTP, utilizadas para recuperar información de un servidor sin modificar ningún dato. Con el cliente HTTP moderno de Java, realizar estas peticiones se ha vuelto mucho más intuitivo y directo.
Estructura básica de una petición GET
Para realizar una petición GET simple, necesitamos seguir tres pasos fundamentales:
- Crear un cliente HTTP
- Construir una solicitud GET
- Enviar la solicitud y procesar la respuesta
Veamos un ejemplo completo:
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
public class SimpleGetExample {
public static void main(String[] args) throws Exception {
// 1. Crear el cliente HTTP
HttpClient client = HttpClient.newHttpClient();
// 2. Construir la solicitud GET
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://jsonplaceholder.typicode.com/posts/1"))
.timeout(Duration.ofSeconds(5))
.GET() // Este método es opcional, ya que GET es el predeterminado
.build();
// 3. Enviar la solicitud y recibir la respuesta como String
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
// 4. Procesar la respuesta
System.out.println("Código de estado: " + response.statusCode());
System.out.println("Cuerpo de la respuesta: " + response.body());
}
}
Este ejemplo muestra la forma más directa de realizar una petición GET. Observa que el método .GET()
es técnicamente opcional, ya que es el método predeterminado cuando construimos una solicitud HTTP.
Configuración de parámetros de consulta (query parameters)
Muchas APIs requieren parámetros de consulta para filtrar o personalizar los resultados. Estos parámetros se añaden a la URI:
// Construir una URI con parámetros de consulta
URI uri = URI.create("https://api.openweathermap.org/data/2.5/weather?q=Madrid&appid=tu_api_key&units=metric");
HttpRequest request = HttpRequest.newBuilder()
.uri(uri)
.build();
Para una construcción más dinámica de parámetros, podemos utilizar la clase URLBuilder
o simplemente concatenar los parámetros de forma segura:
String ciudad = "Madrid";
String apiKey = "tu_api_key";
String unidades = "metric";
String endpoint = "https://api.openweathermap.org/data/2.5/weather";
String queryParams = String.format("?q=%s&appid=%s&units=%s",
ciudad, apiKey, unidades);
URI uri = URI.create(endpoint + queryParams);
Configuración de encabezados (headers)
Los encabezados HTTP proporcionan metadatos adicionales sobre la solicitud. Son esenciales para muchas APIs que requieren autenticación o especificación del formato de datos:
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.github.com/users/octocat"))
.header("Accept", "application/json")
.header("User-Agent", "Java HttpClient Bot")
.build();
Para añadir múltiples valores al mismo encabezado, podemos usar el método headers()
:
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.ejemplo.com/recursos"))
.headers("Accept", "application/json",
"Authorization", "Bearer " + token,
"User-Agent", "Java 11 HttpClient")
.build();
Manejo de respuestas
El cliente HTTP moderno ofrece diferentes procesadores de cuerpo (body handlers) para convertir la respuesta al formato deseado:
// Obtener la respuesta como String
HttpResponse<String> textResponse = client.send(request,
HttpResponse.BodyHandlers.ofString());
// Obtener la respuesta como array de bytes
HttpResponse<byte[]> bytesResponse = client.send(request,
HttpResponse.BodyHandlers.ofByteArray());
// Guardar la respuesta directamente en un archivo
HttpResponse<Path> fileResponse = client.send(request,
HttpResponse.BodyHandlers.ofFile(Paths.get("respuesta.json")));
Manejo de códigos de estado
Es importante verificar el código de estado de la respuesta para asegurarse de que la solicitud se procesó correctamente:
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
int statusCode = response.statusCode();
if (statusCode >= 200 && statusCode < 300) {
// Éxito - procesar la respuesta
System.out.println("Datos recibidos: " + response.body());
} else if (statusCode == 404) {
// Recurso no encontrado
System.out.println("El recurso solicitado no existe");
} else {
// Otro error
System.out.println("Error en la solicitud: " + statusCode);
System.out.println("Mensaje: " + response.body());
}
Configuración de timeouts
Para evitar que las solicitudes se bloqueen indefinidamente, es recomendable configurar tiempos de espera:
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.ejemplo.com/datos"))
.timeout(Duration.ofSeconds(10)) // La solicitud fallará después de 10 segundos
.build();
Ejemplo práctico: Consulta a una API pública
Veamos un ejemplo completo que consulta la API pública de OpenWeatherMap para obtener el clima actual:
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
public class WeatherApiExample {
public static void main(String[] args) {
try {
// Parámetros de la consulta
String ciudad = "Barcelona";
String apiKey = "tu_api_key"; // Reemplaza con tu clave API real
// Construir la URI
String url = String.format(
"https://api.openweathermap.org/data/2.5/weather?q=%s&appid=%s&units=metric",
ciudad, apiKey);
// Crear el cliente y la solicitud
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.timeout(Duration.ofSeconds(5))
.header("Accept", "application/json")
.build();
// Enviar la solicitud
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
// Verificar y procesar la respuesta
if (response.statusCode() == 200) {
String jsonResponse = response.body();
System.out.println("Datos del clima para " + ciudad + ":");
System.out.println(jsonResponse);
// Aquí podrías usar una biblioteca JSON para parsear la respuesta
// y extraer información específica como temperatura, humedad, etc.
} else {
System.out.println("Error al obtener datos: " + response.statusCode());
System.out.println(response.body());
}
} catch (Exception e) {
System.out.println("Error en la solicitud: " + e.getMessage());
e.printStackTrace();
}
}
}
Manejo de redirecciones
Por defecto, el cliente HTTP sigue las redirecciones automáticamente. Sin embargo, podemos personalizar este comportamiento:
HttpClient client = HttpClient.newBuilder()
.followRedirects(HttpClient.Redirect.NORMAL) // Seguir redirecciones normales
.build();
// Otras opciones:
// HttpClient.Redirect.ALWAYS - Seguir todas las redirecciones
// HttpClient.Redirect.NEVER - No seguir ninguna redirección
Buenas prácticas para peticiones GET
- Siempre configura timeouts para evitar bloqueos indefinidos
- Verifica los códigos de estado antes de procesar la respuesta
- Maneja las excepciones adecuadamente para proporcionar mensajes de error útiles
- Reutiliza las instancias de HttpClient cuando sea posible, ya que son thread-safe y mantienen un pool de conexiones
- Incluye encabezados User-Agent para identificar tu aplicación ante los servidores
Con estas técnicas, puedes realizar peticiones GET de forma eficiente y robusta utilizando el cliente HTTP moderno de Java, aprovechando todas las ventajas que ofrece esta API sobre las implementaciones anteriores.
Realizar peticiones POST simples
A diferencia de las peticiones GET que solicitan información, las peticiones POST se utilizan para enviar datos al servidor para crear o actualizar recursos. El cliente HTTP moderno de Java facilita enormemente la realización de estas operaciones, proporcionando una API fluida y potente para construir y enviar solicitudes POST.
Anatomía de una petición POST
Una petición POST típicamente contiene:
- Una URI de destino
- Encabezados HTTP (incluyendo Content-Type)
- Un cuerpo (body) con los datos a enviar
- Opcionalmente, parámetros de configuración como timeouts
La principal diferencia con las peticiones GET es la inclusión del cuerpo de la solicitud, que puede contener datos en diversos formatos como JSON, XML, formularios o datos binarios.
Envío de datos JSON
El formato JSON es ampliamente utilizado en APIs modernas. Para enviar datos JSON, necesitamos configurar el encabezado Content-Type
adecuadamente y proporcionar el cuerpo de la solicitud:
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
public class JsonPostExample {
public static void main(String[] args) throws Exception {
// Crear el cliente HTTP
HttpClient client = HttpClient.newHttpClient();
// Datos a enviar en formato JSON
String jsonData = """
{
"title": "Nuevo artículo",
"body": "Contenido del artículo",
"userId": 1
}
""";
// Construir la solicitud POST
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://jsonplaceholder.typicode.com/posts"))
.timeout(Duration.ofSeconds(10))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(jsonData))
.build();
// Enviar la solicitud y recibir la respuesta
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
// Procesar la respuesta
System.out.println("Código de estado: " + response.statusCode());
System.out.println("Respuesta: " + response.body());
}
}
El elemento clave aquí es el método POST()
que recibe un BodyPublisher. Este componente se encarga de publicar el contenido del cuerpo de la solicitud.
Publicadores de cuerpo (BodyPublishers)
Java proporciona varios publicadores predefinidos para diferentes tipos de datos:
- ofString(): Para enviar texto plano o JSON como String
- ofByteArray(): Para enviar datos binarios
- ofFile(): Para enviar el contenido de un archivo
- ofInputStream(): Para enviar datos desde un InputStream
- noBody(): Para solicitudes sin cuerpo
// Enviar datos desde un archivo
HttpRequest.BodyPublishers.ofFile(Path.of("datos.json"))
// Enviar datos binarios
byte[] datos = obtenerDatosBinarios();
HttpRequest.BodyPublishers.ofByteArray(datos)
// Enviar desde un InputStream
InputStream stream = obtenerStream();
HttpRequest.BodyPublishers.ofInputStream(() -> stream)
Envío de formularios
Para enviar datos de formulario (formato application/x-www-form-urlencoded
), necesitamos formatear los datos correctamente:
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.StringJoiner;
public class FormPostExample {
public static void main(String[] args) throws Exception {
HttpClient client = HttpClient.newHttpClient();
// Datos del formulario
Map<String, String> formData = new HashMap<>();
formData.put("username", "usuario123");
formData.put("password", "clave456");
formData.put("action", "login");
// Codificar los datos del formulario
StringJoiner sj = new StringJoiner("&");
for (Map.Entry<String, String> entry : formData.entrySet()) {
sj.add(URLEncoder.encode(entry.getKey(), StandardCharsets.UTF_8) + "=" +
URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8));
}
String formBody = sj.toString();
// Construir la solicitud POST
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://httpbin.org/post"))
.timeout(Duration.ofSeconds(10))
.header("Content-Type", "application/x-www-form-urlencoded")
.POST(HttpRequest.BodyPublishers.ofString(formBody))
.build();
// Enviar la solicitud
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println("Código de estado: " + response.statusCode());
System.out.println("Respuesta: " + response.body());
}
}
Envío de datos multipart (archivos y formularios)
Para enviar datos multipart (como formularios con archivos adjuntos), necesitamos crear manualmente el cuerpo multipart con los límites (boundaries) adecuados:
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.UUID;
public class MultipartPostExample {
public static void main(String[] args) throws Exception {
HttpClient client = HttpClient.newHttpClient();
// Generar un boundary único para separar las partes
String boundary = UUID.randomUUID().toString();
// Archivo a subir
Path filePath = Path.of("imagen.jpg");
String filename = filePath.getFileName().toString();
String mimeType = Files.probeContentType(filePath);
byte[] fileData = Files.readAllBytes(filePath);
// Construir el cuerpo multipart
String separator = "--" + boundary + "\r\nContent-Disposition: form-data; ";
String end = "\r\n--" + boundary + "--\r\n";
// Parte 1: campo de texto
StringBuilder builder = new StringBuilder();
builder.append(separator)
.append("name=\"descripcion\"\r\n\r\n")
.append("Mi imagen de perfil")
.append("\r\n");
// Parte 2: archivo
builder.append(separator)
.append("name=\"archivo\"; filename=\"")
.append(filename)
.append("\"\r\nContent-Type: ")
.append(mimeType)
.append("\r\n\r\n");
// Convertir el inicio y el final a bytes
byte[] start = builder.toString().getBytes(StandardCharsets.UTF_8);
byte[] newline = "\r\n".getBytes(StandardCharsets.UTF_8);
byte[] endBytes = end.getBytes(StandardCharsets.UTF_8);
// Combinar todas las partes en un solo array
byte[] requestBody = new byte[start.length + fileData.length + newline.length + endBytes.length];
System.arraycopy(start, 0, requestBody, 0, start.length);
System.arraycopy(fileData, 0, requestBody, start.length, fileData.length);
System.arraycopy(newline, 0, requestBody, start.length + fileData.length, newline.length);
System.arraycopy(endBytes, 0, requestBody, start.length + fileData.length + newline.length, endBytes.length);
// Construir la solicitud POST
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://httpbin.org/post"))
.header("Content-Type", "multipart/form-data; boundary=" + boundary)
.POST(HttpRequest.BodyPublishers.ofByteArray(requestBody))
.build();
// Enviar la solicitud
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println("Código de estado: " + response.statusCode());
System.out.println("Respuesta: " + response.body());
}
}
Aunque este enfoque funciona, para aplicaciones reales se recomienda utilizar bibliotecas como Apache HttpComponents o OkHttp que simplifican considerablemente el manejo de solicitudes multipart.
Peticiones POST asíncronas
Al igual que con las peticiones GET, podemos realizar solicitudes POST de forma asíncrona:
import java.util.concurrent.CompletableFuture;
public class AsyncPostExample {
public static void main(String[] args) {
HttpClient client = HttpClient.newHttpClient();
String jsonData = "{\"nombre\":\"Juan\",\"edad\":30}";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://httpbin.org/post"))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(jsonData))
.build();
// Enviar la solicitud de forma asíncrona
CompletableFuture<HttpResponse<String>> futureResponse =
client.sendAsync(request, HttpResponse.BodyHandlers.ofString());
// Procesar la respuesta cuando esté disponible
futureResponse
.thenApply(response -> {
System.out.println("Código de estado: " + response.statusCode());
return response.body();
})
.thenAccept(body -> System.out.println("Respuesta: " + body))
.exceptionally(ex -> {
System.err.println("Error en la solicitud: " + ex.getMessage());
return null;
});
// Hacer otras tareas mientras se procesa la solicitud
System.out.println("Solicitud enviada, continuando con otras tareas...");
// Esperar a que se complete la solicitud (solo para este ejemplo)
futureResponse.join();
}
}
Este enfoque es especialmente útil cuando necesitas realizar múltiples solicitudes en paralelo o no quieres bloquear el hilo principal.
Manejo de respuestas en peticiones POST
El procesamiento de respuestas para peticiones POST es similar al de las peticiones GET, pero con algunas consideraciones adicionales:
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
int statusCode = response.statusCode();
switch (statusCode) {
case 201: // Created
System.out.println("Recurso creado exitosamente");
System.out.println("URI del nuevo recurso: " +
response.headers().firstValue("Location").orElse("No disponible"));
break;
case 200: // OK
System.out.println("Operación completada con éxito");
break;
case 400: // Bad Request
System.out.println("Error en los datos enviados: " + response.body());
break;
case 401: // Unauthorized
case 403: // Forbidden
System.out.println("Error de autenticación o autorización");
break;
case 422: // Unprocessable Entity
System.out.println("Datos válidos pero inaceptables: " + response.body());
break;
default:
System.out.println("Respuesta inesperada: " + statusCode);
System.out.println("Cuerpo: " + response.body());
}
Ejemplo práctico: Creación de un recurso en una API REST
Veamos un ejemplo completo que crea un nuevo usuario en una API REST:
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
public class CreateUserExample {
public static void main(String[] args) {
try {
// Crear el cliente HTTP
HttpClient client = HttpClient.newHttpClient();
// Datos del nuevo usuario en formato JSON
String userData = """
{
"name": "Ana García",
"email": "ana.garcia@ejemplo.com",
"gender": "female",
"status": "active"
}
""";
// Construir la solicitud POST
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://gorest.co.in/public/v2/users"))
.timeout(Duration.ofSeconds(15))
.header("Content-Type", "application/json")
.header("Authorization", "Bearer TU_TOKEN_DE_ACCESO") // Reemplazar con tu token real
.POST(HttpRequest.BodyPublishers.ofString(userData))
.build();
// Enviar la solicitud
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
// Procesar la respuesta
if (response.statusCode() == 201) {
System.out.println("Usuario creado exitosamente:");
System.out.println(response.body());
} else {
System.out.println("Error al crear usuario. Código: " + response.statusCode());
System.out.println("Respuesta: " + response.body());
}
} catch (Exception e) {
System.out.println("Error en la solicitud: " + e.getMessage());
e.printStackTrace();
}
}
}
Buenas prácticas para peticiones POST
- Siempre especifica el encabezado Content-Type adecuado para el formato de datos que estás enviando
- Valida los datos antes de enviarlos para evitar errores 400 (Bad Request)
- Maneja adecuadamente los diferentes códigos de estado que pueden devolver las APIs
- Implementa reintentos para errores transitorios (como 429 Too Many Requests o 503 Service Unavailable)
- Considera la seguridad utilizando HTTPS y tokens de autenticación cuando sea necesario
- Limita el tamaño de los datos enviados para evitar problemas de rendimiento
Con estas técnicas, puedes realizar peticiones POST de manera efectiva utilizando el cliente HTTP moderno de Java, aprovechando su API fluida y su soporte para operaciones tanto síncronas como asíncronas.
Ejercicios de esta lección HttpClient moderno
Evalúa tus conocimientos de esta lección HttpClient moderno con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.
Streams: match
Gestión de errores y excepciones
CRUD en Java de modelo Customer sobre un ArrayList
Clases abstractas
Listas
Métodos de la clase String
Streams: reduce()
API java.nio 2
Polimorfismo
Pattern Matching
Streams: flatMap()
Llamada y sobrecarga de funciones
Métodos referenciados
Métodos de la clase String
Representación de Fecha
Operadores lógicos
Inferencia de tipos con var
Tipos de datos
Estructuras de iteración
Streams: forEach()
Objetos
Funciones lambda
Uso de Scanner
Tipos de variables
Streams: collect()
Operadores aritméticos
Arrays y matrices
Clases y objetos
Interfaz funcional Consumer
CRUD en Java de modelo Customer sobre un HashMap
Interfaces
Enumeraciones Enums
API Optional
Interfaz funcional Function
Encapsulación
Interfaces
Uso de API Optional
Representación de Hora
Herencia básica
Clases y objetos
Interfaz funcional Supplier
HashMap
Sobrecarga de métodos
Polimorfismo de tiempo de ejecución
OOP en Java
Sobrecarga de métodos
CRUD de productos en Java
Clases sealed
Creación de Streams
Records
Encapsulación
Streams: min max
Herencia
Métodos avanzados de la clase String
Funciones
Polimorfismo de tiempo de compilación
Reto sintaxis Java
Conjuntos
Estructuras de control
Recursión
Excepciones
Herencia avanzada
Estructuras de selección
Uso de interfaces
Operadores
Variables
HashSet
Objeto Scanner
Streams: filter()
Operaciones de Streams
Interfaz funcional Predicate
Streams: sorted()
Configuración de entorno
Uso de variables
Clases
Streams: distinct()
Streams: count()
ArrayList
Mapas
Datos de referencia
Interfaces funcionales
Métodos básicos de la clase String
Tipos de datos
Clases abstractas
Instalación
Funciones
Excepciones
Estructuras de control
Herencia de clases
La clase Scanner
Generics
Streams: map()
Funciones y encapsulamiento
Todas las lecciones de Java
Accede a todas las lecciones de Java y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.
Instalación De Java
Introducción Y Entorno
Configuración De Entorno Java
Introducción Y Entorno
Tipos De Datos
Sintaxis
Variables
Sintaxis
Operadores
Sintaxis
Estructuras De Control
Sintaxis
Funciones
Sintaxis
Recursión
Sintaxis
Arrays Y Matrices
Sintaxis
Excepciones
Programación Orientada A Objetos
Clases Y Objetos
Programación Orientada A Objetos
Encapsulación
Programación Orientada A Objetos
Herencia
Programación Orientada A Objetos
Clases Abstractas
Programación Orientada A Objetos
Interfaces
Programación Orientada A Objetos
Sobrecarga De Métodos
Programación Orientada A Objetos
Polimorfismo
Programación Orientada A Objetos
La Clase Scanner
Programación Orientada A Objetos
Métodos De La Clase String
Programación Orientada A Objetos
Excepciones
Programación Orientada A Objetos
Records
Programación Orientada A Objetos
Pattern Matching
Programación Orientada A Objetos
Inferencia De Tipos Con Var
Programación Orientada A Objetos
Enumeraciones Enums
Programación Orientada A Objetos
Generics
Programación Orientada A Objetos
Clases Sealed
Programación Orientada A Objetos
Listas
Framework Collections
Conjuntos
Framework Collections
Mapas
Framework Collections
Funciones Lambda
Programación Funcional
Interfaz Funcional Consumer
Programación Funcional
Interfaz Funcional Predicate
Programación Funcional
Interfaz Funcional Supplier
Programación Funcional
Interfaz Funcional Function
Programación Funcional
Métodos Referenciados
Programación Funcional
Creación De Streams
Programación Funcional
Operaciones Intermedias Con Streams: Map()
Programación Funcional
Operaciones Intermedias Con Streams: Filter()
Programación Funcional
Operaciones Intermedias Con Streams: Distinct()
Programación Funcional
Operaciones Finales Con Streams: Collect()
Programación Funcional
Operaciones Finales Con Streams: Min Max
Programación Funcional
Operaciones Intermedias Con Streams: Flatmap()
Programación Funcional
Operaciones Intermedias Con Streams: Sorted()
Programación Funcional
Operaciones Finales Con Streams: Reduce()
Programación Funcional
Operaciones Finales Con Streams: Foreach()
Programación Funcional
Operaciones Finales Con Streams: Count()
Programación Funcional
Operaciones Finales Con Streams: Match
Programación Funcional
Api Optional
Programación Funcional
Transformación
Programación Funcional
Reducción Y Acumulación
Programación Funcional
Mapeo
Programación Funcional
Streams Paralelos
Programación Funcional
Agrupación Y Partición
Programación Funcional
Filtrado Y Búsqueda
Programación Funcional
Api Java.nio 2
Entrada Y Salida Io
Fundamentos De Io
Entrada Y Salida Io
Leer Y Escribir Archivos
Entrada Y Salida Io
Httpclient Moderno
Entrada Y Salida Io
Clases De Nio2
Entrada Y Salida Io
Api Java.time
Api Java.time
Localtime
Api Java.time
Localdatetime
Api Java.time
Localdate
Api Java.time
Executorservice
Concurrencia
Virtual Threads (Project Loom)
Concurrencia
Future Y Completablefuture
Concurrencia
Spring Framework
Frameworks Para Java
Micronaut
Frameworks Para Java
Maven
Frameworks Para Java
Gradle
Frameworks Para Java
Lombok Para Java
Frameworks Para Java
Quarkus
Frameworks Para Java
Ecosistema Jakarta Ee De Java
Frameworks Para Java
Introducción A Junit 5
Testing
Certificados de superación de Java
Supera todos los ejercicios de programación del curso de Java y obtén certificados de superación para mejorar tu currículum y tu empleabilidad.
En esta lección
Objetivos de aprendizaje de esta lección
- Comprender la estructura y componentes principales de la API HttpClient moderna en Java 11+.
- Realizar peticiones HTTP GET y POST utilizando la API fluida y builder pattern.
- Configurar y manejar encabezados, parámetros, timeouts y códigos de estado en las solicitudes HTTP.
- Implementar operaciones asíncronas con CompletableFuture para mejorar la concurrencia.
- Aplicar buenas prácticas en el manejo de autenticación, multipart/form-data y procesamiento de respuestas HTTP.