String message = URLEncoder.encode("my message", "UTF-8");
try {
// instantiate the URL object with the target URL of the resource to
// request
URL url = new URL("http://www.example.com/comment");
// instantiate the HttpURLConnection with the URL object - A new
// connection is opened every time by calling the openConnection
// method of the protocol handler for this URL.
// 1. This is the point where the connection is opened.
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
// set connection output to true
connection.setDoOutput(true);
// instead of a GET, we're going to send using method="POST"
connection.setRequestMethod("POST");
// instantiate OutputStreamWriter using the output stream, returned
// from getOutputStream, that writes to this connection.
// 2. This is the point where you'll know if the connection was
// successfully established. If an I/O error occurs while creating
// the output stream, you'll see an IOException.
OutputStreamWriter writer = new OutputStreamWriter(
connection.getOutputStream());
// write data to the connection. This is data that you are sending
// to the server
// 3. No. Sending the data is conducted here. We established the
// connection with getOutputStream
writer.write("message=" + message);
// Closes this output stream and releases any system resources
// associated with this stream. At this point, we've sent all the
// data. Only the outputStream is closed at this point, not the
// actual connection
writer.close();
// if there is a response code AND that response code is 200 OK, do
// stuff in the first if block
if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
// OK
// otherwise, if any other status code is returned, or no status
// code is returned, do stuff in the else block
} else {
// Server returned HTTP error code.
}
} catch (MalformedURLException e) {
// ...
} catch (IOException e) {
// ...
}
在上面的示例HTTP POST中,每种方法旁边的问题的前3个答案均作为内联注释列出。
从getOutputStream:
返回写入此连接的输出流。
基本上,我认为您对它的工作原理有很好的了解,所以让我重申一下外行的话。getOutputStream
基本上是打开连接流,目的是将数据写入服务器。在上面的代码示例中,“消息”可能是我们要发送到服务器的评论,它代表了帖子上留下的评论。看到时getOutputStream
,您正在打开连接流以进行写入,但是实际上直到调用才真正写入任何数据writer.write("message=" + message);
。
从getInputStream():
返回从此打开的连接读取的输入流。如果读取超时在可读取数据之前到期,则从返回的输入流进行读取时会抛出SocketTimeoutException。
getInputStream
相反。像一样getOutputStream
,它也打开一个连接流,但目的是从服务器读取数据,而不是向其写入数据。如果连接或流打开失败,您将看到一个SocketTimeoutException
。
getInputStream怎么样?由于我只能在getInputStream上获得响应,那么这是否意味着我没有在getOutputStream上发送任何请求,而只是建立了连接?
请记住,发送请求和发送数据是两种不同的操作。调用getOutputStream或getInputStream时 url.openConnection()
,会将请求发送到服务器以建立连接。服务器会向您发送确认已建立连接的确认,这时会发生握手。然后就是在该时间点,您准备发送或接收数据。因此,除非您发出请求的目的是发送数据,否则无需调用getOutputStream 建立打开流的连接。
用外行的话来说,发出getInputStream
请求等同于打电话给您朋友的房子说:“嘿,如果我过来借用那副老虎钳,可以吗?” 然后您的朋友通过说“确定!快来得到它”来建立握手。然后,此时建立连接,您可以步行到朋友家,敲门,要求使用虎钳,然后返回家中。
使用一个类似的例子,getOutputStream
您可能会打电话给您的朋友,并说:“嘿,我欠您的钱,可以寄给您吗?”?您的朋友在里面需要钱和生病,以至于您把钱存放了这么久,他说:“当然,过来吧,这便宜的混蛋。” 因此,您步行到朋友家,然后将钱“邮寄”给他。然后,他将您踢出去,然后您回到家中。
现在,继续外行的示例,让我们看一些例外。如果您给朋友打电话而他不在家,则可能是500错误。如果您打来电话并收到一条断线电话号码的消息,是因为您的朋友一直不厌其烦地借钱,则找不到404页。如果您的手机因未付款而没电了,则可能是IOException。(注意:本部分可能并非100%正确。它旨在使您大致了解外行的情况。)
问题5:
是的,您是正确的,openConnection只会创建一个新的连接对象,而不会建立它。当您调用getInputStream或getOutputStream时,将建立连接。
openConnection
创建一个新的连接对象。从URL.openConnection javadocs:
每次通过为此URL调用协议处理程序的openConnection方法打开一个新连接。
当您调用openConnection时建立连接,并在实例化它们时同时调用InputStream和OutputStream。
问题6:
为了测量开销,我通常在整个连接块周围包装一些非常简单的计时代码,如下所示:
long start = System.currentTimeMillis();
log.info("Time so far = " + new Long(System.currentTimeMillis() - start) );
// run the above example code here
log.info("Total time to send/receive data = " + new Long(System.currentTimeMillis() - start) );
我确定有更多高级方法可以测量请求时间和开销,但这通常足以满足我的需求。
有关不要求关闭连接的信息,请参阅在Java中URL连接何时关闭?。