17.13非ブロックI/O
アプリケーションのウェブコンテナは、通常、クライアントリクエストごとにサービス側スレッドを割り当てます.拡張可能なWebアプリケーションを開発するには、関連要求のスレッドに空きがないことを確認し、ブロック操作の完了を待つ必要はありません.非同期処理は、新しいスレッドでブロック操作を処理するメカニズムを提供し、関連要求のスレッドをコンテナに返す.すべてのブロック操作がサービスメソッドで非同期で実行されても、関連クライアント要求のスレッドはinput/outputに基づいて一時的にアイドル状態になる可能性があります.例えば、クライアントが遅いネットワーク接続上で大きなHTTP POST要求を送信する場合、server読み取り要求の速度はクライアントがアップロードする速度よりずっと速い.TIOを使用すると、クライアントの要求の残りの部分を待つため、コンテナ関連要求のスレッドがアイドル状態になることがあります.JAVA EE非同期モード処理要求時にservletとfilterをサポートするNIOを提供する.次の手順では、サービス・メソッドでNIOを使用してリクエストを処理し、応答を書き出す方法をまとめます.
NIOサポートクラスjavax.servlet.ServeretInputStream
メソッド署名:void setReadListener(ReadListener rl)記述:入力ストリームをコールバックメソッドを含むリスナーオブジェクトに関連付けて、データを非同期で読み出す.提供されるリスナーオブジェクトは、匿名クラスであってもよいし、他のメカニズムを使用してリスナーオブジェクトに入力ストリームを入力してもよい.メソッド署名:boolean isReady()メソッド記述:データがブロックされていない場合はtrueメソッド署名を返します:boolean isFinished()メソッド記述:すべてのデータが読み込まれたらtrueを返します
NIOサポートクラスjavax.servlet.ServeretOutputStream
メソッド署名:void setWriteListener(WriteListener wl)メソッド記述:この出力ストリームをコールバックメソッドを含むリスナーオブジェクトに関連付けて、非同期でデータを書き込む.ライターオブジェクトを匿名クラスとして提供するか、他のメカニズムを使用してライターオブジェクトに出力ストリームを渡します.メソッド署名:boolean isReady()メソッド記述:データがブロックされていない場合はtrueを返します.
NIOリスナーサポートインタフェース
インタフェース名:ReadListenerインタフェースメソッド:void onDataAvailable()、void onAllDataRead()、void onError(Throwable t)記述:サーブレットInputStreamデータが有効に読み取れる場合、データの読み取りが完了し、エラーが発生した場合にListenerを呼び出す方法.インタフェース名:WriteListenerインタフェースメソッド:void onWritePossible()、void onError(Throwable t)記述:サーブレットOutputStreamデータがブロックされずに読み取ることができ、エラーが発生した場合にリスナーを呼び出すこれらのメソッド.
NIOを使用して大きなHTTP POST要求を読み込む
このセクションでは、servletオブジェクトで大きなHTTP POSTデータをどのように読み出し、要求を非同期モードに入れてNIO機能を使用するかを示します.
この例では、@WebServiceletコメントパラメータasyncSupported=trueを使用して、非同期のサポートを持つWeb Serviceletを宣言します.サービス・メソッドは、まず、非ブロックI/Oを使用するために必要な要求オブジェクトのstartAsync()メソッドを呼び出すことによって、非同期モードに要求を置く.次に、サービスメソッドは、要求に関連付けられた入力ストリームを取得し、内部クラスとして定義された読み出しリスナーを割り当てる.リスナーは、使用可能なときに要求の一部を読み出し、読み出し要求が完了すると、クライアントに応答の一部を書き込む.
1. Asynchronous Processing ,
2. service
3.
4.
NIOサポートクラスjavax.servlet.ServeretInputStream
メソッド署名:void setReadListener(ReadListener rl)記述:入力ストリームをコールバックメソッドを含むリスナーオブジェクトに関連付けて、データを非同期で読み出す.提供されるリスナーオブジェクトは、匿名クラスであってもよいし、他のメカニズムを使用してリスナーオブジェクトに入力ストリームを入力してもよい.メソッド署名:boolean isReady()メソッド記述:データがブロックされていない場合はtrueメソッド署名を返します:boolean isFinished()メソッド記述:すべてのデータが読み込まれたらtrueを返します
NIOサポートクラスjavax.servlet.ServeretOutputStream
メソッド署名:void setWriteListener(WriteListener wl)メソッド記述:この出力ストリームをコールバックメソッドを含むリスナーオブジェクトに関連付けて、非同期でデータを書き込む.ライターオブジェクトを匿名クラスとして提供するか、他のメカニズムを使用してライターオブジェクトに出力ストリームを渡します.メソッド署名:boolean isReady()メソッド記述:データがブロックされていない場合はtrueを返します.
NIOリスナーサポートインタフェース
インタフェース名:ReadListenerインタフェースメソッド:void onDataAvailable()、void onAllDataRead()、void onError(Throwable t)記述:サーブレットInputStreamデータが有効に読み取れる場合、データの読み取りが完了し、エラーが発生した場合にListenerを呼び出す方法.インタフェース名:WriteListenerインタフェースメソッド:void onWritePossible()、void onError(Throwable t)記述:サーブレットOutputStreamデータがブロックされずに読み取ることができ、エラーが発生した場合にリスナーを呼び出すこれらのメソッド.
NIOを使用して大きなHTTP POST要求を読み込む
このセクションでは、servletオブジェクトで大きなHTTP POSTデータをどのように読み出し、要求を非同期モードに入れてNIO機能を使用するかを示します.
@WebServlet(urlPatterns={"/asyncioservlet"}, asyncSupported=true)
public class AsyncIOServlet extends HttpServlet {
@Override
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws IOException {
final AsyncContext acontext = request.startAsync();
final ServletInputStream input = request.getInputStream();
input.setReadListener(new ReadListener() {
byte buffer[] = new byte[4*1024];
StringBuilder sbuilder = new StringBuilder();
@Override
public void onDataAvailable() {
try {
do {
int length = input.read(buffer);
sbuilder.append(new String(buffer, 0, length));
} while(input.isReady());
} catch (IOException ex) { ... }
}
@Override
public void onAllDataRead() {
try {
acontext.getResponse().getWriter()
.write("...the response...");
} catch (IOException ex) { ... }
acontext.complete();
}
@Override
public void onError(Throwable t) { ... }
});
}
}
この例では、@WebServiceletコメントパラメータasyncSupported=trueを使用して、非同期のサポートを持つWeb Serviceletを宣言します.サービス・メソッドは、まず、非ブロックI/Oを使用するために必要な要求オブジェクトのstartAsync()メソッドを呼び出すことによって、非同期モードに要求を置く.次に、サービスメソッドは、要求に関連付けられた入力ストリームを取得し、内部クラスとして定義された読み出しリスナーを割り当てる.リスナーは、使用可能なときに要求の一部を読み出し、読み出し要求が完了すると、クライアントに応答の一部を書き込む.