httpull connectについての認識


原文のリンク先:
http://www.blogjava.net/supercrsky/articles/247449.html
JDKのURLConnection接続Servletの問題に対して、ネット上では関連がありますが、ある一つまたはいくつかの問題を説明しただけで、FAQの方式で解決したもので、しかも比較的にばらばらです.今はこの種類の使用について本人のプロジェクトでの使用経験についてまとめました.
1:>URL要求のカテゴリ:
二つのクラスに分けて、GETとPOST要求.両者の違いは:
     a:)get要求は、静的ページを取得することができ、また、URLの文字列の後ろにパラメータを置いて、servletに渡すこともでき、
     b:postとgetの違いは、postのパラメータがURLの文字列に入るのではなく、http要求の本文に入れることです.
2:>URLConnectionの対象問題:
URLConnectionのオブジェクトは、以下のコードの例を示します.
//下のindex.jspは<servlet-mapping>でマッピングされます.
//一つのServlet(comp.quantanetwork.get Cient Data Servlet)
//このServletの注意点は以下の通りです.
URL url = new URL("http://localhost:8080/TestHttpURLConnectionPro/index.jsp"); 

URLConnection rulConnection = url.openConnection();//    urlConnection        URL  
          //     (   http)   URLConnection  
          //    HttpURLConnection,          
          //  HttpURLConnection     ,     
          // HttpURLConnection   API.  : 

HttpURLConnection httpUrlConnection = (HttpURLConnection) rulConnection; 
3:>HttpURLConnectionオブジェクトパラメータ問題
//      httpUrlConnection  ,     post  ,      
// http   ,      true,       false; 
httpUrlConnection.setDoOutput(true); 

//      httpUrlConnection  ,      true; 
httpUrlConnection.setDoInput(true); 

// Post          
httpUrlConnection.setUseCaches(false); 

//                java   
// (      ,         , WEB               java.io.EOFException) 
httpUrlConnection.setRequestProperty("Content-type", "application/x-java-serialized-object"); 

//         "POST",   GET 
httpUrlConnection.setRequestMethod("POST"); 

//   ,    2  url.openConnection()         connect    , 
        httpUrlConnection.connect(); 
4:>  HttpURLConnection接続問題:
//   getOutputStream      connect( :       connect()  , 
//             connect()   )。 
OutputStream outStrm = httpUrlConnection.getOutputStream(); 
5:>HttpURLConnectionデータの書き込みとデータ送信の問題:
//                   ,            。 
ObjectOutputStream objOutputStrm = new ObjectOutputStream(outStrm); 

//           ,              
objOutputStrm.writeObject(new String("      ")); 

//        ,             (   ObjectOutputStream) 
objOutputStm.flush(); 

//      。  ,               ,                , 
//       getInputStream()         http           
objOutputStm.close(); 

//   HttpURLConnection     getInputStream()  , 
//               HTTP          。 
InputStream inStrm = httpConn.getInputStream(); // <===  ,               

//    httpConn.getInputStream()     ,  HTTP     ,               , 
//            close()  ,                    . 
//   ,                、     、       、     、 
//       (                 ) 
objOutputStm.writeObject(new String("")); 
httpConn.getInputStream(); 
まとめ:a:)HttpURLConnectの関数は、実際にサーバーとのtcp接続を確立しただけで、http要求を実際に送っていません.
    postであれgetであれ、httpは実際にHttpURLConnectionのget InputStream()という関数の中に正式に発送するように要求します.
       b:)URL要求をPOST方式で送信する場合、URL要求パラメータの設定順序は、重複の中の重さであり、
    connectionオブジェクトのすべての配置(その一山のset関数)
    いずれもconnect()関数が実行される前に完了しなければなりません.OutputStreamに対する書き込み操作は、inputStreamの読み取り操作の前にしなければならない.
    これらの順序はhttp要求のフォーマットによって決定される.
    inputStream読み取り操作がoutputStreamの書き込み操作前に例外を投げます.
    java.net.Protocol Exception:Canot write output after reading input…
      
       c:)http要請は実際に二つの部分から構成されています.
    一つはhttpヘッダで、今回http要求に関する配置は全部httpヘッダで定義されています.
           一つは本文contentです.
    connect()関数は、HttpURLConnectオブジェクトの設定値に基づいてhttpヘッダ情報を生成しますので、connect関数を呼び出す前に、
    すべての配置を準備しなければなりません.
       d:)httpヘッダの後ろに続くのはhttp要求の本文であり、本文の内容はoutputStreamを通じて書かれています.
    実際には、OutputStreamはネットワークストリームではなく、最大文字ストリームであり、中に書き込んだものはすぐにネットワークに送られません.
    メモリバッファに存在し、outputStreamストリームがオフされると、入力された内容に応じてhttp本文が生成されます.
    これでhttpが要請したものは全部準備ができました.get InputStream()関数が呼び出されると、準備したhttpを要求します.
    正式にサーバに送信した後、今度のhttp要求に対するサーバの戻り情報を読み出すための入力ストリームに戻る.httpのために
    要求はget InputStreamの時に発送されました.(httpヘッダと本文を含む)ので、get InputStream()関数
    その後、connectionオブジェクトを設定(httpヘッダの情報を修正)したり、outputStreamに書き込む(本文を修正する)
    これらの操作を実行すると異常が発生します.
6:>>Servlet端の開発注意点:
a:)クライアントから送信されるPOSTタイプのHTTP要求に対しては、Servletは、doPost方法を実装しなければならず、doGet方法を使用することができない.
b:HttpServletRequestのgetInputStream()方法でInputStreamのオブジェクトを取得する.
     InputStream inStream=httpRequest.get Input Stream()
     現在、instream.availableを呼び出します.この方法は「この入力フローに戻って次の方法で起動しても大丈夫です.
     ストリームから読み出し(またはスキップ)した推定バイト数」を入力すると、常に0に戻ります.この方法の戻り値を使用してバッファを割り当てることを試みました.
     このストリームのすべてのデータを保存する方法は正しくありません.じゃ、今の解決方法は?
     Servletのこの一端は以下のように実現される.
     InputStream inStream=httpRequest.get Input Stream()
     Object InputStream objInStream=new Object InputStream;
     Object obj=objInStream.readObject()
    //後続の処置をする
    //......
    //... ...
     クライアントは、実際のデータを送信するかどうかに関わらず、オブジェクトを書き込みます.
     Object OutputStream OutputStrm=new Object OutputStream;
     ObjOutputStrm.writeObject(new String)//ここで空のデータを送ります.
    //nullオブジェクトを一つ送ることもできます.サービスを取ってから判断処理をします.
     OutputStrm.writeObject(null);
     OutputStrm.flush();
     OutputStm.close()
なお、上記では、オブジェクト出力ストリームObject OutputStreamを作成する際に、HttpServletRequestから取得する入力ストリームが
      (すなわち、new Object OutputStream(outStrm)のoutStrm)はBufferedOutput Stream流に包装され、
      がある必要があります.この文は、バッファ出力ストリームにストリーム情報を取り込むために使用されます.
      Object OutputStream OutputStrm=new Object OutputStream(new BufferedOutput Stream);
      OutputStrm.writeObject(null);
      objOutputStrm.flush()/<======ここにあるべきです
      OutputStm.close()
HttpURLConnectionはHTTPプロトコルに基づいており、その下の層はsocket通信によって実現される.タイムアウトが設定されていないと、ネットワーク異常の場合、プログラムがダウンして実行されなくなる恐れがあります.以下の2つの文で対応するタイムアウトを設定できます.
System.set Property(「sun.net.client.default ConnectTimeout」、タイムアウトミリ秒数文字列);
System.set Property(「sun.net.client.default ReadTimeout」、タイムアウトミリ秒数文字列);
内訳:sun.net.client.default ConnectTimeout:ホストと接続するタイムアウト時間(単位:ミリ秒)
sun.net.client.default ReadTimeout:ホストからデータを読み出すタイムアウト時間(単位:ミリ秒)
たとえば:
System.set Property(「sun.net.client.default Connect Timeout」、「30000」);
System.set Property(sun.net.client.default ReadTime)
Javaでは、HttpURLConnectionを使用して、WEBリソースを要求することができる.
HttpURLConnectionオブジェクトは直接構成できません.URL.openConnectionを通じてHttpURLConnectionオブジェクトを獲得する必要があります.例のコードは以下の通りです.
String szUrl = "http://www.ee2ee.com/";
URL url = new URL(szUrl);
HttpURLConnection urlCon = (HttpURLConnection)url.openConnection(); 
HttpURLConnectionはHTTPプロトコルに基づいています.その下の階はsocket通信により実現されます.タイムアウトを設定しないと、ネットワーク異常の場合、プログラムがデッドダウンして実行できなくなる可能性があります.以下の2つの文で対応するタイムアウトを設定できます.
System.set Property(「sun.net.client.default ConnectTimeout」、タイムアウトミリ秒数文字列);
System.set Property(「sun.net.client.default ReadTimeout」、タイムアウトミリ秒数文字列);
内訳:sun.net.client.default ConnectTimeout:ホストと接続するタイムアウト時間(単位:ミリ秒)
sun.net.client.default ReadTimeout:ホストからデータを読み出すタイムアウト時間(単位:ミリ秒)
たとえば:
System.set Property(「sun.net.client.default Connect Timeout」、「30000」);
System.set Property(「sun.net.client.default ReadTimeout」、「30000」)
JDK 1.5以前のバージョンは、これらの2つのシステム属性を設定することにより、ネットワークのタイムアウトを制御することができます.1.5では、HttpURLConnectionの親タイプURLConnectionの次の2つの方法が使用されます.
set Connect Timeout:接続ホストタイムアウトを設定する(単位:ミリ秒)
set ReadTimeout:ホストからデータを読み出すタイムアウトを設定する(単位:ミリ秒)
たとえば:
HttpURLConnection urlCon = (HttpURLConnection)url.openConnection();
urlCon.setConnectTimeout(30000);
urlCon.setReadTimeout(30000); 
注意したいのは、JDK 1.4.2環境下で、default ReadTimeoutが設定されている場合、ネットワークのタイムアウトが発生したら、HttpURLConnectは自動的に再度要求を提出し、一回の呼び出しを要求し、サーバーに二回の問題が発生します.JDK 1.4.2のバグだと思います.JDK 1.5.0では、この問題はすでに解決されました.自動再送はありません.out'、'30000');