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 でまだリクエストを送信しておらず、単に接続を確立しているだけということですか?
リクエストの送信とデータの送信は 2 つの異なる操作であることに注意してください。getOutputStream または getInputStream を呼び出すときはurl.openConnection()
、サーバーにリクエストを送信して接続を確立します。接続が確立されたことを示す確認応答をサーバーが送り返すハンドシェイクが発生します。その時点で、データを送受信する準備が整います。したがって、要求を作成する目的がデータの送信である場合を除き、ストリームを開く接続を確立するために getOutputStream を呼び出す必要はありません。
依頼するということは、平たく言えばgetInputStream
、友達の家に電話して「あのバイスグリップを借りてもいいですか?」と言うようなものです。あなたの友人は、「もちろん!来て、それを手に入れてください」と言って握手を確立します。次に、その時点で接続が確立され、友人の家に歩いて行き、ドアをノックし、バイスグリップを要求し、家に戻ります.
同様の例を使用するとgetOutputStream
、友人に電話して、「ねえ、私はあなたに借りているお金があります。あなたに送ってもいいですか?」と言うでしょう? あなたの友人は、お金を必要としていて、あなたが長い間それを保管していたので病気になり、「もちろん、あなたの安いろくでなしに来てください」と言います。それで、あなたは友達の家に歩いて行き、彼にお金を「POST」します。その後、彼はあなたを追い出し、あなたは家に戻ります。
さて、素人の例を続けて、いくつかの例外を見てみましょう。友人に電話したときに彼が家にいなかった場合、それは 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 接続がクローズされるのはいつですか? を参照してください。.