« ◇justとまだ、seeと見初める;言語の時間軸 | トップページ | WindowsXP/32bitからWindows7/64bitへダウングレード »

JavaでHTTP/HTTPSクライアント・サンプルプログラム

 JavaでHTTP/HTTPSクライアント・サンプルプログラム

HttpURLConnectionクラスを使えばHTTPクライアント、HTTPSクライアントを 差を意識することなく作成することができます。
接続先はurl形式(protocol://host:port/path?query)形式で与えます。

引数で指定されるアドレスにXML内容のPOSTを出すコードを以下に載せます。
落とし穴となる文字コードの指定を送信、受信とも行っています。

import java.io.*;
import java.net.*;
import java.util.*;
public class HttpClieTst{
   public static void main(String[]args_){
      String content="<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
                    +"<A><B>2</B></A>"; // 仮のPOST-body(XML)
      try{
         // アドレス設定、ヘッダー情報設定
         URL url = new URL(args_[0]);
         HttpURLConnection con = (HttpURLConnection)url.openConnection();
         con.setRequestMethod("POST");         // POSTまたはGET
         con.setDoOutput(true);              // POSTのデータを後ろに付ける
         con.setInstanceFollowRedirects(false);// 勝手にリダイレクトさせない
         con.setRequestProperty("Accept-Language", "jp"); 
         con.setRequestProperty("Content-Type","text/xml;charset=utf-8");
         con.connect();
         // 送信
         PrintWriter pw = new PrintWriter(new BufferedWriter(
                                    new OutputStreamWriter(
                                       con.getOutputStream()
                                       ,"utf-8")));
         pw.print(content);// content
         pw.close();       // closeで送信完了
         // body部の文字コード取得
         String contentType = con.getHeaderField("Content-Type");
         String charSet     = "Shift-JIS";//"ISO-8859-1";
         for(String elm : contentType.replace(" ", "").split(";")) {
            if (elm.startsWith("charset=")) {
                charSet = elm.substring(8);
                break;
                }
             }  
         // body部受信
         BufferedReader br;
         try{
            br = new BufferedReader(new InputStreamReader(
                                con.getInputStream(),charSet));
            }
         catch(Exception e_){
            System.out.println( con.getResponseCode()
                               +" "+ con.getResponseMessage() );
	    br = new BufferedReader(new InputStreamReader(
                                  con.getErrorStream(),charSet));
            }
         String line;
         while ((line = br.readLine()) != null) {
            System.out.println(line+"\n");
            }
         br.close();
         con.disconnect(); 
         }
      catch(Exception e){
         e.printStackTrace(System.err);
         System.exit(1);
         }
      System.exit(0);
      }
   }

接続先がhttpsの場合url.openConnection()が実際戻すクラスはHttpsURLConnection ですが、HttpURLConnectionの派生であるため、特に意識することなく使用できます。

HttpsURLConnectionを使った送受信ではデータは暗号化されますが、意識する必要 はありません。

POST-bodyを持たない場合は灰色の部分は不要です。
bodyがある場合con.setDoOutput(true);が必須ですので注意が必要です。

body部の文字コードをレスポンス・ヘッダから取得するには con.getHeaderField("Content-Type")で得た情報を 自力で解析する必要があります。
contentがXMLの場合、最初の行を読んで文字コードを切り替える手法も ありますが、確実ではありません。
文字コードは最も複雑で難しく混乱したものとなります。Content-Typeでshift-jis となっていながら、XML記述がencoding="UTF-8"となっていることもあります。

受信用ストリーム取得(con.getInputStream())は レスポンスコードが200以外の場合exceptionを投げ、ストリームを得る事が できません。
通常はexceptionをcatchし、con.getErrorStream()でストリームを改めて 取得します。

 補足

幾つか補足します。

connect(),disconnect()は必須ではありませんが、念のため付けておくことを 勧めます。

setInstanceFollowRedirects(false);指定が無い場合サーバが302など リダイレクト応答を返した場合、勝手にそちらを読みに行ってしまい 極めて混乱した結果となります。
この指定は必須です。

レスポンスヘッダの全項目はgetHeaderFields()で得ることができます。

         Map<String,List<String>> headers = con.getHeaderFields();
         for(String key:headers.keySet()){
            System.out.println(key + ":" + headers.get(key));
            }
getHeaderFields()で得られるのはStringのリストを内容とする辞書です。 キーはヘッダー要素名です。
getHeaderField()がStringで、 getHeaderFields()はStrtingリストとなっていることに注意が必要です。

HttpURLConnectionでなくHttpsURLConnectionを用いれば、暗号化に関わる 情報の取得なども可能です。
ただし、http接続の場合とのプログラム上でのかき分けが必要となるので 勧めません。

 build.xmlなど

このコードは実際に次のANT-build.xmlでビルド、実行しています。

<?xml version="1.0" encoding="UTF-8"?>
<project default="main">
   <target name="main" depends="build,run">
      <echo>=== BUILD and RUN done ===</echo>
   </target>
   <target name="build">
      <javac srcdir  ="."
             includes="*.java"
             includeAntRuntime="false"
             encoding="UTF-8"
             debug   ="yes"
             optimize="no" />
   </target>
   <target name="run">
      <java classname  ="HttpClieTst"
            classpath  ="."
            fork       ="true"
            failonerror="true">
            <!-- output="out.txt" error="err.txt" -->
         <arg line="https://ssltest2.verisign.co.jp/"/>
      </java>
   </target>
   <target name="clean">
      <delete dir="." includes="*.class,*.BAK"/>
   </target>
</project>

https://ssltest2.verisign.co.jp/はベリサイン社のHTTPS検証サイトです。
GETでもPOSTでも簡単な応答を返してくれます。 サンプルプログラムでは無意味なXMLを送っていますが、 無視してくれます
次のような応答が得られれば正常に動いています。

....
     [java] 当サイトにインストールされたサーバIDのルート認証局は<b>Class 3 Publi
c Primary Certification Authority</b>です。
     [java]
     [java] </p>
     [java]
     [java] <hr size="1">
     [java]
     [java] <font size="2">Copyright(c)<br>
     [java]
     [java] VeriSign Japan K.K.</font><br>
     [java]
     [java] </body>
     [java]
     [java] </html>
....
ただし、繰り返しアクセスすることは控えましょう。

なお、このbuild.xmlに関して単純ANTとJAVAメモ:幾つかの落とし穴回避のためのに説明があります。

 ダウンロード

ソースとビルドキットの入ったHttpClieTst.zipを置きます。
「右クリック-対象をファイルに保存」でダウンロードできます

展開すると次のファイルが得られます。

   HttpClieTst/
      A00_clean.bat
      A01_build.bat
      A05_run.bat
      A10_test.bat
      A90_release.bat
      AA00_clean.sh
      AA01_build.sh
      AA05_run.sh
      AA10_test.sh
      build.xml
      HttpClieTst.java
      README_UTF8.txt
      READEM_EUC.tzt
      README_SJIS.txt
      release.xml

.batと.shは単にantを呼んでいるだけです。
WindowsとLinuxで動作確認を行ってあります。

 ###

あまり沢山の要素を盛り込まない形のサンプルコードを作りたかったのですが 結局これが最低ラインだと思います。

日本語を諦めれば単純になります。エラー時に細かな内容を取らなければ単純になります。 そして実際の応用で嵌る事になります。

もちろんGETやbody無しのGETにして、bodyの受信をしないなどとすれば もっと単純化できます。そして役立たずのサンプルとなります。

|

« ◇justとまだ、seeと見初める;言語の時間軸 | トップページ | WindowsXP/32bitからWindows7/64bitへダウングレード »

トラックバック


この記事へのトラックバック一覧です: JavaでHTTP/HTTPSクライアント・サンプルプログラム:

« ◇justとまだ、seeと見初める;言語の時間軸 | トップページ | WindowsXP/32bitからWindows7/64bitへダウングレード »