POST データを再読み取りするための Liberty Web アプリケーションの構成

Web アプリケーションは、入力ストリーム、リーダー、または解析対象パラメーターを使用して、有効範囲内の要求のポスト・データを再読み取りできます。 この再読み取り動作を使用するように Web コンテナー・プロパティーを設定します。

始めに

Java™ サーブレット仕様により、Web アプリケーションは、入力ストリーム、リーダー、または解析済みパラメーターを使用して、要求の POST データを読み取ることができます。 ただし、ポスト・データを読み取る際、要求の適用範囲内で Web アプリケーションが使用できるのはこれらの方法のうち 1 つのみです。

Web コンテナー・プロパティーを設定すると、Web アプリケーションはポスト・データを複数回再読み取りすることができます。 ただし、新しい読み取り操作を開始する前に、リーダーまたは入力ストリームをいったん閉じて読み取り操作を完了する必要があります。 リーダーまたは入力ストリームを閉じる前にデータが完全に読み取られている必要はありません。 データの部分読み取りを完了できます。 解析対象パラメーターの場合、Web コンテナーはポスト・データ全体を読み取り、すべてのパラメーターの解析が完了してから読み取り操作を閉じます。

アプリケーションは、ポスト・データのノンブロッキング再読み取りに対応します。 例えば、非同期読み取りリスナー (AsyncReadListener) を使用し、閉じる動作の後ブロッキング読み取りを行うことで、アプリケーションはノンブロッキング読み取りを行うことができます。 また、例えば、非同期読み取りリスナーを使用してノンブロッキング読み取りを行い、閉じる動作を行って、その後新しい非同期読み取りリスナーを使用して 2 回目のノンブロッキング読み取りを行うこともできます。

アプリケーションがノンブロッキング読み取りを使用して引き続きポスト・データの読み取りを行う場合、サーバーは直前に読み取りを行ったデータを最初に提供します。 前回実行された読み取り時に要求で送信されたポスト・データの一部が読み取られていなかった場合、アプリケーションが残りのポスト・データを読み取る際に新規読み取りはブロックを行います。

このタスクについて

web コンテナーのプロパティーを true に設定します。 次に、ポスト・データを再読み取りできる Web アプリケーションを実行します。 例を示しています。

手順

  1. ポスト・データの再読み取りを使用可能にします。

    server.xml ファイルで enablemultireadofpostdata カスタム・プロパティーを true に設定すると、カスタム・プロパティーはサーバー・レベルで設定されます。 再読み取り動作は、サーバー上のすべての Web アプリケーションに適用されます。 再読み取りの動作を特定の Web アプリケーションに適用する場合は、 web.xml ファイルで com.ibm.ws.webcontainer.SET_MULTI_READ_WEBAPP コンテキスト・パラメーターを true に設定します。 特定の Web アプリケーションにおいて、Web アプリケーション・レベルの設定はサーバー・レベルの設定をオーバーライドします。

    enablemultireadofpostdata カスタム・プロパティーと com.ibm.ws.webcontainer.SET_MULTI_READ_WEBAPP コンテキスト・パラメーターの両方とも、デフォルトは false です。

    この動作をサーバー・レベルで使用可能にするには、以下のステートメントを server.xml ファイルに追加してください。
    <webContainer enablemultireadofpostdata="true" />
    この動作を Web アプリケーション・レベルで使用可能にするには、以下の context-param ステートメントを web.xml ファイルに追加してください。
                    
    <context-param>                 
        <param-name>com.ibm.ws.webcontainer.SET_MULTI_READ_WEBAPP</param-name>                    
        <param-value>true</param-value>                
    </context-param>
  2. ポスト・データを再読み取りできる Web アプリケーションを実行します。

ブロッキング読み取りの例

以下のステップとコードのスニペットは、アプリケーションが getInputStream () メソッド、getParameter () メソッド、および getReader () メソッドを使用してポスト・データを再読み取りする方法を示しています。 ただし、これらのメソッドはアプリケーション内でどのような組み合わせでも使用できます。
  1. getInputStream () メソッドを使用して入力ストリームを取得します。
  2. データを読み取ります。
  3. 入力ストリームを閉じます。
  4. getInputStream () メソッドを使用して新規入力ストリームを取得します。
  5. データを読み取ります。
  6. 入力ストリームを閉じます。
  7. getParameter () メソッドを使用してパラメーターを取得します。
  8. getReader () メソッドを使用してリーダーを取得します。
  9. データを読み取ります。
  10. リーダーを閉じます。
  11. getParameter () メソッドを使用してパラメーターを再度取得します。

          java.io.InputStream in = request.getInputStream();
          byte[] inBytes = new byte[5];

          int readLen = in.read(inBytes);
          if (readLen > 0){
		
	     }              
          if (close)
                in.close();
	
	  java.io.InputStream in2 = request.getInputStream();
          byte[] inBytes = new byte[2048];

          for (int n; (n = in2.read(inBytes, 0, 2048)) != -1;) {
                readLen += n;
          }
          if (close)
                in2.close();

	  String param = request.getParameter("Test");
		
	  java.io.BufferedReader rdr = request.getReader();         
          StringBuffer inBuffer = new StringBuffer();
          char[] inChars = new char[1024];
          for (int n; (n = rdr.read(inChars,0,1024)) != -1;) {
             inBuffer.append(new String(inChars, 0, n));
          }
          rdr.close();

	  String param2 = request.getParameter("Test");

ノンブロッキング読み取りの例

以下のステップとコードのスニペットは、アプリケーションが getInputStream () メソッドおよび getParameter () メソッドを使用してポスト・データを再読み取りする方法を示しています。 ただし、これらのメソッドはアプリケーション内でどのような組み合わせでも使用できます。
  1. getInputStream () メソッドを使用して入力ストリームを取得します。
  2. setReadListener () メソッドを使用してサーブレット入力ストリームからリスナーを取得します。
  3. onDataAvailable () メソッドでデータを読み取ります。
  4. 入力ストリームを閉じます。

    入力ストリームが閉じた後、onAllDataRead () メソッドと onError () メソッドはこのリスナー用に呼び出されません。

  5. getParameter () メソッドを使用してパラメーターを取得します。
  6. getInputStream () メソッドを使用して新規入力ストリームを取得します。
  7. setReadListener () メソッドを使用してサーブレット入力ストリームから新規リスナーを取得します。
  8. onDataAvailable () メソッドでデータを読み取ります。
  9. すべてのデータを読み取る場合は、次にこのリスナー用に onAllDataRead () メソッドが呼び出されます。
        java.io.InputStream input = request.getInputStream();
	RL1 = ((ServletInputStream) input).setReadListener(readListener);
	
	RL1
	onDataAvailable(){

		if (input.isReady()) {
                         Len = input.read(inBytes);                 
                }
		input.close();

	        String param = request.getParameter("Test");

       	        java.io.InputStream input = request.getInputStream();
		RL2 = ((ServletInputStream) input).setReadListener(readListener);
	}

        RL1 // onAllDataRead() or onError() will not be called for RL1, as the stream has been closed for RL1
     
        RL2
        onDataAvailable(){

		if (input.isReady()) {
                        Len = input.read(inBytes);                 
               }

	 }
	
	 RL2 // If all data read
	 onAllDataRead(){
	 	 AsncContext.complete();
	 }