Características HttpUrlConnection de java.net

Hola

Hoy trataré de hablar sobre cómo puede enviar una solicitud y leer la respuesta del servidor HTTP utilizando URLConnection de la biblioteca JRE.

Actualmente estamos aprendiendo Java en línea. Todo nuestro equipo usa Slack para el trabajo y la comunicación. Para obtener información sobre los usuarios, utilizamos la API de Slack. Para no hablar sobre la API en sí durante mucho tiempo (este es un tema para un artículo separado), diré brevemente: la API de Slack se basa en el protocolo HTTP, para obtener información sobre los usuarios, debe enviar una solicitud con un URI en el que debe haber un nombre de método de la API a la API de la dirección del host . slack.com Aquí hay una lista de algunos métodos:
  • users.list
  • chat.postMessage
  • conversaciones.crear
  • archivos.upload
  • estoy abierto

Para obtener una lista de usuarios, necesita el método users.list. Formamos el URI - /api/users.list en el cuerpo de la solicitud, debería haber un token de autenticación en el formulario application / x-www-form-urlencoded, es decir, la solicitud debería verse así (pero hay un matiz que será menor):

GET /users.list HTTP/1.1 Content-Type: application/x-www-form-urlencoded token=xoxp-1234567890-098765-4321-a1b2c3d4e5 


Conocía la biblioteca Apache HttpComponents, pero para fines de investigación utilizaremos las herramientas disponibles en la biblioteca estándar Java 8, es decir, la implementación de java.net.URLConnection.

Para obtener la entidad URLConnection, debe usar el objeto de la clase java.net.URL, su constructor toma el tipo String donde, además de todo, debe especificarse el protocolo, en nuestro caso, https.

Después de recibir la entidad URL, llamamos al método openConnection () que devolverá la entidad HttpsUrlConnection.

 String url = “https://slack.com/api/users.list”; URLConnection connection = new URL(url).openConnection(); 

En este caso, debe manejar o lanzar MalformedUrlException e IOException.

Después de eso, la variable de conexión almacenará una referencia al objeto HttpsUrlConnectionImpl. Por defecto, se generará una solicitud GET. Para agregar un encabezado, utilizamos el método setRequestProperty () , que acepta clave y valor. Necesitamos instalar un Content-Type aquí que tenga el valor application / x-www-form-urlencoded . Bueno, y lo hacemos!
 connection.setRequestProperty(“Content-Type”, “application/x-www-form-urlencoded”); 

Ahora solo queda enviar una solicitud escribiendo nuestro token y límite en el cuerpo. Para hacer esto, establezca el campo doOutput del objeto de conexión en verdadero utilizando el método setDoOutput () ;

 connection.setDoOutput(true); 

A continuación, la parte más interesante: debe pasar de alguna manera nuestro cuerpo de solicitud a un OutputStream. Utilizaremos OutputStreamWriter:

 OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream()); 

Hay una advertencia: después de que llamamos al método getOutputStream (), el método de solicitud cambia a POST, ya que GET no proporciona el cuerpo de la solicitud, pero dado que la holgura no impone una restricción estricta sobre el método, todo estuvo bien. Y entonces la solicitud GET debería verse así:
 GET /users.list?token=xoxp-1234567890-098765-4321-a1b2c3d4e5&limit=100 HTTP/1.1 Content-Type: application/x-www-form-urlencoded 

Pero no comencé a rehacerlo. Y en cambio, nuestra solicitud resultó así:

 POST /users.list HTTP/1.1 Content-Type: application/x-www-form-urlencoded token=xoxp-1234567890-098765-4321-a1b2c3d4e5 

(* algunos encabezados son configurados por HttpsUrlConnection y están ausentes aquí)

Y así, para escribir nuestro cuerpo de solicitud, usamos write ();.
 String reqBody = “token=xoxp-1234567890-098765-4321-a1b2c3d4e5&limit=100”; writer.write(reqBody); writer.close(); 

Después de eso, se enviará nuestra solicitud y podremos leer la respuesta recibida. Es importante cerrar OutputStream o hacer flush () antes de recibir un InputStream, de lo contrario los datos no saldrán del búfer (alternativamente, puede usar PrintStream - en el método println (), se llama a flush () por defecto). Para leer usé BufferedReader:
 StringBuilder respBody = new StringBuilder(); BufferedReader reader = new BufferedReader(connection.getInputStream()); reader.lines().forEach(l -> respBody.append(l + “\r\n”); reader.close(); 

(* use lines () para obtener Stream en la salida; \ r \ n - carácter CRLF - inserta una transición a una nueva línea)

Y, si nos autenticamos con éxito, la variable respBody debería almacenar nuestra respuesta del servidor, que en nuestro caso es un objeto JSON. Después de eso, se puede enviar a la siguiente etapa de procesamiento.

Después de cierta optimización, todo se ve así:

 package main.java.com.bilichenko.learning; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.nio.charset.Charset; import java.util.Optional; import java.util.stream.Collectors; public class SlackClient { private static final String HOST = "https://api.slack.com"; private static final String GET_USERS_URI = "/api/users.list"; private static final String TOKEN = "xx-ooo-YOUR-TOKEN-HERE"; public static void main(String[] args) throws IOException { SlackClient slackClient = new SlackClient(); System.out.println(slackClient.getRawResponse(HOST + GET_USERS_URI, "application/x-www-form-urlencoded", "token=" + TOKEN).orElse("no response")); } public Optional<String> getRawResponse(String url, String contentType, String requestBody) throws MalformedURLException, IOException { HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection(); connection.setRequestProperty("Content-Type", contentType); connection.setConnectTimeout(10000); connection.setRequestMethod("POST"); connection.setDoOutput(true); try(OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream())) { writer.write(requestBody); } if (connection.getResponseCode() != 200) { System.err.println("connection failed"); return Optional.empty(); } try(BufferedReader reader = new BufferedReader( new InputStreamReader(connection.getInputStream(), Charset.forName("utf-8")))) { return Optional.of(reader.lines().collect(Collectors.joining(System.lineSeparator()))); } } } 

¡Espero que haya sido útil!

Source: https://habr.com/ru/post/459080/


All Articles