你好
今天,我将尝试讨论如何使用JRE库中的URLConnection发送请求并从HTTP服务器读取响应。
我们目前正在在线学习Java。 我们整个团队都使用Slack进行工作和沟通。 有关用户的信息,我们使用Slack API。 为了避免长时间谈论API本身(这是另一篇文章的主题),我将简短地说一遍:Slack API是基于HTTP协议构建的,要获取有关用户的信息,您需要发送一个带有URI的请求,其中URI中必须有一个方法名称,该API必须来自API到主机地址
api。 slack.com以下是一些方法的列表:
- users.list
- chat.postMessage
- 对话创建
- files.upload
- 即时开放
要获得用户列表,您需要users.list方法。 我们在请求主体中形成
URI-/api/users.list ,在应用程序/ x-www-form-urlencoded形式中应该有一个身份验证令牌,也就是说,请求应该看起来像这样(但是会有一个细微差别会更低):
GET /users.list HTTP/1.1 Content-Type: application/x-www-form-urlencoded token=xoxp-1234567890-098765-4321-a1b2c3d4e5
我知道Apache HttpComponents库,但是出于研究目的,我们将使用标准Java 8库中可用的工具,即java.net.URLConnection的实现。
要获取URLConnection实体,您需要使用java.net.URL类的对象,其构造函数采用String类型,在该类型中,除所有内容外,还必须指定协议-在我们的示例中为https。
收到URL实体后,我们调用
openConnection()方法,该方法将返回HttpsUrlConnection实体。
String url = “https:
在这种情况下,您需要处理或引发MalformedUrlException和IOException。
之后,连接变量将存储对HttpsUrlConnectionImpl对象的引用。 默认情况下,将生成一个GET请求,要添加Header,我们使用
setRequestProperty()方法,该方法接受键和值。 我们需要在此处安装一个Content-Type,其值为
application / x-www-form-urlencoded 。 好吧,我们做到了!
connection.setRequestProperty(“Content-Type”, “application/x-www-form-urlencoded”);
现在只剩下通过写我们的令牌和限制到正文中来发送请求了。 为此,请使用
setDoOutput()方法将连接对象的doOutput字段设置为true;
connection.setDoOutput(true);
接下来,最有趣的部分-您需要以某种方式将我们的请求正文传递给OutputStream。 我们将使用OutputStreamWriter:
OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream());
有一个警告:在我们调用getOutputStream()方法之后,由于GET不提供请求正文,因此请求方法更改为POST,但是好处是,松弛对方法没有严格限制,因此一切都很好。 因此,GET请求应如下所示:
GET /users.list?token=xoxp-1234567890-098765-4321-a1b2c3d4e5&limit=100 HTTP/1.1 Content-Type: application/x-www-form-urlencoded
但是我没有开始重做。 相反,我们的请求结果如下:
POST /users.list HTTP/1.1 Content-Type: application/x-www-form-urlencoded token=xoxp-1234567890-098765-4321-a1b2c3d4e5
(*一些标头是由HttpsUrlConnection自己设置的,此处不存在)
因此,要编写请求主体,请使用write();。
String reqBody = “token=xoxp-1234567890-098765-4321-a1b2c3d4e5&limit=100”; writer.write(reqBody); writer.close();
之后,我们的请求将被发送,我们可以读取收到的响应。 在接收InputStream之前关闭OutputStream或执行flush()很重要,否则数据将不会离开缓冲区(或者,您可以使用PrintStream-在println()方法中,默认调用flush())。 为了阅读,我使用了BufferedReader:
StringBuilder respBody = new StringBuilder(); BufferedReader reader = new BufferedReader(connection.getInputStream()); reader.lines().forEach(l -> respBody.append(l + “\r\n”); reader.close();
(*使用行()获得输出流; \ r \ n-CRLF字符-插入到新行的过渡)
并且,如果我们成功进行身份验证,则respBody变量应存储来自服务器的响应,在本例中为服务器的JSON对象。 之后,可以将其发送到下一个处理阶段。
经过一些优化后,一切看起来像这样:
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()))); } } }
希望对您有所帮助!