Recursos HttpUrlConnection de java.net

Olá

Hoje vou tentar falar sobre como você pode enviar uma solicitação e ler a resposta do servidor HTTP usando o URLConnection da biblioteca JRE.

No momento, estamos aprendendo Java online. Toda a nossa equipe usa o Slack para trabalho e comunicação. Para obter informações sobre usuários, usamos a API do Slack. Para não falar sobre a própria API por um longo tempo (este é um tópico para um artigo separado), direi brevemente: a Slack API é construída sobre o protocolo HTTP, para obter informações sobre os usuários, você precisa enviar uma solicitação com um URI no qual deve haver um nome de método da API para a API do endereço do host . slack.com Aqui está uma lista de alguns métodos:
  • users.list
  • chat.postMessage
  • conversations.create
  • files.upload
  • im.open

Para obter uma lista de usuários, você precisa do método users.list. Como formamos o URI - /api/users.list no corpo da solicitação, deve haver um token de autenticação no formulário application / x-www-form-urlencoded, ou seja, a solicitação deve se parecer com isso (mas há uma nuance menor):

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


Eu conhecia a biblioteca Apache HttpComponents, mas para fins de pesquisa, usaremos as ferramentas disponíveis na biblioteca Java 8 padrão, a saber, a implementação de java.net.URLConnection.

Para obter a entidade URLConnection, você precisa usar um objeto da classe java.net.URL, seu construtor usa o tipo String onde, além de tudo, o protocolo deve ser especificado - no nosso caso, https.

Depois de receber a entidade URL, chamamos o método openConnection () que retornará a entidade HttpsUrlConnection.

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

Nesse caso, você precisa manipular ou lançar MalformedUrlException e IOException.

Depois disso, a variável de conexão armazenará uma referência ao objeto HttpsUrlConnectionImpl. Por padrão, uma solicitação GET será gerada. Para adicionar um cabeçalho, usamos o método setRequestProperty () , que aceita chave e valor. Precisamos instalar um tipo de conteúdo aqui que tenha o valor application / x-www-form-urlencoded . Bem, e nós fazemos!
 connection.setRequestProperty(“Content-Type”, “application/x-www-form-urlencoded”); 

Agora resta apenas enviar uma solicitação escrevendo nosso token e limite no corpo. Para fazer isso, defina o campo doOutput do objeto de conexão como true usando o método setDoOutput () ;

 connection.setDoOutput(true); 

A seguir, a parte mais interessante - você precisa, de alguma forma, passar nosso corpo de solicitação para um OutputStream. Usaremos OutputStreamWriter:

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

Há uma ressalva: depois que chamamos o método getOutputStream (), o método request muda para POST, pois GET não fornece o corpo da solicitação, mas como o slack não impõe uma restrição estrita ao método, tudo correu bem. E assim a solicitação GET deve ficar assim:
 GET /users.list?token=xoxp-1234567890-098765-4321-a1b2c3d4e5&limit=100 HTTP/1.1 Content-Type: application/x-www-form-urlencoded 

Mas não comecei a refazê-lo. E, em vez disso, nosso pedido acabou assim:

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

(* alguns cabeçalhos são definidos pelo próprio HttpsUrlConnection e estão ausentes aqui)

E assim, para escrever nosso corpo de solicitação, usamos write ();.
 String reqBody = “token=xoxp-1234567890-098765-4321-a1b2c3d4e5&limit=100”; writer.write(reqBody); writer.close(); 

Depois disso, nosso pedido será enviado e podemos ler a resposta recebida. É importante fechar OutputStream ou flush () antes de receber um InputStream, caso contrário, os dados não sairão do buffer (como alternativa, você pode usar PrintStream - no método println (), flush () é chamado por padrão). Para a leitura, usei o 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 obter fluxo na saída; \ r \ n - caractere CRLF - insere uma transição para uma nova linha)

E, se autenticarmos com êxito, a variável respBody deverá armazenar nossa resposta do servidor, que no nosso caso é um objeto JSON. Depois disso, ele pode ser enviado para a próxima etapa do processamento.

Após alguma otimização, tudo fica assim:

 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 tenha sido útil!

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


All Articles